In general class names are not unique in Java. If you want to identify
a class then you always have to use the combination of classloader and
class name. In the JAXB case it is classloader and package name but it
is the same general problem. Whenver you use a classname as a String at
some place then this is a smell and likely breaks in OSGi.
I would try to not use the thread context classloader as you can easily
forget to set it back and then it can influence other calls.
So you remain with the problem of determining the correct classloader to
use. Basically you have to use a classloader that has visibility of the
classes you want to load. The easiest way to do this is to use the
classloader of one of the classes you want to load. So in your case the
best option is probably to just use the classloader of the Person class
: Person.class.getClassLoader(). This approach will work in any environment
(plain Java, JavaEE and OSGi). In OSGi this call will return the
classloader of the bundle that contains the Person class.
Christian
Am 03.03.2015 um 22:37 schrieb Yang, Gang CTR USARMY (US):
Hi, Krzysztof,
Greatly appreciate your effort and your help. I also found couple of solutions
from other website's posts. One of them is your first solution and another is
to use newInstance(package.ObjectFactory.class), which would not apply to my
simple example since it's non-schema-derived, but did work for my original
legacy code, which is schema-derived.
Looking over your solutions, both are classloader-based. I was a little
uncomfortable playing with classloader at application layer. Shouldn't the
framework have taken care of it? How does an application developer know what
classloader to use in general? Interested in hearing your opinion on this.
Thanks again.
Gang
________________________________
From: Krzysztof Sobkowiak [krzys.sobkow...@gmail.com]
Sent: Tuesday, March 03, 2015 2:50 PM
To: users@servicemix.apache.org
Subject: Re: Simple JAXB client doesn't work in ServiceMix
Hi Gang
Sometimes theory is not enough. I had to create a small project. One solution
which worked for me was following line
jaxbContext = JAXBContext.newInstance("mil.army.security.ts3.jaxb.personnel",
this.getClass().getClassLoader());
Another one which worked for me was setting if the context class loader
try {
Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
jaxbContext =
JAXBContext.newInstance("mil.army.security.ts3.jaxb.personnel");
} finally {
Thread.currentThread().setContextClassLoader(cl);
}
This ensures the JAXBContext uses the class loader of your bundle to
instantiate the JAXB Context. In this way your
classes are visible for the JAXBContext.
Please try these solutions. I have attached my sample project. I have made them
from one of the cxf samples and it con
have too many unnecessary dependencies. Feel free to play with this.
Regards
Krzysztof
On 03.03.2015 16:13, Yang, Gang CTR USARMY (US) wrote:
Hi, Krzysztof,
Thanks for the response. I've tried this configuration thinking to make the
JAXB package also visible to the outside and I just tried it again now. It did
not work.
Gang
________________________________
From: Krzysztof Sobkowiak [krzys.sobkow...@gmail.com]
Sent: Monday, March 02, 2015 6:01 PM
To: users@servicemix.apache.org
Subject: Re: Simple JAXB client doesn't work in ServiceMix
Hi
Could you try following definition for export packages?
<Export-Package>
mil.army.security.ts3.jaxb.*
</Export-Package>
or
<Export-Package>
mil.army.security.ts3.jaxb.personnel
</Export-Package>
Regards
Krzysztof
On 02.03.2015 23:20, Yang, Gang CTR USARMY (US) wrote:
Hi,
I had a post for help on JAXB not working in ServiceMix earlier. But that configuration was quite complex. I
now simplified it to a simple JAXB client bundle (no longer embedded/wrapped). It has a single class, Person,
which is annotated with @XmlRootElement and a jaxb.index resource file that contains a single line of the
class name "Person". The JAXB client code simply calls
JAXBContext.newInstance("package") to get the JAXB context in the constructor. A blueprint
deployment descriptor simply defines the JAXB client as a bean. I deployed it into the ServiceMix and the
bean creation causes the "package doesnt contain ObjectFactory.class or jaxb.index" exception from
the call to the JAXBContext.newInstance(). Here's the details about the code. Hope someone can spot what's
missing:
The Person class:
package
mil.army.security.ts3.jaxb.personnel;
import
javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public
class
Person {
private int customerNumber
;
...
// getters and setters
......
}
The JAXB client code:
package mil.army.security.ts3.jaxb;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import mil.army.security.ts3.jaxb.personnel.Person;
public class PersonTransformer {
JAXBContext jaxbContext = null;
Marshaller marshaller = null;
Unmarshaller unmarshaller = null;
public PersonTransformer() {
try {
jaxbContext =
JAXBContext.newInstance("mil.army.security.ts3.jaxb.personnel");
marshaller = jaxbContext.createMarshaller();
unmarshaller = jaxbContext.createUnmarshaller();
}
catch (JAXBException jaxbE) {
System.err.println("PersonTransformer.PersonTransformer():
JAXBException: " + jaxbE);
jaxbE.printStackTrace();
}
}
}
The blueprint deployment descriptor:
<?xml version="1.0" encoding="UTF-8"?>
<blueprint
xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxws="http://cxf.apache.org/blueprint/jaxws"
xsi:schemaLocation="<thismessage:/>http://www.osgi.org/xmlns/blueprint/v1.0.0
http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd
http://cxf.apache.org/blueprint/jaxws
http://cxf.apache.org/schemas/blueprint/jaxws.xsd">
<bean id="jaxbTransformer"
class="mil.army.security.ts3.jaxb.PersonTransformer"/>
</blueprint>
The bundle is built with maven-bundle-plugin using the following imports and
exports:
<Import-Package>
org.osgi.service.blueprint,
javax.xml.bind,
javax.xml.bind.annotation
</Import-Package>
<Export-Package>
mil.army.security.ts3.jaxb
</Export-Package>
To me, it's such a simple JAXB client that should've had every thing that
runtime needs to run it. Unfortunately it failed in ServiceMix. The stacktrace
is at the end of this email. Would appreciate help and suggestions.
Thanks,
Gang
------------------
Stacktrace:
karaf@root<mailto:karaf@root>> PersonTransformer.PersonTransformer(): JAXBException:
javax.xml.bind.JAXBException: "mil.army.security.ts3.j
axb.personnel" doesnt contain ObjectFactory.class or jaxb.index
javax.xml.bind.JAXBException: "mil.army.security.ts3.jaxb.personnel" doesnt
contain ObjectFactory.class or jaxb.index
at
com.sun.xml.bind.v2.ContextFactory.createContext(ContextFactory.java:197)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:143)
at javax.xml.bind.ContextFinder.find(ContextFinder.java:310)
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:446)
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:409)
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:313)
at
mil.army.security.ts3.jaxb.PersonTransformer.<init>(PersonTransformer.java:21)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native
Method)
at
sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at
sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:408)
at
org.apache.aries.blueprint.utils.ReflectionUtils.newInstance(ReflectionUtils.java:329)
at
org.apache.aries.blueprint.container.BeanRecipe.newInstance(BeanRecipe.java:962)
at
org.apache.aries.blueprint.container.BeanRecipe.getInstance(BeanRecipe.java:331)
at
org.apache.aries.blueprint.container.BeanRecipe.internalCreate2(BeanRecipe.java:806)
at
org.apache.aries.blueprint.container.BeanRecipe.internalCreate(BeanRecipe.java:787)
at
org.apache.aries.blueprint.di.AbstractRecipe$1.call(AbstractRecipe.java:79)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at
org.apache.aries.blueprint.di.AbstractRecipe.create(AbstractRecipe.java:88)
at
org.apache.aries.blueprint.container.BlueprintRepository.createInstances(BlueprintRepository.java:245)
at
org.apache.aries.blueprint.container.BlueprintRepository.createAll(BlueprintRepository.java:183)
at
org.apache.aries.blueprint.container.BlueprintContainerImpl.instantiateEagerComponents(BlueprintContainerImpl
.java:681)
at
org.apache.aries.blueprint.container.BlueprintContainerImpl.doRun(BlueprintContainerImpl.java:378)
at
org.apache.aries.blueprint.container.BlueprintContainerImpl.run(BlueprintContainerImpl.java:269)
at
org.apache.aries.blueprint.container.BlueprintExtender.createContainer(BlueprintExtender.java:276)
at
org.apache.aries.blueprint.container.BlueprintExtender.createContainer(BlueprintExtender.java:245)
at
org.apache.aries.blueprint.container.BlueprintExtender.modifiedBundle(BlueprintExtender.java:235)
at
org.apache.aries.util.tracker.hook.BundleHookBundleTracker$Tracked.customizerModified(BundleHookBundleTracker
.java:500)
at
org.apache.aries.util.tracker.hook.BundleHookBundleTracker$Tracked.customizerModified(BundleHookBundleTracker
.java:433)
at
org.apache.aries.util.tracker.hook.BundleHookBundleTracker$AbstractTracked.track(BundleHookBundleTracker.java
:725)
at
org.apache.aries.util.tracker.hook.BundleHookBundleTracker$Tracked.bundleChanged(BundleHookBundleTracker.java
:463)
at
org.apache.aries.util.tracker.hook.BundleHookBundleTracker$BundleEventHook.event(BundleHookBundleTracker.java
:422)
at
org.apache.felix.framework.util.SecureAction.invokeBundleEventHook(SecureAction.java:1127)
at
org.apache.felix.framework.util.EventDispatcher.createWhitelistFromHooks(EventDispatcher.java:696)
at
org.apache.felix.framework.util.EventDispatcher.fireBundleEvent(EventDispatcher.java:484)
at org.apache.felix.framework.Felix.fireBundleEvent(Felix.java:4429)
at org.apache.felix.framework.Felix.startBundle(Felix.java:2100)
at org.apache.felix.framework.BundleImpl.start(BundleImpl.java:976)
at
org.apache.felix.fileinstall.internal.DirectoryWatcher.startBundle(DirectoryWatcher.java:1245)
at
org.apache.felix.fileinstall.internal.DirectoryWatcher.startBundles(DirectoryWatcher.java:1217)
at
org.apache.felix.fileinstall.internal.DirectoryWatcher.doProcess(DirectoryWatcher.java:509)
at
org.apache.felix.fileinstall.internal.DirectoryWatcher.process(DirectoryWatcher.java:358)
at
org.apache.felix.fileinstall.internal.DirectoryWatcher.run(DirectoryWatcher.java:310)
--
Krzysztof Sobkowiak
JEE & OSS Architect
Senior Solution Architect @ Capgemini SSC <http://www.pl.capgemini-sdm.com/en>
Apache ServiceMix <http://servicemix.apache.org/> Committer & PMC