Axis2 + maven ClassFormatError when trying to consume service - web-services

I've created with Axis2 XMLBeans (Version 1.6.2) a client to connect some CRM Dynamics webservices. The client works perfectly fine when I launch it as a standalone project, but when I integrate it into the maven structure of the project and I try to consume the service, I get the following error:
ERROR [http-bio-8080-exec-13][render_portlet_jsp:154]
java.lang.ClassFormatError: Incompatible magic value 4022320623 in
class file
schemaorg_apache_xmlbeans/system/sC40263DCBC25A143E59FC252DB52E714/TypeSystemHolder
at java.lang.ClassLoader.defineClassCond(ClassLoader.java:632) at
java.lang.ClassLoader.defineClass(ClassLoader.java:616) at
java.security.SecureClassLoader.defineClass(SecureClassLoader.java:141)
at
org.apache.catalina.loader.WebappClassLoader.findClassInternal(WebappClassLoader.java:2889)
at
org.apache.catalina.loader.WebappClassLoader.findClass(WebappClassLoader.java:1170)
at
org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1678)
at
org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1556)
at
org.apache.xmlbeans.XmlBeans.typeSystemForClassLoader(XmlBeans.java:769)
at
com.microsoft.schemas.crm._2007.webservices.RetrieveDocument.(RetrieveDocument.java:19)
at
com.microsoft.schemas.crm._2007.webservices.RetrieveDocument$Factory.newInstance(RetrieveDocument.java:147)
I've created the Axis code who's giving the error via Maven with the following plugin:
<plugins>
<plugin>
<groupId>org.apache.axis2</groupId>
<artifactId>axis2-wsdl2code-maven-plugin</artifactId>
<version>1.6.2</version>
<executions>
<execution>
<goals>
<goal>wsdl2code</goal>
</goals>
<configuration>
<packageName>myPackage</packageName>
<wsdlFile>src/main/resources/CrmService.wsdl</wsdlFile>
<databindingName>xmlbeans</databindingName>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
Any idea what is happening? The error indicates normally that the class is corrupted, but I've generated several times (and with different versions of Axis2) and the result is the same...

Just find the solution. In order to include the generated classes into the jar, I've added this lines:
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
<resource>
<directory>target/generated-sources/axis2/wsdl2code/resources</directory>
<filtering>true</filtering>
</resource>
<resource>
<directory>target/generated-sources/axis2/wsdl2code/src</directory>
<filtering>true</filtering>
</resource>
</resources>
After changing the filtering of the resources directory to false, the problem disappears.

I ran into the same problem, I generated an axis 2 client with xmlbeans and when testing it gave me the same error, I looked in many places for a possible solution and this was the only one that worked for me.
The web client is built in a maven module for another web application inside a jar as a dependency.
at the end modifying the pom file to add the filter equal to false it worked

Related

Customizing JWT generation not working in WSO2 APIM 3.1.0

