Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 361110

Summary: Deserializing sessions does not work in OSGi
Product: [RT] Jetty Reporter: Rüdiger Herrmann <ruediger.herrmann>
Component: osgiAssignee: Jan Bartel <janb>
Status: CLOSED WORKSFORME QA Contact:
Severity: normal    
Priority: P3 CC: gregw, janb, jetty-inbox
Version: 8.0.2   
Target Milestone: 8.1.x   
Hardware: All   
OS: All   
Whiteboard:
Bug Depends on:    
Bug Blocks: 353117    
Attachments:
Description Flags
Stacktrace none

Description Rüdiger Herrmann CLA 2011-10-17 05:15:35 EDT
Currently it seems not possible to use Jetty in OSGi when session failover is enabled.
We have Jetty embedded and configured to use JDBCSessionIdManager and JDBCSessionManager. In the case of a fail-over, when a session is deserialized, a ClassNotFoundException occurs. As far as we understand, this is caused by the ClassLoadingInputStream that uses Class.forName with contextClassLoader to load classes. 
Though in therory it would be possible to set a contextClassLoader, we don't see a place where to actually set an OSGi-aware class loader. 

Under the above assunptions, we suggest to allow to set a custom class loader on the servlet context, that is used whenever a session that belongs to the context is deserialized.
Application code (or framework code in our case) could call:
  servletContext.setAttribute( "org.eclipse.jetty.serialization.classLoader", new CustomClassLoader() );
when the context is initialized (note: the attribute name is just a suggestion).
The ClassLoadingObjectInputStream would then use the above set CustomClassLoader to load classs during deserialization.
Comment 1 Hugues Malphettes CLA 2011-10-17 20:14:08 EDT
Hi there,
Jan tells me that the classloading uses this piece of java code:
return Class.forName(cl.getName(), false, Thread.currentThread().getContextClassLoader());

Where the thread's context classloader is the webapp's classloader.
It should behave as expected.

Could you share the stack trace and a way for us to reproduce the issue?
Comment 2 Jan Bartel CLA 2011-10-17 20:15:06 EDT
Hi Ruediger,

Can you paste the full stack trace?
Also, is this jetty-7 or jetty-8? Which release number?

This is a bit surprising to me, as I understood that our OSGi code will provide
a special, osgi-aware classloader to each webapp that is deployed. Thus, when
the Session is being re-inflated over on a new node, the context classloader
should already be set to this this special osgi-aware classloader, and thus
able to resolve the class reference. Perhaps seeing the stack trace will make
this clearer to me.

