Archive

Articles taggués ‘jaxws’

Setting timeout on generated JAXWS CXF Clients

23/09/2009 un commentaire

When generating client with the CXF (2.2.2 in this case, should apply to all…) Java API without any configuration file, here is the way to set the client timeout :

package org.ow2.petals.kernel.ws.client;
 
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.frontend.ClientProxy;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
import org.apache.cxf.transport.http.HTTPConduit;
import org.apache.cxf.transports.http.configuration.HTTPClientPolicy;
import org.ow2.petals.kernel.ws.api.RuntimeService;
 
public class Main {
 
    private void createService() {
        long timeout = 10000L;
        JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
        factory.setServiceClass(RuntimeService.class);
        factory.setAddress("http://localhost:9999/service/Runtime");
        RuntimeService runtimeService = (RuntimeService) factory.create();
 
        Client client = ClientProxy.getClient(runtimeService);
        if (client != null) {
            HTTPConduit conduit = (HTTPConduit) client.getConduit();
            HTTPClientPolicy policy = new HTTPClientPolicy();
            policy.setConnectionTimeout(timeout);
            policy.setReceiveTimeout(timeout);
            conduit.setClient(policy);
        }
    }
}

Note that here the RuntimeService class is my JAXWS annotated class.

Categories: WebService Tags: , ,

Easily expose JAXWS in PEtALS with Maven

26/05/2009 Aucun commentaire

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.

Categories: PEtALS Tags: , ,

An operation with name  » already exists in this service

14/05/2009 4 commentaires

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

Categories: WebService Tags: , ,