I tried to implement the steps given in WSO2 3.1.0 documentation (https://apim.docs.wso2.com/en/3.0.0/learn/api-gateway/passing-end-user-attributes-to-the-backend/passing-enduser-attributes-to-the-backend-using-jwt/) for customizing JWT.
As given in the documentation, I created the custom JWT generator java class, generated the jar and placed it under WSO2 Home/repository/components/lib folder. Did the necessary configurations in deployment.toml for enabling JWT and restarted the server.
When i hit an API with the bearer token, i am getting the X-JWT-Assertion header in the carbon logs but when i decode it, it doesn't contain the custom claims that i added in the custom JWT generator java class.
It contains the standard claims as seen in the below image and not the custom claims that were added (current_timestamp, message).
Need suggestions on this as i have followed the steps given in the documentation.
After some research I found out it is a OSGi bundle that runs on top of Apache Felix.
Please check following import available in sample code (CustomGatewayJWTGenerator):
import org.osgi.service.component.annotations.Component;
See also sample pom.xml. It adds some information about OSGi bundle:
Here is the important part:
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>3.2.0</version>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Bundle-Name>${project.artifactId}</Bundle-Name>
<Export-Package>
org.wso2.carbon.test.*
</Export-Package>
<Import-Package>
org.wo2.carbon.apimgt.gateway.*,
org.wso2.carbon.apimgt.impl.*
com.nimbusds.jwt.*,
*;resolution:=optional
</Import-Package>
</instructions>
</configuration>
</plugin>
As you can see, it exports components as OSGi. See bellow my pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.wso2</groupId>
<artifactId>wso2</artifactId>
<version>1.2</version>
</parent>
<groupId>org.example</groupId>
<artifactId>CustomGatewayJWTGenerator</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>bundle</packaging>
<dependencies>
<dependency>
<groupId>org.wso2.carbon.apimgt</groupId>
<artifactId>org.wso2.carbon.apimgt.gateway</artifactId>
<version>${carbon.apimgt.version}</version>
</dependency>
<dependency>
<groupId>org.wso2.orbit.com.nimbusds</groupId>
<artifactId>nimbus-jose-jwt</artifactId>
<version>7.3.0.wso2v1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>3.2.0</version>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Bundle-Name>${project.artifactId}</Bundle-Name>
<Export-Package>
la.foton.wso2.apim.custom.*
</Export-Package>
<Import-Package>
org.wo2.carbon.apimgt.gateway.*,
org.wso2.carbon.apimgt.impl.*
com.nimbusds.jwt.*,
*;resolution:=optional
</Import-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
<properties>
<carbon.apimgt.version>6.6.163</carbon.apimgt.version>
</properties>
</project>
I believe you just need to change package information in <Export-Package>, copy JAR file to $APIM_HOME/repository/components/dropins and restart server.
Please let me know if something goes wrong. If it works, please mark answer as correct to help others. :)
I have kept the default JWT properties and values that come predefined with the product as is and have added the one you told. Placed the CustomGatewayJWTGenerator jar in the dropins folder.
The JWT properties look as below now in deployment.toml. Please let me know if the configurations shown below are correct.
[apim.jwt]
enable = true
encoding = "base64" # base64,base64url
generator_impl = "org.wso2.carbon.apimgt.keymgt.token.JWTGenerator"
claim_dialect = "http://wso2.org/claims"
header = "X-JWT-Assertion"
signing_algorithm = "SHA256withRSA"
enable_user_claims = true
claims_extractor_impl = "org.wso2.carbon.apimgt.impl.token.DefaultClaimsRetriever"
[apim.jwt.gateway_generator]
impl = "org.wso2.carbon.test.CustomGatewayJWTGenerator"
Restarted the server and now when i test the API with JWT access token, the invocation fails and getting null pointer exception.
Error Details are as shown below:
ERROR {org.apache.synapse.transport.passthru.ServerWorker} - Error processing GET request for : /pizzashack/1.0.0/menu. java.lang.NullPointerException
at org.wso2.carbon.apimgt.gateway.handlers.security.jwt.JWTValidator.generateAndRetrieveJWTToken_aroundBody2(JWTValidator.java:353)
at org.wso2.carbon.apimgt.gateway.handlers.security.jwt.JWTValidator.generateAndRetrieveJWTToken(JWTValidator.java:336)
at org.wso2.carbon.apimgt.gateway.handlers.security.jwt.JWTValidator.authenticate_aroundBody0(JWTValidator.java:319)
at org.wso2.carbon.apimgt.gateway.handlers.security.jwt.JWTValidator.authenticate(JWTValidator.java:110)
at org.wso2.carbon.apimgt.gateway.handlers.security.oauth.OAuthAuthenticator.authenticate_aroundBody4(OAuthAuthenticator.java:334)
at org.wso2.carbon.apimgt.gateway.handlers.security.oauth.OAuthAuthenticator.authenticate(OAuthAuthenticator.java:109)
at org.wso2.carbon.apimgt.gateway.handlers.security.APIAuthenticationHandler.isAuthenticate_aroundBody42(APIAuthenticationHandler.java:419)
at org.wso2.carbon.apimgt.gateway.handlers.security.APIAuthenticationHandler.isAuthenticate(APIAuthenticationHandler.java:413)
at org.wso2.carbon.apimgt.gateway.handlers.security.APIAuthenticationHandler.handleRequest_aroundBody36(APIAuthenticationHandler.java:349)
at org.wso2.carbon.apimgt.gateway.handlers.security.APIAuthenticationHandler.handleRequest(APIAuthenticationHandler.java:320)
at org.apache.synapse.rest.API.process(API.java:367)
at org.apache.synapse.rest.RESTRequestHandler.apiProcessNonDefaultStrategy(RESTRequestHandler.java:149)
at org.apache.synapse.rest.RESTRequestHandler.dispatchToAPI(RESTRequestHandler.java:95)
at org.apache.synapse.rest.RESTRequestHandler.process(RESTRequestHandler.java:71)
at org.apache.synapse.core.axis2.Axis2SynapseEnvironment.injectMessage(Axis2SynapseEnvironment.java:327)
at org.apache.synapse.core.axis2.SynapseMessageReceiver.receive(SynapseMessageReceiver.java:98)
at org.apache.axis2.engine.AxisEngine.receive(AxisEngine.java:180)
at org.apache.synapse.transport.passthru.ServerWorker.processNonEntityEnclosingRESTHandler(ServerWorker.java:368)
at org.apache.synapse.transport.passthru.ServerWorker.run(ServerWorker.java:189)
at org.apache.axis2.transport.base.threads.NativeWorkerPool$1.run(NativeWorkerPool.java:172)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:813)
I tried to reproduce this scenario locally. It was reproducible when we are using JWT access tokens to invoke the API.
But I was able to successfully get the custom claims in the X-JWT-Assertion header when using OAuth tokens. Please see the below image.
You need to follow this documentation to do the customisation when using JWT access tokens to invoke the API.
I followed the documentation that you shared for invoking the API with JWT access token. I cloned the GIT repository given in the doc.: https://github.com/wso2/samples-apim/tree/master/CustomGatewayJWTGenerator, imported the CustomGatewayJWTGenerator code into eclipse. After the import was successful, i could see a build path error in eclipse: joda-time-2.9.4.wso2v1.jar' in project 'CustomGatewayJWTGenerator' cannot be read or is not a valid ZIP file. Even though the error was seen in eclipse, i was able to build the jar using Maven. I placed the generated jar in lib folder and after server restart verified that the jar was present in dropins folder as well. But somehow, the custom claims that i added in the CustomGatewayJWTGenerator java class are still not coming in the X-JWT-Assertion header. Is it something to do with the error that i got in eclipse after importing the CustomGatewayJWTGenerator project or am i going wrong somewhere else?
The CustomGatewayJWTGenerator java class:
X-JWT-Assertion header:

CXF wsdl2java: No adress location in wsdl:port tag

When creating a web-service using CXF (configuration in Spring), my resulting WSDL is missing the address location in port tag. This is problematic for client side. If CXF is used for client creation, endpoint must be set programatically in client code. If Axis is used (the consumer of my web-service wants to be able to use Axis 1), there is an error saying
Error in generating Java from WSDL: java.io.IOException:
Emitter failure. Cannot find endpoint address in port FooServiceSOAPPort
in service FooServiceLocator
Instead of being forced to create the client using CXF or Axis2 and manually setting the endpoint in client code, I would like to have the following child element:
<soap:address location="http://localhost:9000/services/foo"/>
under the tag <wsdl:port binding="..." name="...> in my WSDL (generated by CXF from my service code).
If I save the WSDL as local file and I manually add the line above, client is generated without any problems using Axis, no manual endpoint setting is needed on the client side and everything is OK. So, how do I make the address location line appear in WSDL generated by CXF?
Here's my Spring config (relevant endpoint tag):
<jaxws:endpoint xmlns:hel="http://user.services/"
name="Foo"
address="/services/foo"
implementor="services.foo.FooImpl"/>
Here's my service interface:
#WebService
public interface Foo {
String method1(String arg1);
}
and implementation
#WebService(endpointInterface = "services.foo.Foo")
#SOAPBinding(style = Style.DOCUMENT, use = Use.LITERAL)
public class FooImpl implements Foo {
#WebMethod(operationName = "method1")
public String method1(String arg1) {
return "OK";
}
}
My first question is how you are generating the WSDL file. Using Ant or Maven. If you are using Maven following will solve your problem.
<build>
<plugins>
<plugin>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-java2ws-plugin</artifactId>
<version>${cxf.version}</version>
<executions>
<execution>
<id>process-classes</id>
<phase>process-classes</phase>
<configuration>
<className>com.stackoverflow.cxf.HelloWorld</className>
<genWsdl>true</genWsdl>
<verbose>true</verbose>
<address>http://localhost:9999/blah/blah</address>
</configuration>
<goals>
<goal>java2ws</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
in the <address> you can specify the one you want. If you are using java2ws command line tool (provided by cxf) you can specify the same using -address command line argument. CXF java2ws tool. I tried this using CXF version 2.5.9. generating sample web service and following is the snippet of resulting wsdl.
<wsdl:service name="HelloWorldService">
<wsdl:port name="HelloWorldPort" binding="tns:HelloWorldServiceSoapBinding">
<soap:address location="http://localhost9999/blah/blah"/>
</wsdl:port>
</wsdl:service>