thanks
Jan
Comment 3 Rüdiger Herrmann CLA 2011-10-18 13:59:50 EDT
(In reply to comment #2)
> Also, is this jetty-7 or jetty-8? Which release number?
I am working with Jetty 8.0.2.SNAPSHOT from ~ 2011-10-14.

> This is a bit surprising to me, as I understood that our OSGi code will provide
> a special, osgi-aware classloader to each webapp that is deployed. Thus, when
> the Session is being re-inflated over on a new node, the context classloader
> should already be set to this this special osgi-aware classloader, and thus
> able to resolve the class reference. Perhaps seeing the stack trace will make
> this clearer to me.
I am sorry that I didn't realize that there is an OSGi integration for Jetty. I though the jetty.osgi.* just contained the HttpService. 
So my situation has changed: I am now going along the Jetty/OSGi doc [1] and try to register an instance of class Server as an OSGi service and then a ContextHandler.
When the Server is registered, I get an IllegalStateException: ERROR: No ContextHandlerCollection or OSGiAppProvider configured. I am unsure whether I really need both, a ContextHandlerCollection *and* an OSGiAppProvider. The code reads like 'yes I need both', the exception message says rather 'either or'.
Please note, I don't want to deploy a WAR or such. I want to programmatically start a server, create a context, register a servlet and then send some requests to that servlet.

Please let me know if I should use another place (new bug, mailing list) to solve the changed issue.

[1] http://wiki.eclipse.org/Jetty/Feature/Jetty_OSGi
Comment 4 Rüdiger Herrmann CLA 2011-10-18 14:01:29 EDT
Created attachment 205446 [details]
Stacktrace

Stacktrace of exception from comment #3
Comment 5 Hugues Malphettes CLA 2011-10-18 22:27:43 EDT
Hi Rüdiger, in order for a jetty server to be able to deploy web-apps it needs to be configured with an app provider.
For OSGi web bundles it needs an OSGiAppProvider.
Usually we use an xml file to configure a jetty server.
For example here is such a config file for OSGi:
http://git.eclipse.org/c/jetty/org.eclipse.jetty.project.git/tree/jetty-osgi/jetty-osgi-boot/jettyhome/etc/jetty-osgi-default.xml

In such a file, you can configure the session manager etc.

Once such a jetty server is configured in this manner, the jetty.osgi.boot bundle will take care of listening for new web-bundles and have them plugged in the OSGiAppProvider (maybe that is where we could take care of the lazy activation of jetty.osgi.boot with one extra parameter on the OSGiAppProvider to decide to activate or not the bundle).

If you are in the situation where you have a single jetty instance on your equinox and you are happy with a custom jetty.xml config file you could consider starting it in this manner:
- choose if you want to have your jetty.xml inside a bundle or in a separate folder.
- Setup the appropriate system property -Djetty.home.bundle=id.of.your.bundle
inside it, have a /etc/jetty.xml file
or if in a folder: -Djetty.home=path/to/jettyhome such that path/to/jettyhome/etc/jetty.xml exists.
- activate jetty.osgi.boot

In fact I stumbled on a blog that describes something eerily similar to your situation as far as I understand it:
http://eclipsesource.com/blogs/2011/08/12/how-to-build-a-cluster-with-jetty-osgi/


Let me know.
Comment 6 Hugues Malphettes CLA 2011-10-18 22:48:14 EDT
(In reply to comment #5) 
> In fact I stumbled on a blog that describes something eerily similar to your
> situation as far as I understand it:
> http://eclipsesource.com/blogs/2011/08/12/how-to-build-a-cluster-with-jetty-osgi/
Hum I must be missing something you guys are already collaborating on github!
Thanks for sharing with this blog post and the github project by the way.

My understanding is that you would like to have the same project work on jetty-8?
Let me know if I can help.
Correct me if it is a different situation.
Comment 7 Rüdiger Herrmann CLA 2011-10-19 04:23:04 EDT
Hi Hugues,

let me give you some context. Though the blog is from a colleague of mine, it is not directly related to the work I am doing.
We have a JUnit test suite for integrations tests of RAP. These tests ensure e.g. that session failover works. 

With these tests we developed helper classes to start an embedded Jetty server, deploy a web app and after test code was executed stop and clean up the server. The server runs in the same VM as the tests. All setup is done programmatically, the web app that is deployed is not WAR'ed or anything. Instead of having a web.xml we set up the web app programmatically. 
See JettyEngine [1] and JettyController [2] in case you want more details.

To test failover cluster scenarios, we can use the helper classes to create two or more server instances and have them form a cluster.

So far there is no OSGi involved. Since RAP runs on OSGi, the next logical step was to enable failover clustering on RAP in OSGi. Therefore we need to extend helper classes. The goal is to do the same as before (start server, deploy web app, stop server) while running on OSGi.

Our first approach was to just run the tests in OSGi. This brought us (via bug 358263) here, to the initial desription of the bug. But just then we noticed that Jetty comes with org.eclipse.jetty.osgi.boot to integrate into OSGi.

Now we are seeking advice which path to follow. 
option a) leave aside the Jetty/OSGi integration
This leads to the problem described here initially (and more problems down the path?)

option b) use the Jetty/OSGi integration. We went this path up to the missing OSGiAppProvider (comment #3). 
We use the same helper classes from the non-OSGi tests to create and configure a Server. When registering this instance as a service, we hit the "no app provider" exception (comment #4).
As far as I understand, the context file configures the server. The server instance that we register is already fully configured. Would it be worth trying to supply an OSGiAppProvider with an empty context file?
After the server is registered successfully, the next step would be to register a ServletContextHandler as described here [3].

[1] http://dev.eclipse.org/viewcvs/viewvc.cgi/org.eclipse.rap/runtime.rwt.test/org.eclipse.rap.rwt.cluster.testfixture/src/org/eclipse/rap/rwt/cluster/testfixture/internal/jetty/JettyEngine.java?view=markup&root=RT_Project
[2] http://dev.eclipse.org/viewcvs/viewvc.cgi/org.eclipse.rap/runtime.rwt.test/org.eclipse.rap.rwt.cluster.testfixture/src/org/eclipse/rap/rwt/cluster/testfixture/internal/jetty/JettyController.java?root=RT_Project&view=log
[3] http://wiki.eclipse.org/Jetty/Feature/Jetty_OSGi#The_OSGi_service_.27org.eclipse.jetty.server.handler.ContextHandler.27
Comment 8 Rüdiger Herrmann CLA 2011-10-19 04:27:48 EDT
I forgot to mention that this issue is about Jetty 8.
Comment 9 Rüdiger Herrmann CLA 2011-10-26 05:29:07 EDT
For your reference, we think this issues is related to bug 361554. As opposed to programmatically embedding Jetty as desribed here, bug 361554 points out that also a ClassNotFoundException occurs when using Jetty/OSGi as a standalone server in a cluster.
Comment 10 Jan Bartel CLA 2013-08-25 23:18:25 EDT
Hi Rüdiger,

I think since you opened bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=361554 this bug report is closeable. As you point out in the other bug, this bug report seems to discuss a number of different things, and there's nothing that I can clearly address as a bug.

I will close this issue for now (leaving 361554 open), but please reopen with a clear statement of the problem if you feel there is something here for me to address. 

regards
Jan