OSGi integration not working in Vaadin 8.2.1

Hi,

I just tried to run a simple Hello World Vaadin app in an OSGi environment (I don’t use Karaf) and ended up with a ClassNotFoundException:

Caused by: java.lang.ClassNotFoundException: de.unia.smds.maf.web.gui.MyUI
 at java.net.URLClassLoader.findClass(Unknown Source)
 at java.lang.ClassLoader.loadClass(Unknown Source)
 at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
 at java.lang.ClassLoader.loadClass(Unknown Source)
 at org.eclipse.osgi.internal.framework.ContextFinder.loadClass(ContextFinder.java:132)
 at java.lang.ClassLoader.loadClass(Unknown Source)
 at com.vaadin.server.ServletPortletHelper.verifyUIClass(ServletPortletHelper.java:72)

My Setup is as follows:

  • I’m using BndTools 3.5 in Eclipse Oxygen
  • From Maven I get the following dependencies:
<dependency>
      <groupId>com.vaadin</groupId>
      <artifactId>vaadin-osgi-integration</artifactId>
      <version>8.2.1</version>
  </dependency>
  
  <dependency>
      <groupId>com.vaadin</groupId>
      <artifactId>vaadin-server</artifactId>
      <version>8.2.1</version>
  </dependency>
  
  <dependency>
      <groupId>com.vaadin</groupId>
      <artifactId>vaadin-themes</artifactId>
      <version>8.2.1</version>
  </dependency>
  
  <dependency>
      <groupId>com.vaadin</groupId>
      <artifactId>vaadin-client-compiled</artifactId>
      <version>8.2.1</version>
  </dependency>
  • I created a new Bnd OSGi project and configured my Buildpath like this:
-buildpath: \
 org.eclipse.xtend.lib,\
 org.eclipse.xtend.lib.macro,\
 org.eclipse.xtext.xbase.lib,\
 com.google.guava;version=18.0,\
 osgi.enroute.base.api,\
 com.vaadin.server;version=8.2,\
 org.jsoup;version=1.8,\
 com.vaadin.external.gentyref;version=1.2,\
 com.vaadin.client-compiled;version=8.2,\
 com.vaadin.shared;version=8.2,\
 com.vaadin.themes;version=8.2
  • Then I created the two classes MyUI and MyUIServlet
public class MyUI extends UI {
  @Override
  protected void init(final VaadinRequest request) {
    Label _label = new Label("Hello World");
    this.setContent(_label);
  }
}

@Component(service = VaadinServlet.class, property = { (HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN + "=/hello") })
@VaadinServletConfiguration(ui = MyUI.class, productionMode = false)
@SuppressWarnings("all")
public class MyUIServlet extends VaadinServlet {
}

When I try to access the UI at http://localhost:8080/hello I receive the above mentioned exception.

Am I missing something here?

Kind regards,
Thomas

Hi Tatu,

I now annotated both with @Component(…), but I still get the same error.

One way how I got it to show at least the UI is to switch from felix.http to pax.web … I don’t know what the differences are but with pax.web there are no more ClassNotFoundExceptions.

But now it immediatly looses connection after creating the UI and then tries to reconnect the whole time.

Can you tell me in what setting you test your implementation, so that I could recreate it for my setup?

Kinf regards,
Thomas

I think you need @Component(service = UI.class, name = “MyUI”) or something like that for your UI class as well.

I tried another approach and merged the
example of Peter Kriens
and the
current work of Mirjan Merruko
into a semi-working example which can be found in
my GitHub repository
.

The UI is shown initially, but then I get again a ClassNotFoundException, but this time not for the UI but for a AppWidgetset. Additionally, the UI seems to loose connection to the server immediatly after the first load. When I open the app in debug mode (?debug) then the log says:

261ms First response processed 969 ms after fetchStart
262ms Processing time was 39ms
263ms Referenced paintables: 3
302ms RPC invocations to be sent to the server:
303ms   3 (class com.vaadin.client.ui.ui.UIConnector) :
304ms      com.vaadin.shared.ui.ui.UIServerRpc.resize([2560, 1260, 2560, 1260]
)
306ms Sending xhr message to server: {"csrfToken":"e4b9ccd4-e20f-415d-9eda-52191c3f650d","rpc":[["3","com.vaadin.shared.ui.ui.UIServerRpc","resize",[2560,1260,2560,1260]
]],"syncId":0,"clientId":0,"wsver":"8.2.1"}
322ms Server returned 404 for xhr
325ms Reconnecting because of XHR failure
326ms Reconnect attempt 1 for XHR
328ms Re-sending last message to the server...
329ms Sending xhr message to server: {"csrfToken":"e4b9ccd4-e20f-415d-9eda-52191c3f650d","rpc":[["3","com.vaadin.shared.ui.ui.UIServerRpc","resize",[2560,1260,2560,1260]
]],"syncId":0,"clientId":0,"wsver":"8.2.1"}

Any advice is highly appreciated!

