Since I am always using command line tools such as Maven or Ant to create my project and to package them, I have just created a new Maven plugin to easily and quickly expose a JAXWS service in PEtALS with Maven. This plugin will generate the JBI Service Unit and Service Assembly from a Maven java project with just a few lines of Maven settings…
As an example, the following interface :
package org.ow2.petals;
import javax.jws.WebMethod;
import javax.jws.WebService;
@WebService
public interface Service {
@WebMethod
String ping(String input);
}
and its implementation :
package org.ow2.petals;
public class ServiceImpl implements Service {
public String ping(String input) {
return input;
}
}
will generate a Service Assembly idirectly deployable to PEtALS by the help of the Maven plugin :
<build>
<plugins>
<plugin>
<groupId>org.ow2.petals</groupId>
<artifactId>maven-petals-jaxws2jbi</artifactId>
<version>1.0-SNAPSHOT</version>
<executions>
<execution>
<id>generate-jbi</id>
<phase>package</phase>
<configuration>
<className>
org.ow2.petals.ServiceImpl
</className>
</configuration>
<goals>
<goal>java2jbi</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
The plugin takes the Service class, generates its associated WSDL file and the JBI descriptor and then package all into a Service Assembly.
PEtALS
jaxws, maven, PEtALS
Here is a tip on how to avoid this type of exception with JAXWS but before let’s try to understand why your Service construciton fails…
This exception occurs when your service definition (the Java interface in our case) have some duplicates methods without the same number of parameters (ie method overloading). This exception is totally normal since it is quite logic that the resulting Web Service can only have unique operation names :
- Check a WSDL file. Did you ever see the same operation X times?
- The Web Service Engine generally tries to get the operation context from the operation name. Then it will unmarshall the parameters (it will not have a look to the operation parameters to choose the operation like it should be done in the Java Runtime).
Here is a service definition sample which will be used in this article :
package com.googlecode.chamerling.blog.jaxws.duplicate;
/**
* @author Christophe HAMERLING
*
*/
public interface Service {
void foo();
void foo(String bar);
}
So let’s implement this interface :
package com.googlecode.chamerling.blog.jaxws.duplicate;
import javax.jws.WebService;
/**
* @author Christophe HAMERLING
*
*/
@WebService
public class ServiceKo implements Service {
public void foo() {
}
public void foo(String bar) {
}
}
Let’s use the JaxWsServerFactoryBean CXF factory (other WS stacks should throw the same exception…) to expose this service :
import org.apache.cxf.jaxws.JaxWsServerFactoryBean;
/**
* @author Christophe HAMERLING
*/
public class App {
private static final String URL = "http://localhost:9999/chamerling/services/";
public static void main(String[] args) {
JaxWsServerFactoryBean svrFactory = new JaxWsServerFactoryBean();
Service space = new ServiceKo();
svrFactory.setAddress(URL + "ServiceKO");
svrFactory.setServiceBean(space);
org.apache.cxf.endpoint.Server service = svrFactory.create();
System.out.println("Service is available at "
+ service.getEndpoint().getEndpointInfo().getAddress());
}
}
You should have a beautiful stack trace :
java.lang.IllegalArgumentException: An operation with name [{http://duplicate.jaxws.blog.chamerling.googlecode.com/}foo] already exists in this service
at org.apache.cxf.service.model.InterfaceInfo.addOperation(InterfaceInfo.java:71)
at org.apache.cxf.service.factory.ReflectionServiceFactoryBean.createOperation(ReflectionServiceFactoryBean.java:774)
at org.apache.cxf.jaxws.support.JaxWsServiceFactoryBean.createOperation(JaxWsServiceFactoryBean.java:484)
at org.apache.cxf.service.factory.ReflectionServiceFactoryBean.createInterface(ReflectionServiceFactoryBean.java:766)
at org.apache.cxf.service.factory.ReflectionServiceFactoryBean.buildServiceFromClass(ReflectionServiceFactoryBean.java:361)
at org.apache.cxf.jaxws.support.JaxWsServiceFactoryBean.buildServiceFromClass(JaxWsServiceFactoryBean.java:525)
at org.apache.cxf.service.factory.ReflectionServiceFactoryBean.initializeServiceModel(ReflectionServiceFactoryBean.java:422)
at org.apache.cxf.service.factory.ReflectionServiceFactoryBean.create(ReflectionServiceFactoryBean.java:190)
at org.apache.cxf.jaxws.support.JaxWsServiceFactoryBean.create(JaxWsServiceFactoryBean.java:164)
at org.apache.cxf.frontend.AbstractWSDLBasedEndpointFactory.createEndpoint(AbstractWSDLBasedEndpointFactory.java:100)
at org.apache.cxf.frontend.ServerFactoryBean.create(ServerFactoryBean.java:117)
at org.apache.cxf.jaxws.JaxWsServerFactoryBean.create(JaxWsServerFactoryBean.java:168)
at com.googlecode.chamerling.blog.jaxws.duplicate.AppTest.testKoService(AppTest.java:37)
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:585)
at junit.framework.TestCase.runTest(TestCase.java:154)
at junit.framework.TestCase.runBare(TestCase.java:127)
at junit.framework.TestResult$1.protect(TestResult.java:106)
at junit.framework.TestResult.runProtected(TestResult.java:124)
at junit.framework.TestResult.run(TestResult.java:109)
at junit.framework.TestCase.run(TestCase.java:118)
at junit.framework.TestSuite.runTest(TestSuite.java:208)
at junit.framework.TestSuite.run(TestSuite.java:203)
at org.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestReference.run(JUnit3TestReference.java:130)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)
So the solution is to use the @WebParam @WebMethod annotation. Simply use this annotation to specify unique operation names in your service implementation :
package com.googlecode.chamerling.blog.jaxws.duplicate;
import javax.jws.WebMethod;
import javax.jws.WebService;
/**
* @author Christophe HAMERLING
*
*/
@WebService
public class ServiceOk implements Service {
@WebMethod(operationName = "foo1")
public void foo() {
}
@WebMethod(operationName = "foo2")
public void foo(String bar) {
}
}
Sources for this example are availble on my google code project (http://code.google.com/p/chamerling/) under http://code.google.com/p/chamerling/source/browse/#svn/trunk/blog/jaxws-duplicate
WebService
cxf, java, jaxws
This news has not been published on the PEtALS Web Site (why?) but yes we now have some SCA (Service Component Architecture) tools available with PEtALS ESB!
This work is a result of the ScorWare project in which eBM WebSourcing was involved in.
The SCA feature is provided in PEtALS by the SCA JBI Service Engine (link to the component and link to the documentation)
The main advantage of SCA over other approaches, like BPEL or EIP, is that you can define the composition with Java instead of XML. The SCA composite defines services, which are exposed in the bus. It also defines references, which point to services that might be called or used by the composite at runtime. These references define possible dependencies. And eventually, your composite embeds a Java implementation which allows you to manipulate the references as simple Java objects. This makes the user job easier, in particular to call a service operation or test conditions on a service call result.
For more details on SCA, on tools and more, take a look at the links below :
- SCA is a specification defined by the Open SOA consortium.
- SCA is in standardization process by the OASIS Consortium.
- OW2 FraSCAti is the SCA platform the SCA service engine is based on.
- Eclipse SCA Tools exist and are hosted by the SOA Tools Platform project. They can be used with the SCA service engine.
- PEtALS Eclipse tools complete the STP SCA tools for PEtALS specifics (PEtALS Maven plug-in support, packaging for PEtALS…).
PEtALS
PEtALS, SCA, soa