Hello,
I work on a project that utilizes a plain Java application that launches an embedded Jetty web server which then launches several instances of the Equinox Servlet bridge. As I was debugging some code I noticed that Syserr was not being printed out to the console at all but Sysout was working just fine. I added the following code to the startup() method of one of my immediately activated components within one of the servlet bridge instances:
new Timer().schedule(new TimerTask() {
@Override
public void run() {
System.out.println(System.err);
System.err.println("Works");
}
}, 0, 1000);
The following is the output of the test:
java.io.PrintStream@5ba91eec
Works
java.io.PrintStream@5ba91eec
Works
org.apache.felix.gogo.runtime.threadio.ThreadPrintStream@5bc44dd2 <---Change 1
Works
org.apache.felix.gogo.runtime.threadio.ThreadPrintStream@5bc44dd2
Works
Works
org.apache.felix.gogo.runtime.threadio.ThreadPrintStream@5bc44dd2
Works
org.apache.felix.gogo.runtime.threadio.ThreadPrintStream@5bc44dd2
org.apache.felix.gogo.runtime.threadio.ThreadPrintStream@5bc44dd2
Works
org.apache.felix.gogo.runtime.threadio.ThreadPrintStream@5bc44dd2
Works
org.apache.felix.gogo.runtime.threadio.ThreadPrintStream@310031be <---Change 2
Works
org.apache.felix.gogo.runtime.threadio.ThreadPrintStream@41d5df31 <---Change 3
org.apache.felix.gogo.runtime.threadio.ThreadPrintStream@41d5df31
org.apache.felix.gogo.runtime.threadio.ThreadPrintStream@32a8ee87 <---Change 4
org.apache.felix.gogo.runtime.threadio.ThreadPrintStream@32a8ee87
org.apache.felix.gogo.runtime.threadio.ThreadPrintStream@32a8ee87
org.apache.felix.gogo.runtime.threadio.ThreadPrintStream@32a8ee87
org.apache.felix.gogo.runtime.threadio.ThreadPrintStream@32a8ee87
org.apache.felix.gogo.runtime.threadio.ThreadPrintStream@32a8ee87
I noticed that the PrintStream that was set on System.err eventually changes to the Felix GoGo ThreadPrintStream which is to be expected since I am using Felix GoGo for my OSGI console.
The first issue I see is that the instance of ThreadPrintStream that is set changes three times. Looking at the source for org.apache.felix.service.threadio.ThreadIO.ThreadIOImpl I noticed this method:
final ThreadPrintStream err = new ThreadPrintStream(this, System.err, true);
final ThreadPrintStream out = new ThreadPrintStream(this, System.out, false);
final ThreadInputStream in = new ThreadInputStream(this, System.in);
public void start()
{
if (System.out instanceof ThreadPrintStream)
{
throw new IllegalStateException("Thread Print Stream already set");
}
System.setOut(out);
System.setIn(in);
System.setErr(err);
}
Normally the if statement would trigger and prevent a new ThreadPrintStream from being set but this is not the case. The issue is that the class of the ThreadPrintStream instance stored in System.out is not the same class as the current ThreadPrintStream. This is due to the fact that the ThreadPrintStream class is loaded in different class loaders as I fire up new instances of the Equinox servlet bridge under Jetty. This causes a new ThreadPrintStream to be set each time I launch an instance of the Equinox servlet bridge.
The real issue is that after the third change of the PrintStream in System.err I loose all Syserr in the servlet. I am assuming that the issue is somehow related to the changing instance of ThreadPrintStream but I do not have any direct evidence for this yet.
I have tried reverting to the built in console using the property
[code]
osgi.console.enable.builtin=true
[\code]
but this just results in the following error:
!ENTRY org.eclipse.osgi 4 0 2014-10-22 16:03:02.783
!MESSAGE Could not find bundle: unknown
!STACK 0
org.osgi.framework.BundleException: Could not find bundle: unknown
at org.eclipse.core.runtime.internal.adaptor.ConsoleManager.checkForConsoleBundle(ConsoleManager.java:58)
at org.eclipse.core.runtime.adaptor.EclipseStarter.startup(EclipseStarter.java:333)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.eclipse.equinox.servletbridge.FrameworkLauncher.start(FrameworkLauncher.java:411)
at org.eclipse.equinox.servletbridge.BridgeServlet.init(BridgeServlet.java:83)
at javax.servlet.GenericServlet.init(GenericServlet.java:244)
at org.eclipse.jetty.servlet.ServletHolder.initServlet(ServletHolder.java:582)
at org.eclipse.jetty.servlet.ServletHolder.initialize(ServletHolder.java:372)
at org.eclipse.jetty.servlet.ServletHandler.initialize(ServletHandler.java:847)
at org.eclipse.jetty.servlet.ServletContextHandler.startContext(ServletContextHandler.java:300)
at org.eclipse.jetty.webapp.WebAppContext.startWebapp(WebAppContext.java:1359)
at org.eclipse.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1352)
at org.eclipse.jetty.server.handler.ContextHandler.doStart(ContextHandler.java:744)
at org.eclipse.jetty.webapp.WebAppContext.doStart(WebAppContext.java:497)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:125)
at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:107)
at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:60)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:125)
at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:107)
at org.eclipse.jetty.server.handler.AbstractHandler.doStart(AbstractHandler.java:60)
at org.eclipse.jetty.server.handler.ScopedHandler.doStart(ScopedHandler.java:120)
at org.eclipse.jetty.server.handler.ContextHandler.startContext(ContextHandler.java:785)
at org.eclipse.jetty.server.handler.ContextHandler.doStart(ContextHandler.java:744)
at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:125)
at org.eclipse.jetty.util.component.ContainerLifeCycle.addBean(ContainerLifeCycle.java:289)
at org.eclipse.jetty.util.component.ContainerLifeCycle.addBean(ContainerLifeCycle.java:221)
at org.eclipse.jetty.util.component.ContainerLifeCycle.updateBeans(ContainerLifeCycle.java:771)
at org.eclipse.jetty.server.handler.HandlerCollection.setHandlers(HandlerCollection.java:89)
at org.eclipse.jetty.server.handler.ContextHandlerCollection.setHandlers(ContextHandlerCollection.java:144)
at org.eclipse.jetty.server.handler.HandlerCollection.addHandler(HandlerCollection.java:155)
at com.xmlnamespace.panel.server.deployment.ServerDeploymentManager.deployServer(ServerDeploymentManager.java:328)
at com.xmlnamespace.panel.server.deployment.ServerDeploymentManager.startCommunicationManager(ServerDeploymentManager.java:251)
at com.xmlnamespace.panel.server.Server.main(Server.java:330)
I feel that this is a bug in the Felix GoGo implementation but I am not sure if I should file a bug report with Equinox or Felix. Any help with this issue would be greatly appreciated as this is causing me quite the headache.
The following is a list of jars that make up the Equinox servlet bridge:
org.apache.felix.gogo.command_0.10.0.v201209301215.jar
org.apache.felix.gogo.runtime_0.10.0.v201209301036.jar
org.apache.felix.gogo.shell_0.10.0.v201212101605.jar
org.eclipse.equinox.cm_1.1.0.v20131021-1936.jar
org.eclipse.equinox.common_3.6.200.v20130402-1505.jar
org.eclipse.equinox.console_1.1.0.v20140131-1639.jar
org.eclipse.equinox.ds_1.4.200.v20131126-2331.jar
org.eclipse.equinox.http.registry_1.1.300.v20130402-1529.jar
org.eclipse.equinox.http.servlet_1.1.500.v20140318-1755.jar
org.eclipse.equinox.http.servletbridge_1.0.300.v20130327-1442.jar
org.eclipse.equinox.preferences_3.5.200.v20140224-1527.jar
org.eclipse.equinox.registry_3.5.400.v20140428-1507.jar
org.eclipse.equinox.util_1.0.500.v20130404-1337.jar
org.eclipse.osgi_3.10.0.v20140606-1445.jar
org.eclipse.osgi.services_3.4.0.v20140312-2051.jar