Axis2 client side by Spring

I have a simple Axis2 client. I using Spring as light container.
My question is: Is there an integration between axis2 client and spring?
I past familiar with org.springframework.remoting.jaxws.JaxWsPortProxyFactoryBean class in Spring but don'y know it worked with axis2 or not.
this link can give you a general idea Of what you need to do
At first you need to generate stub code from axis2 endpoint. Using maven and axis2 maven plugging is like this:
<plugin>
<groupId>org.apache.axis2</groupId>
<artifactId>axis2-wsdl2code-maven-plugin</artifactId>
<version>${axis.version}</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>wsdl2code</goal>
</goals>
<configuration>
<wsdlFile>{axis2wsdl-url} or src/main/resources/wsdl/{downloaded wsdl file}</wsdlFile>
<packageName>com.cybersource.stub</packageName>
<databindingName>xmlbeans</databindingName>
</configuration>
</execution>
</executions>
</plugin>
Next you need to install the generated jar files into maven repository. Before you do anything you need to go to the place the stub code is generated and run "ant" it will generate required jar files and you need to install them into your repo.
If you are using Spring Boot add these two beans:
#Bean
public ConfigurationContext getConfigurationContext() throws AxisFault {
ConfigurationContext ctx = ConfigurationContextFactory
.createConfigurationContextFromFileSystem(config.getAxisConfigLocation(), null);
return ctx;
}
#Bean
public Policy getOMElement() throws FileNotFoundException {
String policyLocation = config.getAxisConfigLocation() + "/conf/policy.xml";
InputStream in = new FileInputStream(policyLocation);
OMXMLParserWrapper omxmlParserWrapper = OMXMLBuilderFactory.createOMBuilder(in);
Policy policy = PolicyEngine.getPolicy(omxmlParserWrapper.getDocumentElement());
return policy;
}
You should set config.getAxisConfigLocation() to somewhere you copied Axis config files like this:
in the above schema axis2.xml is important to generate axis2 context. policy.xml and rampart-xxx.mar files are for authentication which you need to know how your server deal with it.
In your connector section you need to inject ctx and/or policy beans and generate stub like this:
#Autowired
ConfigurationContext ctx;
#Autowired
Policy policy;
private TransactionProcessorStub generateStub() throws AxisFault {
TransactionProcessorStub stub = new TransactionProcessorStub(ctx, config.getServerurl());
ServiceClient client = stub._getServiceClient();
Options clientOptions = client.getOptions();
clientOptions.setProperty(WSHandlerConstants.USER, config.getMerchantid());
clientOptions.setProperty(RampartMessageData.KEY_RAMPART_POLICY, policy);
client.setOptions(clientOptions);
client.engageModule("rampart");
return stub;
}

AXIS error: There is no SOAP service at this location

