I'm being driven out of my mind by the following exception:
java.lang.IllegalArgumentException:
com.sun.xml.messaging.saaj.soap.LocalStrings != com.sun.xml.internal.messaging.saaj.soap.LocalStrings
at java.util.logging.Logger.getLogger(Logger.java:357)
at com.sun.xml.internal.messaging.saaj.soap.SAAJMetaFactoryImpl.<clinit>(SAAJMetaFactoryImpl.java:41)
It's occurring when I try to deploy a WAB (web application OSGi bundle) to Glassfish (3.1.1).
I'm trying to use an up-to-date version of SAAJ (com.sun.xml.messaging.saaj...) rather than the old JDK one (which is the com.sun.xml.internal.saaj... one), by putting the string com.sun.xml.messaging.saaj.soap.ver1_1.SOAPMessageFactory1_1Impl in the file META-INF/services/javax.xml.soap.MessageFactory.
It appears there is some logging going on before the OSGi classloading kicks in, and therefore the 'wrong' ResourceBundle is being returned during initialization of the static log field of com.sun.xml.messaging.saaj.soap.MessageFactoryImpl (SAAJ's implementation of javax.xml.soap.MessageFactory).
Anyone seen this / any workarounds on offer?
Never got to the bottom of this, but manifest voodoo eventually made it go away (with all of the javax.xml.ws / javax.ws.rs packages in Import-Package rather than on the bundle classpath WEB-INF/lib).
It was also possible to work around it by using
-Djavax.xml.soap.MessageFactory=com.sun.xml.messaging.saaj.soap.ver1_1.SOAPMessageFactory1_1Impl
on Glassfish startup, though obviously this forces that implementation on all users of MessageFactory.
See: JDK-6741342 : Logger.getLogger() throws java.lang.IllegalArgumentException on saaj classes.
Instead, it's related to the introduction of saaj into JDK 6.....and the workaround involved re-ordering jars.
Related
I'm trying to embed apache felix into a simple hello world java project with maven, but I can't find a way to get a reference to a service of a bundle. I've installed org.apache.felix.bundlerepository bundle into OSGi from a jar and also added it as a maven dependency to my project. After that I'm starting the bundle, getting BundleContext from it and then calling getServiceReference(RepositoryAdmin.class.getName()) on that bundle context. The first thing I'm unhappy with is that I have to use BundleContext from the installed bundle, if I'd use BundleContext of the Framework the ServiceReference will be always null. This is not convinient.
The second, more important issue, is that when I finally receiving a reference to RepositoryAdmin service from bundlerepository bundle I can't cast it to org.apache.felix.bundlerepository.RepositoryAdmin, executing the following code:
(RepositoryAdmin)admin.getBundleContext().getService(ref)
will throw this exception:
java.lang.ClassCastException: org.apache.felix.bundlerepository.impl.RepositoryAdminImpl cannot be cast to org.apache.felix.bundlerepository.RepositoryAdmin
I know this is a kind of classpath issue and may be caused by incompatibility of interfaces, but I'm using a bundle jar of the same version (2.0.2) as a maven dependency of my project.
I'm also aware of Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA osgi configuration option which should force a bundle to use a package from the host application, but it didnt help me.
Here is the main class of my project https://github.com/ArtemZ/osgi-study/blob/master/src/main/java/com/artemz/demo/Main.java which is messy because I was trying different things on it in order to get a reference to a service, but none actually worked for me.
Hope someone will help me, because I'm really desperate with this issue.
Thanks for giving some more details about what you are doing. I already followed the mails on the felix list.
Now I think I understand what happens. The reason why you can not get the service from outside the RepositoryAdmin bundle is that the package you define in
FRAMEWORK_SYSTEMPACKAGES_EXTRA is "org.apache.felix.bundlerepository; version=2.0.2"
is not the same version as the package from the RepositoryAdmin bundle. I downloaded the bundle and looked into the Manifest:
Export-Package: org.osgi.service.repository;version="1.0";uses:="org.osg
i.resource",org.apache.felix.bundlerepository;version="2.1";uses:="org.
osgi.framework"
So as you see the version you should export from the system bundle is 2.1 not 2.0.2.
In OSGi the versions are defined per package not on the bundle level. So while most times they are the same this is not always true. Espcecially for OSGi spec packages.
So when the package version are different you have two effects:
1. You will not be able to find a service with a different package
2. If you get a service object in some other way like you did then you will have a class cast exception as they are loaded by different classloaders.
So can you try the 2.1 version and report if it works?
When my code executes this line:
DefaultHttpClient httpclient = new DefaultHttpClient();
I'm getting this Exception:
org.apache.commons.logging.LogConfigurationException: Class org.apache.commons.logging.impl.Log4JLogger does not implement Log
does somebody know how can I solve that?
Maybe is not important (or maybe it is), but the app is a plugin for Jira, and is using Maven for the dependencies.
Thanks !
EDIT:
EDIT 2:
Could this be related with OSGi from Jira?
How can I use commons-logging in an OSGi environment?
From here:
http://wiki.apache.org/commons/Logging/FrequentlyAskedQuestions
Commons-logging was not designed with OSGi in mind. This is why it is
difficult to get commons-logging working in OSGi environments:
LogFactory loads Log implementations by name (see
Class.forName(String)). This is usually not possible in OSGi since
every bundle classloader can only see the classes a bundle defines
imports for. The bundle class loader that loads the commons-logging
bundle will not have access to user provided
commons-logging.properties files. commons-logging-api.jar contains
classes that are also included in commons-logging.jar. This is
contrary to traditional OSGi application architectures where one
bundle defines an API and other bundles provide implementations for
that API. There alternatives to using commons-logging directly in OSGi
are:
Rebundled versions that contain proper OSGi meta data are available
from Apache Felix, SpringSource and Eclipse Orbit. Using Pax logging.
Further information about this topic is available in the archives of
the commons dev ML and the felix dev ML and in Jira.
and when I try to access to the OSGi tab from Jira (going to JIRASERVER/plugins/servlet/upm/osgi#osgi) I can see an exception:
classNotFoundException: org.apache.commons.logging.impl.SLF4JLogFactory
And also I can see from the IDE (when searching for Log4JLogger class) that I have two definitions:
package org.apache.commons.logging.impl.Log4JLogger
public class Log4JLogger implements Log, Serializable {
and
package com.atlassian.extras.common.log;
class Log4jLogger implements com.atlassian.extras.common.log.Logger.Log {
this is really confusing....
I'm not sure, but could it be that the logger you configured does not correspond to the logger in your pom dependencies? Perhaps a different version?
Yet another silly question. I am sure it is something easy, but that already took me a lot of time and I don't get it working ;(
I have a written a working prototype to make a rest call to a server. To do this I utilize "jersey-client-1.14.jar". That works quite well by adding it to the eclipse projects class path.
Now I am trying to do the same in an OSGi bundle. These were the steps I did:
I created a /lib folder in my OSGi bundle project.
Added the jersey-client-1.14.jar in that folder.
Added the jar in the MANIFEST.MF in the classpath: Bundle-ClassPath: ., lib/jersey-client-1.14.jar
Checked that it was also correctly added to the projects classpath.
In the Eclipse workspace I have no compiling errors.
At runtime I have the phenomenon that I get a classdef not found exception when creating the jersey client with Client.create();
!ENTRY org.eclipse.equinox.event 4 0 2012-11-08 23:14:43.975
!MESSAGE Exception while dispatching event org.osgi.service.event.Event [topic=openhab/command/Hue_Bulb_2] to handler org.openhab.binding.hue.internal.HueBinding#70f5f42b
!STACK 0
java.lang.NoClassDefFoundError: Could not initialize class com.sun.jersey.spi.service.ServiceFinder
at com.sun.jersey.api.client.Client.init(Client.java:213)
at com.sun.jersey.api.client.Client.access$000(Client.java:118)
at com.sun.jersey.api.client.Client$1.f(Client.java:191)
at com.sun.jersey.api.client.Client$1.f(Client.java:187)
at com.sun.jersey.spi.inject.Errors.processWithErrors(Errors.java:193)
at com.sun.jersey.api.client.Client.(Client.java:187)
at com.sun.jersey.api.client.Client.(Client.java:159)
at com.sun.jersey.api.client.Client.create(Client.java:669)
at org.openhab.binding.hue.internal.bridge.HueBridge.getSettingsJson(HueBridge.java:64)
at org.openhab.binding.hue.internal.bridge.HueBridge.pairBridgeIfNecessary(HueBridge.java:19)
at org.openhab.binding.hue.internal.HueBinding.receiveCommand(HueBinding.java:37)
at org.openhab.core.events.AbstractEventSubscriber.handleEvent(AbstractEventSubscriber.java:62)
at org.eclipse.equinox.internal.event.EventHandlerWrapper.handleEvent(EventHandlerWrapper.java:197)
at org.eclipse.equinox.internal.event.EventHandlerTracker.dispatchEvent(EventHandlerTracker.java:197)
at org.eclipse.equinox.internal.event.EventHandlerTracker.dispatchEvent(EventHandlerTracker.java:1)
at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:230)
at org.eclipse.osgi.framework.eventmgr.ListenerQueue.dispatchEventSynchronous(ListenerQueue.java:148)
at org.eclipse.equinox.internal.event.EventAdminImpl.dispatchEvent(EventAdminImpl.java:135)
at org.eclipse.equinox.internal.event.EventAdminImpl.sendEvent(EventAdminImpl.java:78)
at org.eclipse.equinox.internal.event.EventComponent.sendEvent(EventComponent.java:39)
at org.openhab.core.internal.events.EventPublisherImpl.sendCommand(EventPublisherImpl.java:76)
at org.openhab.ui.webapp.internal.servlet.CmdServlet.service(CmdServlet.java:115)
at org.eclipse.equinox.http.servlet.internal.ServletRegistration.service(ServletRegistration.java:61)
at org.eclipse.equinox.http.servlet.internal.ProxyServlet.processAlias(ProxyServlet.java:128)
at org.eclipse.equinox.http.servlet.internal.ProxyServlet.service(ProxyServlet.java:60)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:848)
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:598)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:486)
at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:231)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1065)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:413)
at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:192)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:999)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:117)
at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:250)
at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:149)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:111)
at org.eclipse.jetty.server.Server.handle(Server.java:350)
at org.eclipse.jetty.server.AbstractHttpConnection.handleRequest(AbstractHttpConnection.java:454)
at org.eclipse.jetty.server.AbstractHttpConnection.headerComplete(AbstractHttpConnection.java:890)
at org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.headerComplete(AbstractHttpConnection.java:944)
at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:630)
at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:230)
at org.eclipse.jetty.server.AsyncHttpConnection.handle(AsyncHttpConnection.java:77)
at org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle(SelectChannelEndPoint.java:606)
at org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:46)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:603)
at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:538)
at java.lang.Thread.run(Thread.java:680)
23:14:43.992 ERROR OSGi[:98] - Exception while dispatching event org.osgi.service.event.Event [topic=openhab/command/Hue_Bulb_2] to handler org.openhab.binding.hue.internal.HueBinding#70f5f42b
java.lang.NoClassDefFoundError: Could not initialize class com.sun.jersey.spi.service.ServiceFinder
at com.sun.jersey.api.client.Client.init(Client.java:213)
at com.sun.jersey.api.client.Client.access$000(Client.java:118)
at com.sun.jersey.api.client.Client$1.f(Client.java:191)
at com.sun.jersey.api.client.Client$1.f(Client.java:187)
at com.sun.jersey.spi.inject.Errors.processWithErrors(Errors.java:193)
at com.sun.jersey.api.client.Client.(Client.java:187)
at com.sun.jersey.api.client.Client.(Client.java:159)
at com.sun.jersey.api.client.Client.create(Client.java:669)
at org.openhab.binding.hue.internal.bridge.HueBridge.getSettingsJson(HueBridge.java:64)
at org.openhab.binding.hue.internal.bridge.HueBridge.pairBridgeIfNecessary(HueBridge.java:19)
at org.openhab.binding.hue.internal.HueBinding.receiveCommand(HueBinding.java:37)
You'll also need to add jersey-core to you bundle's classpath, as jersey-client has it as a dependency.
You might alos have to add other dependencies if needed. The process is rather easy if not pleasant:
Add a jar
Run the app
See what class is not found, find the jar where that class lives, add it to the bundle classpath, go back to 2
One thing though: Jersey jars are OSGi-ready, so you might as well just add jersey-client.jar and jersey-core.jar to your taget platform and import the required packages.
Looking at your secondary queries I think you just want to know what is going on :-)
OSGi fences JARs to create modules. By default, the fence is impenetrable, no classes outside the bundle (the jar) are visible (being able to load a class from) to classes on the inside, and outsiders cannot see anything inside the bundle. The advantage should be obvious: you can change the inside to your hearts delight since nothing is known outside.
However, in real life you need some holes in the fence to be able to collaborate with others. In your case a bundle tries to load com.sun.jersey.spi.service.ServiceFinder but it runs into the fence because there is no appropriate hole.
The "holes" in OSGi are packages, these are the shared atoms. You list these packages in the manifest. The Import-Package header indicates the packages that you need to see from the outside world and the Export-Package header defines what packages (and under what version) the packages are visible to other bundles.
Obviously you do not want to manually calculate the imports since these are already in your class files, for this reason there is a tool bnd (I am the author) that can be used from maven, ant, gradle, etc. It takes a recipe and calculates the resulting bundle with proper metadata. This tool is extensively supported with the bndtools Eclipse plugin, which is a very nice environment to learn more about OSGi and these issues.
Sir, in eclipse you have been added different package like.
com.sun.jersey.spi.service.ServiceFinder . to start ur service you have to start other service. on which you bundle is dependent.
like i have an jar, which is depependent on rxtxcomm_api-2.1.7.jar.
i had to initialize it or you can say intiat it. before my service. please check it.
Embedding jars is a bad style in OSGi. Generally you should only do this if there is no other way. Embedding jars will easily lead to classpath problems as packages then may come from different bundles. Is there a special reason why you want to embed the jar?
Jersey is fully OSGi ready since version 1.2. See the documentation for examples how to use it.
Most OSGi containers come with a JAX-RS implementation out-of-the-box - being Jersey or what-not. For instance, we're using Apache ServiceMix, which conveniently provides Apache CXF.
What container are you using?
Do you really have to bundle Jersey with your application?
If you need to bundle Jersey for whatever reason, can you please provide an example of your manifest file.
Have you considered using the Maven-Bundle-Plugin?
I need to integrate a REST client into an existing OSGi application implemented using Apache Felix. The REST service is based on RESTeasy implementation (version 2.3.2.Final) of JAX-RS. I created a separate bundle with clients' dependencies, exporting required RESTeasy packages and importing them in the bundle where the client is used, but unfortunately I cannot get it working inside of the OSGi context.
I tried two different approaches. First one using the generic ClientRequest:
ClientRequest request = new ClientRequest(MyService.URL_TEST+"/stats");
request.body(javax.ws.rs.core.MediaType.APPLICATION_XML, stats);
ClientResponse<String> response = request.post(String.class);
The error that I get in this case is pretty weird:
[java] java.lang.RuntimeException: java.lang.ClassCastException:
org.jboss.resteasy.client.core.executors.ApacheHttpClient4Executor cannot be cast to
org.jboss.resteasy.client.ClientExecutor
where I it is known for sure that ApacheHttpClient4Executor implements the ClientExecutor interface.
When I try to use my own REST client wrapper around RESTeasy like this:
MyService myService = MyServiceClient.getInstance();
myService.saveStatistics(stats);
I get a different exception:
[java] java.lang.LinkageError: ClassCastException: attempting to
castjar:file:/D:/Development/Eclipses/eclipse_4.2_j2ee_x64/lib/jaxrs-api-2.3.2.Final.jar
!/javax/ws/rs/ext/RuntimeDelegate.classtobundle:
//78.0:1/javax/ws/rs/ext/RuntimeDelegate.class
As far as I understand, the LinkageError most probably has to do with the way RESTeasy initializes the RuntimeDelegate using some classloader tricks, which probably fall under the restrictions of OSGi framework. I get the suspicion that the java.lang.ClassCastException mentioned first has the same source.
Is there any way to get RESTeasy working inside of OSGi?
PS: discussion about a similar issue with RESTeasy, but outside of OSGi: java.lang.LinkageError: ClassCastException
Update:
these are the libraries included into restclient bundle:
activation-1.1.jar commons-codec-1.2.jar commons-httpclient-3.1.jar commons-io-2.1.jar commons-logging-1.0.4.jar flexjson-2.1.jar httpclient-4.1.2.jar httpcore-4.1.2.jar javassist-3.12.1.GA.jar jaxb-api-2.2.3.jar jaxb-impl-2.2.4.jar jaxrs-api-2.3.2.Final.jar jcip-annotations-1.0.jar jettison-1.3.1.jar jsr250-api-1.0.jar junit-4.10.jar log4j-1.2.14.jar resteasy-jaxb-provider-2.3.2.Final.jar resteasy-jaxrs-2.3.2.Final.jar resteasy-jettison-provider-2.3.2.Final.jar scannotation-1.0.3.jar slf4j-api-1.6.4.jar slf4j-log4j12-1.6.4.jar myservice-common-0.1.0.3.jar my-service-client-0.1.0.3-SNAPSHOT.jar stax-api-1.0-2.jar xmlpull-1.1.3.1.jar xpp3_min-1.1.4c.jar xstream-1.4.2.jar
These are the exports from the restclient bundle: javax.ws.rs, javax.ws.rs.ext, javax.ws.rs.core, org.jboss.resteasy.client, org.jboss.resteasy.client.cache, org.jboss.resteasy.client.extractors, org.jboss.resteasy.client.marshallers, org.jboss.resteasy.client.core.executors, javax.xml.bind.annotation, org.jboss.resteasy.plugins.providers, org.jboss.resteasy.plugins.providers.jaxb, org.jboss.resteasy.spi
Have a look at the SpringSource Bundle Repo, it's got some very useful pre-built bundles of common libraries including the Apache HTTP Client which we are using (in conjunction with gson) to do our RESTful comms.
(unfortunately a legacy module of my project still uses OSGi, but using RESTeasy 3.0.16 now)
When I need to OSGify a dependency my preferred solution now is to wrap it using the excellent Apache Ops4j Pax Tipi project.
The project provides a preconfigured Maven setup (parent POM handles the bundling) and you just have to adapt the GAV coordinates of the original project in a Tipi sub module with a org.apache.ops4j.pax.tipi prefix and build the new bundle project which draws in the original dependency, unpacks and wraps it as OSGi bundle.
You can start from an existing Tipi sub project that best matches your project setup (dependencies, etc.) and adapt any OSGi imports/exports missing (most often, these are created automatically by the maven-bundle-plugin anyway).
This worked quite well for me as long as the original project did not contain too many exotic or malformed dependencies.
However you may run into snags like transitive dependencies using the root package, as I currently experience, which can be a real show stopper (finding out which library is a real nightmare).
Unfortunately, RESTeasy seems to be affected by this, as I get exactly the same error (default package , even after declaring non-test and non-provided dependencies as optional:
The default package '.' is not permitted by the Import-Package syntax.
Upgrading the maven-bundle-plugin to the latest release 3.0.1 yields a different error (even less helpful):
[ERROR] Bundle org.ops4j.pax.tipi:org.ops4j.pax.tipi.resteasy-jaxrs:bundle:3.0.16.Final.1 : Can not parse name from bundle native code header:
[ERROR] Error(s) found in bundle configuration
Update seems to be solved by upping Tipi version in POM to 1.4.0, testing...
Is RESTEasy mandatory ?
I personally use jersey in OSGi and it is working perfectly, both as client and server.
This problem isn't limited to RESTeasy. It also occurs with Jersey.
It is occurring because you have two copies of the JAX-RS classes on the classpath.
You can see this in the LinkageError:
[java] java.lang.LinkageError: ClassCastException: attempting to cast jar:file:/D:/Development/Eclipses/eclipse_4.2_j2ee_x64/lib/jaxrs-api-2.3.2.Final.jar!/javax/ws/rs/ext/RuntimeDelegate.class to bundle://78.0:1/javax/ws/rs/ext/RuntimeDelegate.class
i.e. one copy is coming from:
D:/Development/Eclipses/eclipse_4.2_j2ee_x64/lib/jaxrs-api-2.3.2.Final.jar
and the other from the OSGI bundle.
This causes problems for the RuntimeDelegate class, which by default uses the system class loader to create the RuntimeDelegate implementation (see javax.ws.rs.ext.FactoryFinder).
The problem can also occur if the same jar is loaded via two different class loaders.
There are a couple of workarounds:
remove the jaxrs-api-2.3.2.Final.jar from the system class path
set the thread context class loader to that of your bundle, prior to making any JAX-RS calls.
The FactoryFinder will use this to load the RuntimeDelegate.
To avoid polluting your code with calls to Thread.currentThread().setContextClassLoader(myBundleClassLoader), you can wrap your JAX-RS client using a Proxy. e.g. see the Thread context classloader section of https://puredanger.github.io/tech.puredanger.com/2007/06/15/classloaders/
Specifically, I use spring only for configuring my project through ApplicationContext. In my spring xml I load some bean properties through PropertyPlaceholderConfigurer. Whenever in the dependencies I swap commons-logging-x.x with jcl-slf4j.jar the loading of the context fails with ClassNotFoundExceptions on the placeholder substitutions. Example:
In my spring.xml there is:
<bean id="testbean" class="${testbean.implementingClass}"/>
where testbean.implementingClass is defined in spring.properties:
testbean.implementingClass=my.implementation.TestClass
If I run the project using commons-logging jar all works perfectly. If I change it to jcl-slf4j then I get ClassNotFoundException that the class [${testbean.implementingClass}] was not found, i.e. it does not do the placeholder substituion. Has anyone observed this?
EDIT: My problem doesnt have to do with the jars because:
From http://www.slf4j.org/legacy.html :
Our JCL over SLF4J implementation will allow you to migrate to SLF4J gradually, especially if some of the libraries your software depends on continue to use JCL for the foreseeable future. You can immediately enjoy the benefits of SLF4J's reliability and preserve backward compatibility at the same time. Just replace commons-logging.jar with jcl-over-slf4j.jar. Subsequently, the selection of the underlying logging framework will be done by SLF4J instead of JCL but without the class loader headaches plaguing JCL. The underlying logging framework can be any of the frameworks supported by SLF4J. Often times, replacing commons-logging.jar with jcl-over-slf4j.jar will immediately and permanently solve class loader issues related to commons logging.
When you use jcl-slf4j, you have to make sure you have excluded all commons-logging dependencies from your project. Make sure there is no commons-logging jar anywhere in the classpath.