Kind regards,
Thomas

Update ClassNotFoundExcpetion:

The Vaadin BootstrapHandler tries to get a WidgetsetInfo in its setupMainDiv method, which calls the getWidgetsetInfo method of UIProvider, which in turn tries to load the class “AppWidgetset”. According to the comments in UIProvider.findWidgetsetClass(), a ClassNotFoundException is a normal case, so I will just throw this Exception in my custom ClassLoader whenever it is asked for this class.

Update lost connection:

The lost connection seems to stem from false urlPatterns for UIs. After the initial load of an UI that is registered under localhost:8080/test Vaadin sends XHR requests for each interaction (e.g. resizing, clicks, etc.) to the server. The path for these requests are always in form of /UIDL/?.. In our case this would be localhost:8080/test/UIDL. If there is no servlet registered for this path, the Vaadin client receives a malformed response and displays a popup that says: Connection lost… . I fixed this issue in my example application by letting VaadinApplicationHandler change all urlPatterns of UIs to /*

I’m no expert in web development, so the workarounds might not be good. Any improvements for my solution are welcome :wink:

Hi,
I’ve created another OSGi integration for Vaadin, which enables users to use their UI classes as Declarative Services.

You can check out the code
here

Hi Thomas,

Can you attach your hello world project here or add a link to github so I can take a look at it if I get some time in a week or two?

BR,
Mirjan

Hi Mirjam,

you can find the Code in my GitHub repository: https://github.com/Sandared/vaadin8integration

Kind regards,
Thomas

Hi Mirjan,

I also added a OSGi Vaadin ResourceTracker to the example, as the current solution is not working when I try to add resources that are not within my own bundle. I f you want to add a Resource/Widgetset/Theme to Vaadin you now can just add one of the following lines to your manifest:

OSGiVaadin-Resource: VAADIN/path/to/my/resource
OSGiVaadin-Theme:VAADIN/path/to/my/theme
OSGiVaadin-Widgetset:VAADIN/path/to/my/widgetset

If used in an OSGi environment the tracker then finds those bundles and registers their resources with a sepcial HttpContext Object at the HttpService.

In the repository I did this with the Chart.js addon for Vaadin, where I changed its Manifest.

This way you can also use non OSGiyfied addons, just by adding this line to their manifest, Which is a lot easier than adding a new Class/Component to their sourcecode.

Kind regards,
Thomas

Hi Mirjan,

did you have some spare time to have a look at my solution?

Kind regards,
Thomas

Hi Thomas,

I’m sorry for the late reply, I’ve been quite busy and only now I had the chance to look at the issue.

The logic of this OSGi integration is that a Vaadin developer will easily convert an existing Vaadin application to a Vaadin application that can be deployed on OSGi. For example it’s common practice that if you have a theme in your project extending Valo and you need to use constants for the style names you would have a class extending ValoTheme and store the constants there. The same goes for the VaadinServlet which can be annotated with Component and be ready for OSGi (I’m trying to find time to make it possible as well to use UIs as DS in my fork of the framework as you mentioned).

In regards to your findings I would say that it’s incorrect to hardcode the check “AppWidgetset” and check it through the class loader. I don’t know why that request happens, but it might indicate a packaging error or an error in dependencies in my opinion. Other than that I couldn’t look more at the example by Peter Kriens, unfortunately when I was trying to contribute something in the OSGi integration I wasn’t aware of it even though it has existed before I did any work on it and in my opinion is more sophisticated than the solution I made.

It could serve as an alternative add-on in my opinion for use with OSGi, and perhaps your approach bridging parts of the two is the right way to go, I really liked your addition for declaring themes and widgetsets. You can work on your integration futher and publish it as an addon in the Vaadin directory, or make pull requests in the framework repository to improve parts of the existing integration.

Part of your findings seem like a legitimate bug when it comes to the use of the addon with felix. My understanding is that when registering a servlet through pax web it takes into account the Servlet pattern as found in the annotation of the Servlet and configures it, something that felix doesn’t seem to consider. The vaadin-osgi-integration add-on/module doesn’t consider this and it’s something that can and should be fixed. After adding that in place I could run a simple helloworld through bndtools and felix (though I couldn’t get push to work because of missing dependencies). So thank you for pointing this out.

Let me know if I can do something more I can do for solving this.

Hi Mirjan,

Noticed the changes you have made to OSGi integration in your Github repo. It is marked for Vaadin 8.5.
Will it make it into 8.5 as it is not included in the alpha1 version.

Also, in your previous posting to Thomas you mentioned a problem with push. Is this sorted in your improvements?

Hi Paul, hi Mirjan,

sorry for this long delay, but it seems I completely missed your answer Mirjan and at work our focus switched so I didn’t push my solution further.

I think I’ve found a solution back then that even took care of compiling custom themes on the fly. I hopefully find some spare time in the coming weeks and will try to add my solution as an addon as Mirjan recommended.

Kind regards,
Thomas