Note: I could not find a straight-forward answer to this problem so I will document my solution below as an answer.
I generated the server-side part of a webservice from a wsdl using Axis 1.4 and
the axistools-maven-plugin. The Axis servlet is mapped to /services/*, the
service is configured in WEB-INF/server-config.wsdd as follows:
<deployment xmlns="http://xml.apache.org/axis/wsdd/"
xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
<service name="TestService" style="document" use="literal">
<namespace>http://example.com/testservier</namespace>
<parameter name="className" value="com.example.TestServiceImpl"/>
<parameter name="allowedMethods" value="*"/>
<parameter name="scope" value="Session"/>
</service>
</deployment>
When I deploy this web application to Tomcat and access
http://localhost:8080/testservice/services a list of deployed services is
returned.
And now... Some Services
TestService (wsdl)
TestService
Clicking on wsdl should return the description for this service but results in the following error page:
AXIS error
Could not generate WSDL!
There is no SOAP service at this location
The server-config.wsdd was missing a neccessary configuration setting.
<transport name="http">
<requestFlow>
<handler type="java:org.apache.axis.handlers.http.URLMapper"/>
</requestFlow>
</transport>
It seems the URLMapper is responsible for extracting the service name from
the url, without it axis does not know which service to invoke. This is sort of
documented in the axis faq:
This mechanism works because the HTTP transport in Axis has the URLMapper (org.apache.axis.handlers.http.URLMapper) Handler deployed on the request chain. The URLMapper takes the incoming URL, extracts the last part of it as the service name, and attempts to look up a service by that name in the current EngineConfiguration.
Similarly you could deploy the HTTPActionHandler to dispatch via the SOAPAction HTTP header. You can also feel free to set the service in your own custom way - for instance, if you have a transport which funnels all messages through a single service, you can just set the service in the MessageContext before your transport calls the AxisEngine
This makes it sound like the URLMapper would be configued by default which does not seem to be the case.
When I had this problem, it was caused by using the wrong URL.
I used http://localhost:8080/axis/services/AdminWebService?wsdl instead of http://localhost:8080/axis/services/AdminService?wsdl.
AdminWebService must be changed to AdminService.
You better build the server-config.wsdd automatically with the goal "admin". See the documentation about this plugin:
http://mojo.codehaus.org/axistools-maven-plugin/admin-mojo.html
It is very difficult to generate the server-config.wsdd manually.
Example:
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>axistools-maven-plugin</artifactId>
<version>1.3</version>
<configuration>
<filename>${project.artifactId}.wsdl</filename>
<namespace>http://server.ws.xxx</namespace>
<namespaceImpl>http://server.ws.xxx</namespaceImpl>
<classOfPortType>XXXWebService</classOfPortType>
<location>http://localhost:8080/XX/services/XXXWebService</location>
<bindingName>XXServiceSoapBinding</bindingName>
<style>WRAPPED</style>
<use>literal</use>
<inputFiles>
<inputFile>${basedir}\src\main\webapp\WEB-INF\xxxx\deploy.wsdd</inputFile>
<inputFile>${basedir}\src\main\webapp\WEB-INF\xxxx\deploy.wsdd</inputFile>
</inputFiles>
<isServerConfig>true</isServerConfig>
<extraClasses></extraClasses>
</configuration>
<executions>
<execution>
<goals>
<goal>java2wsdl</goal>
<goal>admin</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>axis</groupId>
<artifactId>axis</artifactId>
<version>1.3</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
I had the same problem recently.
Solution :
In my case, I was using Axis 1.4 and was deploying the application on tomcat. However, for some reason the generated server-config.wsdd was not getting packaged in the war and hence was not getting deployed on tomcat. Once, I ensured this is happening, it started working fine for me.
you ensure server-config.wsdd in your package, you can put this file to resources or you can set in your pom.xml via maven which files will be in the package
server-config.wsdd must be valid and correct tags or necessary config is exist so below rows must be in it;
<handler type="java:org.apache.axis.handlers.http.URLMapper" name="URLMapper"/>
<handler type="java:org.apache.axis.transport.local.LocalResponder" name="LocalResponder" />
<transport name="http">
<parameter name="qs:list" value="org.apache.axis.transport.http.QSListHandler" />
<parameter name="qs:method" value="org.apache.axis.transport.http.QSMethodHandler" />
<parameter name="qs:wsdl" value="org.apache.axis.transport.http.QSWSDLHandler" />
<requestFlow>
<handler type="URLMapper" />
<handler type="java:org.apache.axis.handlers.http.HTTPAuthHandler" />
</requestFlow>
</transport>
<transport name="local">
<responseFlow>
<handler type="LocalResponder" />
</responseFlow>
</transport>

JAX-WS using Maven2 Not able to access wsdl using browser

Trying to create some sample prgms using jax-ws.
I am able to successfully generate the required artifacts(java files) and the wsdl file using wsgen. and finally a .war file is generated by maven.
Deployed this .war file in weblogic 9.2 and tried to access the wsdl using the IE browser.But it did not work.
I observed two things
The java and complied class files are generated and are bundled inside the .war file.But the wsdl file is generated outside and not a part of
.war.
Generally wsgen itself will provide the wsdl url.
My queries are:
In order to get the wsdl in IE browser what changes I need to do in POM.
wsdl file should be part of .war.If yes then where should I keep the file.
what changes I need to do to get the soap location url in the wsdl file.
How are you triggering wsgen? It needs to be invoked during the build lifecycle before the war is packaged by Maven. The configuration below will bind the wsgen execution to the process-resources phase, this should mean the wsdl is output below target/classes and included in the war.
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxws-maven-plugin</artifactId>
<executions>
<execution>
<id>wsgen</id>
<phase>process-resources</phase>
<goals>
<goal>wsgen</goal>
</goals>
</execution>
</executions>
<configuration>
...
As far as part 3 of your question, I'm no expert on these things and don't see a means in the plugin to change it. I did find a post that shows how it can be changed programmatically, which may help.