четверг, 26 ноября 2009 г.

Java EE, Web Services

ServiceMix - my first Web Service

In my company we're using Mule as an ESB. One of my colleagues architects asked me if I could investigate some other ESB providers.

I started with Apache ServiceMix ESB.

And here is my first impression of it and my first service assembly.

ServiceMix overview

It's free, it's open source and it's a JBI compliant ESB.

JBI Components come in two flavors, Binding Components and Service Engines.

Binding Components talk about communication protocols and normalisation/denormalisation rules. Examples are: servicemix-http, servicemix-ftp, servicemix-jms.

Service Engines provide logic like scripting, scheduling, routing, validation, XML document transformations, business logic, business rules, business processes, and many more. ServiceMix uses projects like: Apache CXF, Apache Camel, Apache ActieMQ, Spring, Drools, Quartz, and many more. Examples of SEs are: servicemix-bean, servicemix-camel, servicemix-quartz.

ServiceMix uses JBI Packagings called Service Unit and Service Assembly. Service Unit contains definition of one unit. Service Assembly groups Service Units.

Finally, ServiceMix is 100% Maven-ready project. Creating simple service units and service assemblies is extremely simple. There are Maven2 archetypes which create projects' stubs for you.

Probably I missed 90% of ServiceMix features... To find out more visit its home page: http://servicemix.apache.org/.

And now, my first service assembly...

Creating Service Engine

Using Eclipse I created a new Maven2 project. In archetype selection window I chose:

org.apache.servicemix.tooling - servicemix-cxf-se-service-unit

Then I created JAX-WS Web Service:
@WebService(targetNamespace = "http://ws.servicemix.studies.xh.org/", name = "HelloWorld")
public interface HelloWorld {

@WebResult(name = "return", targetNamespace = "")
@RequestWrapper(localName = "sayHi", targetNamespace = "http://ws.servicemix.studies.xh.org/", className = "org.xh.studies.servicemix.ws.SayHi")
@ResponseWrapper(localName = "sayHiResponse", targetNamespace = "http://ws.servicemix.studies.xh.org/", className = "org.xh.studies.servicemix.ws.SayHiResponse")
@WebMethod
public java.lang.String sayHi(
@WebParam(name = "arg0", targetNamespace = "")
java.lang.String arg0
);
}

@javax.jws.WebService(serviceName = "HelloWorldImplService", portName = "HelloWorldImplPort", targetNamespace = "http://ws.servicemix.studies.xh.org/", endpointInterface = "org.xh.studies.servicemix.ws.HelloWorld")
public class HelloWorldImpl implements HelloWorld {

@Override
public String sayHi(String name) {
return "Hello " + name;
}

}
In src/main/resources I updated the xbean.xml configuration:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:cxfse="http://servicemix.apache.org/cxfse/1.0"
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://servicemix.apache.org/cxfse/1.0 http://servicemix.apache.org/schema/servicemix-cxfse-3.2.3.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
<cxfse:endpoint>
<cxfse:pojo>
<bean class="org.xh.studies.servicemix.ws.HelloWorldImpl" />
</cxfse:pojo>
</cxfse:endpoint>
</beans>
The SE service unit was ready.

Creating Binding Component

Using Eclipse I created a new Maven2 project. In archetype selection window I chose:

org.apache.servicemix.tooling - servicemix-cxf-bc-service-unit

In src/main/resources I updated the xbean.xml definition:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:tns="http://ws.servicemix.studies.xh.org/" xmlns:cxfbc="http://servicemix.apache.org/cxfbc/1.0"
xmlns:xsi="http://http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://servicemix.apache.org/cxfbc/1.0 http://servicemix.apache.org/schema/servicemix-cxf-bc-3.2.3.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
<cxfbc:consumer wsdl="classpath:service.wsdl"
targetService="tns:HelloWorldImplService" targetInterface="tns:HelloWorld">
</cxfbc:consumer>
</beans>
Important: the targetService attribute must point to a WSDL Service not the service class that implements the HelloWorld interface... Special thanks to users@servicemix.apache.org :)

Then I created service.wsdl file accordingly to my JAX-WS Web Service and above xbean.xml file.

Creating Service Assembly

Again, using Eclipse I created new Maven2 project. In archetype selection window I chose:

org.apache.servicemix.tooling - servicemix-service-assembly

In the <dependencies /> element I added my two service units (Note the zip type!):
<dependencies>
<dependency>
<groupId>org.xh.studies.servicemix.ws</groupId>
<artifactId>web-service-se-su</artifactId>
<version>0.0.1-SNAPSHOT</version>
<type>zip</type>
</dependency>
<dependency>
<groupId>org.xh.studies.servicemix.ws</groupId>
<artifactId>web-service-bc-su</artifactId>
<version>0.0.1-SNAPSHOT</version>
<type>zip</type>
</dependency>
</dependencies>
Creating parent project

As a last step I created a parent project so that SA could easily resolve SU dependencies:
<modules>
<module>../my-first-servicemix-sa</module>
<module>../web-service-se-su</module>
<module>../web-service-bc-su</module>
</modules>
Building Service Assemlby

I executed (in parent project):
mvn package
All components were successfully built. Then, I copied SA archive into ServiceMix hotdeploy directory, my service started without any errors, and I was able to see my Web Service exposed on the URL I defined in WSDL file.

Complete example download

Complete working example can be found here: ServiceMix-Web-Service.zip.

In the archive you will find 4 Maven projects:

my-first-servicemix - parent project (execute all Maven commends in this project)
my-first-servicemix-sa - SA with dependencies to SUs
web-service-se-su - Service Engine SU
web-service-bc-su - Binding Component SU

I also wrote an integration test called HelloWorldITCase. After deployment you can invoke it with the following command:
mvn integration-test
Summary

My next goal is use embedded ServiceMix and write a better integration test.

Stay tuned :)

Cheers,
Łukasz

Комментариев нет:

Отправить комментарий