I am writing a console-based Java application, intended to be run by cron
in a batch-processing manner. The batch-processing application makes calls to a SOAP web service, using the Apache CXF framework for JAX-WS.
To make deployment easier, and to prevent CLASSPATH issues, I would like to bundle up the application (with all its dependencies) into a single monolithic JAR file... using the "shade" plugin for Maven.
My application works just fine when I run it from my Eclipse workspace. However, when I try executing the shaded JAR file I get a stacktrace such as the following:
org.apache.cxf.service.factory.ServiceConstructionException: Could not resolve a binding for null
at org.apache.cxf.frontend.AbstractWSDLBasedEndpointFactory.createBindingInfo(AbstractWSDLBasedEndpointFactory.java:404)
at org.apache.cxf.frontend.AbstractWSDLBasedEndpointFactory.createEndpointInfo(AbstractWSDLBasedEndpointFactory.java:258)
at org.apache.cxf.frontend.AbstractWSDLBasedEndpointFactory.createEndpoint(AbstractWSDLBasedEndpointFactory.java:146)
at org.apache.cxf.frontend.ClientFactoryBean.create(ClientFactoryBean.java:52)
at org.apache.cxf.frontend.ClientProxyFactoryBean.create(ClientProxyFactoryBean.java:102)
at org.apache.cxf.jaxws.JaxWsProxyFactoryBean.create(JaxWsProxyFactoryBean.java:115)
at com.example.gui.domain.Session.getService(Session.java:145)
at com.example.gui.domain.service.soap.AbstractServiceImpl.<init>(AbstractServiceImpl.java:23)
at com.example.gui.domain.service.soap.GetUserConsoleOrgsImpl.<init>(GetUserConsoleOrgsImpl.java:14)
at com.example.gui.domain.service.ServiceFactory.getGetUserConsoleOrgsService(ServiceFactory.java:443)
at com.example.gui.domain.AccessManager.getOrgs(AccessManager.java:62)
at com.example.gui.windows.ConsoleApplet.login (ConsoleApplet.java:1253)
at com.example.gui.windows.ConsoleApplet.init(ConsoleApplet.java:1227)
at sun.plugin2.applet.Plugin2Manager$AppletExecutionRunnable.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
Caused by: org.apache.cxf.BusException: No binding factory for namespace http://schemas.xmlsoap.org/soap/ registered.
at org.apache.cxf.binding.BindingFactoryManagerImpl.getBindingFactory(BindingFactoryManagerImpl.java:91)
at org.apache.cxf.frontend.AbstractWSDLBasedEndpointFactory.createBindingInfo(AbstractWSDLBasedEndpointFactory.java:394)
... 14 more
java.lang.NullPointerException
at com.example.gui.domain.service.soap.GetUserConsoleOrgsImpl.getUserConsoleOrgs(GetUserConsoleOrgsImpl.java:29)
at com.example.gui.domain.AccessManager.getOrgs(AccessManager.java:64)
at com.example.gui.windows.ConsoleApplet.login (ConsoleApplet.java:1253)
at com.example.gui.windows.ConsoleApplet.init(ConsoleApplet.java:1227)
at sun.plugin2.applet.Plugin2Manager$AppletExecutionRunnable.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
In fact, if you check out this discussion board message, I'm having the exact same problem that this guy is having. As another person pointed out in that that thread, my issue is probably with the Maven "shade" plugin.
Apache CXF consists of numerous JAR file dependencies, and apparently more than one of those JAR's rely on contents within their META-INF
directories. The Maven "shade" plugin is apparently collapsing all those META-INF
directories into one, and overwriting necessary files rather than merging them together.
Someone in that discussion thread provided a link to this Maven POM file, showing that there are config options and transformers for making the "shade" plugin merge these CXF dependencies properly. I plugged these these settings into my own POM, like so:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>1.4</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.example.MainClass</mainClass>
</transformer>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ApacheNoticeResourceTransformer">
<projectName>Apache CXF</projectName>
</transformer>
<transformer
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/spring.handlers</resource>
</transformer>
<transformer
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/services/com.sun.tools.xjc.Plugin</resource>
</transformer>
<transformer
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/spring.schemas</resource>
</transformer>
<transformer
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/cxf/cxf.extension</resource>
</transformer>
<transformer
implementation="org.apache.maven.plugins.shade.resource.XmlAppendingTransformer">
<resource>META-INF/extensions.xml</resource>
</transformer>
<transformer
implementation="org.apache.maven.plugins.shade.resource.XmlAppendingTransformer">
<resource>META-INF/cxf/extensions.xml</resource>
</transformer>
<transformer
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/cxf/bus-extensions.txt</resource>
</transformer>
<transformer
implementation="org.apache.maven.plugins.shade.resource.XmlAppendingTransformer">
<resource>META-INF/cxf/bus-extensions.xml</resource>
</transformer>
<transformer
implementation="org.apache.maven.plugins.shade.resource.XmlAppendingTransformer">
<resource>META-INF/wsdl.plugin.xml</resource>
</transformer>
<transformer
implementation="org.apache.maven.plugins.shade.resource.XmlAppendingTransformer">
<resource>META-INF/tools.service.validator.xml</resource>
</transformer>
<transformer implementation="org.apache.cxf.maven.PluginTransformer">
<resource>META-INF/tools-plugin.xml</resource>
</transformer>
<transformer
implementation="org.apache.maven.plugins.shade.resource.XmlAppendingTransformer">
<resource>META-INF/cxf/java2wsbeans.xml</resource>
</transformer>
<transformer implementation="org.apache.cxf.maven.CXFAllTransformer" />
</transformers>
</configuration>
</execution>
</executions>
</plugin>
However, I can't find any real explanation for what these settings are doing... and I get the following error when running Maven with debug output enabled:
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1:14.357s
[INFO] Finished at: Tue Jul 26 11:10:43 EDT 2011
[INFO] Final Memory: 18M/59M
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-shade-plugin:1.4:shade (default) on project salestax-poster: Unable to parse configuration of mojo org.apache.maven.plugins:maven-shade-plugin:1.4:shade: ClassNotFoundException: Class name which was explicitly given in configuration using 'implementation' attribute: 'org.apache.cxf.maven.PluginTransformer' cannot be loaded -> [Help 1]
org.apache.maven.lifecycle.LifecycleExecutionException: Failed to execute goal org.apache.maven.plugins:maven-shade-plugin:1.4:shade (default) on project salestax-poster: Unable to parse configuration of mojo org.apache.maven.plugins:maven-shade-plugin:1.4:shade: ClassNotFoundException: Class name which was explicitly given in configuration using 'implementation' attribute: 'org.apache.cxf.maven.PluginTransformer' cannot be loaded
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:221)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:153)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:145)
at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:84)
at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:59)
...
It seems to complain that it can't find the org.apache.cxf.maven.PluginTransformer
class, which seems to exist in the cxf-buildtools
package. However, when I add that package to the POM's dependencies, I get yet another error in the build process:
Jul 26, 2011 10:44:02 AM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.apache.cxf.bus.spring.BusApplicationContext@3aa42c31: display name [org.apache.cxf.bus.spring.BusApplicationContext@3aa42c31]; startup date [Tue Jul 26 10:44:02 EDT 2011]; root of context hierarchy
Jul 26, 2011 10:44:02 AM org.apache.cxf.bus.spring.BusApplicationContext getConfigResources
INFO: No cxf.xml configuration file detected, relying on defaults.
Jul 26, 2011 10:44:02 AM org.springframework.context.support.AbstractApplicationContext obtainFreshBeanFactory
INFO: Bean factory for application context [org.apache.cxf.bus.spring.BusApplicationContext@3aa42c31]: org.springframework.beans.factory.support.DefaultListableBeanFactory@47fe1e26
Jul 26, 2011 10:44:02 AM org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@47fe1e26: defining beans [cxf,org.apache.cxf.bus.spring.BusApplicationListener,org.apache.cxf.bus.spring.BusWiringBeanFactoryPostProcessor,org.apache.cxf.bus.spring.Jsr250BeanPostProcessor,org.apache.cxf.bus.spring.BusExtensionPostProcessor,org.apache.cxf.resource.ResourceManager,org.apache.cxf.configuration.Configurer,org.apache.cxf.binding.BindingFactoryManager,org.apache.cxf.transport.DestinationFactoryManager,org.apache.cxf.transport.ConduitInitiatorManager,org.apache.cxf.wsdl.WSDLManager,org.apache.cxf.phase.PhaseManager,org.apache.cxf.workqueue.WorkQueueManager,org.apache.cxf.buslifecycle.BusLifeCycleManager,org.apache.cxf.endpoint.ServerRegistry,org.apache.cxf.endpoint.ServerLifeCycleManager,org.apache.cxf.endpoint.ClientLifeCycleManager,org.apache.cxf.transports.http.QueryHandlerRegistry,org.apache.cxf.endpoint.EndpointResolverRegistry,org.apache.cxf.headers.HeaderManager,org.apache.cxf.catalog.OASISCatalogManager,org.apache.cxf.endpoint.ServiceContractResolverRegistry]; root of factory hierarchy
[DEBUG]
java.lang.AbstractMethodError: org.apache.xerces.dom.ElementNSImpl.setUserData(Ljava/lang/String;Ljava/lang/Object;Lorg/w3c/dom/UserDataHandler;)Ljava/lang/Object;
at org.apache.cxf.tools.validator.internal.Stax2DOM.startElement(Stax2DOM.java:173)
at org.apache.cxf.tools.validator.internal.Stax2DOM.getDocument(Stax2DOM.java:135)
at org.apache.cxf.tools.validator.internal.Stax2DOM.getDocument(Stax2DOM.java:95)
at org.apache.cxf.tools.validator.internal.Stax2DOM.getDocument(Stax2DOM.java:76)
at org.apache.cxf.tools.validator.internal.WSDL11Validator.getWSDLDoc(WSDL11Validator.java:91)
at org.apache.cxf.tools.validator.internal.WSDL11Validator.isValid(WSDL11Validator.java:111)
at org.apache.cxf.tools.wsdlto.frontend.jaxws.wsdl11.JAXWSDefinitionBuilder.validate(JAXWSDefinitionBuilder.java:201)
at org.apache.cxf.tools.wsdlto.frontend.jaxws.wsdl11.JAXWSDefinitionBuilder.validate(JAXWSDefinitionBuilder.java:61)
at org.apache.cxf.tools.wsdlto.WSDLToJavaContainer.execute(WSDLToJavaContainer.java:132)
at org.apache.cxf.tools.wsdlto.WSDLToJavaContainer.execute(WSDLToJavaContainer.java:238)
at org.apache.cxf.tools.common.toolspec.ToolRunner.runTool(ToolRunner.java:83)
at org.apache.cxf.tools.wsdlto.WSDLToJava.run(WSDLToJava.java:103)
at org.apache.cxf.maven_plugin.WSDL2JavaMojo.processWsdl(WSDL2JavaMojo.java:360)
at org.apache.cxf.maven_plugin.WSDL2JavaMojo.execute(WSDL2JavaMojo.java:257)
at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:101)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:209)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:153)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:145)
at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:84)
at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:59)
at org.apache.maven.lifecycle.internal.LifecycleStarter.singleThreadedBuild(LifecycleStarter.java:183)
at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:161)
at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:319)
at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:156)
at org.apache.maven.cli.MavenCli.execute(MavenCli.java:537)
at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:196)
at org.apache.maven.cli.MavenCli.main(MavenCli.java:141)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:290)
at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:230)
at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:409)
at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:352)
Jul 26, 2011 10:44:03 AM org.springframework.context.support.AbstractApplicationContext doClose
INFO: Closing org.apache.cxf.bus.spring.BusApplicationContext@3aa42c31: display name [org.apache.cxf.bus.spring.BusApplicationContext@3aa42c31]; startup date [Tue Jul 26 10:44:02 EDT 2011]; root of context hierarchy
Jul 26, 2011 10:44:03 AM org.springframework.beans.factory.support.DefaultSingletonBeanRegistry destroySingletons
INFO: Destroying singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@47fe1e26: defining beans [cxf,org.apache.cxf.bus.spring.BusApplicationListener,org.apache.cxf.bus.spring.BusWiringBeanFactoryPostProcessor,org.apache.cxf.bus.spring.Jsr250BeanPostProcessor,org.apache.cxf.bus.spring.BusExtensionPostProcessor,org.apache.cxf.resource.ResourceManager,org.apache.cxf.configuration.Configurer,org.apache.cxf.binding.BindingFactoryManager,org.apache.cxf.transport.DestinationFactoryManager,org.apache.cxf.transport.ConduitInitiatorManager,org.apache.cxf.wsdl.WSDLManager,org.apache.cxf.phase.PhaseManager,org.apache.cxf.workqueue.WorkQueueManager,org.apache.cxf.buslifecycle.BusLifeCycleManager,org.apache.cxf.endpoint.ServerRegistry,org.apache.cxf.endpoint.ServerLifeCycleManager,org.apache.cxf.endpoint.ClientLifeCycleManager,org.apache.cxf.transports.http.QueryHandlerRegistry,org.apache.cxf.endpoint.EndpointResolverRegistry,org.apache.cxf.headers.HeaderManager,org.apache.cxf.catalog.OASISCatalogManager,org.apache.cxf.endpoint.ServiceContractResolverRegistry]; root of factory hierarchy
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 8.152s
[INFO] Finished at: Tue Jul 26 10:44:03 EDT 2011
[INFO] Final Memory: 10M/59M
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.cxf:cxf-codegen-plugin:2.2:wsdl2java (generate-sources) on project salestax-poster: org.apache.xerces.dom.ElementNSImpl.setUserData(Ljava/lang/String;Ljava/lang/Object;Lorg/w3c/dom/UserDataHandler;)Ljava/lang/Object; -> [Help 1]
org.apache.maven.lifecycle.LifecycleExecutionException: Failed to execute goal org.apache.cxf:cxf-codegen-plugin:2.2:wsdl2java (generate-sources) on project salestax-poster: org.apache.xerces.dom.ElementNSImpl.setUserData(Ljava/lang/String;Ljava/lang/Object;Lorg/w3c/dom/UserDataHandler;)Ljava/lang/Object;
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:217)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:153)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:145)
at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:84)
at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:59)
at org.apache.maven.lifecycle.internal.LifecycleStarter.singleThreadedBuild(LifecycleStarter.java:183)
at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:161)
at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:319)
at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:156)
at org.apache.maven.cli.MavenCli.execute(MavenCli.java:537)
at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:196)
at org.apache.maven.cli.MavenCli.main(MavenCli.java:141)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:290)
at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:230)
at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:409)
at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:352)
Caused by: org.apache.maven.plugin.MojoExecutionException: org.apache.xerces.dom.ElementNSImpl.setUserData(Ljava/lang/String;Ljava/lang/Object;Lorg/w3c/dom/UserDataHandler;)Ljava/lang/Object;
at org.apache.cxf.maven_plugin.WSDL2JavaMojo.processWsdl(WSDL2JavaMojo.java:363)
at org.apache.cxf.maven_plugin.WSDL2JavaMojo.execute(WSDL2JavaMojo.java:257)
at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:101)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:209)
... 19 more
Caused by: java.lang.AbstractMethodError: org.apache.xerces.dom.ElementNSImpl.setUserData(Ljava/lang/String;Ljava/lang/Object;Lorg/w3c/dom/UserDataHandler;)Ljava/lang/Object;
at org.apache.cxf.tools.validator.internal.Stax2DOM.startElement(Stax2DOM.java:173)
at org.apache.cxf.tools.validator.internal.Stax2DOM.getDocument(Stax2DOM.java:135)
at org.apache.cxf.tools.validator.internal.Stax2DOM.getDocument(Stax2DOM.java:95)
at org.apache.cxf.tools.validator.internal.Stax2DOM.getDocument(Stax2DOM.java:76)
at org.apache.cxf.tools.validator.internal.WSDL11Validator.getWSDLDoc(WSDL11Validator.java:91)
at org.apache.cxf.tools.validator.internal.WSDL11Validator.isValid(WSDL11Validator.java:111)
at org.apache.cxf.tools.wsdlto.frontend.jaxws.wsdl11.JAXWSDefinitionBuilder.validate(JAXWSDefinitionBuilder.java:201)
at org.apache.cxf.tools.wsdlto.frontend.jaxws.wsdl11.JAXWSDefinitionBuilder.validate(JAXWSDefinitionBuilder.java:61)
at org.apache.cxf.tools.wsdlto.WSDLToJavaContainer.execute(WSDLToJavaContainer.java:132)
at org.apache.cxf.tools.wsdlto.WSDLToJavaContainer.execute(WSDLToJavaContainer.java:238)
at org.apache.cxf.tools.common.toolspec.ToolRunner.runTool(ToolRunner.java:83)
at org.apache.cxf.tools.wsdlto.WSDLToJava.run(WSDLToJava.java:103)
at org.apache.cxf.maven_plugin.WSDL2JavaMojo.processWsdl(WSDL2JavaMojo.java:360)
... 22 more
Has anyone ever used Apache CXF in the context of a Maven shaded JAR, and can provide some guidance as to how you make this work properly?
In my case I needed to add only:
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/cxf/bus-extensions.txt</resource>
</transformer>
If you take a look at this file with and without transformer tag there is a big difference (only one line vs ~50 lines), in particular lines:
org.apache.cxf.binding.soap.SoapBindingFactory::true
org.apache.cxf.binding.soap.SoapTransportFactory::true
are missing which I believe is causing the problem.