Migrating Web Service
Christina Lin
Environment Setup
Install H2 database
Copy travelagency.mv.db to ~/h2 folder in your machine.
Setup Fabric authentication
Go to ~/.m2/settings.xml
Unser servers, add the following id/pwd information
<server>
<id>fabric8.upload.repo</id>
<username>admin</username>
<password>admin</password>
</server>
You can skip this part if you already done so
You can skip this part if you already done so
Setup JBoss Fuse
We are going to create web service endpoint for different clients, these clients services are already up and running for a while. And here is how it works, after receiving hotel request from client, the web service will be dispatched to messaging queues. And because the result needs to go back to the client, we need to make sure the request comes back, there for we need to set the JMS to in-out to make sure it gets the return message back.
Choose the blueprint archetype,
GroupID: org.blogdemo.travelagency
ArtifactID: hotelbookingservice
Create a Fuse project,
Open up /example/src/main/resources/OSGI-INF/blueprint/blueprint.xml and remove the route, so you are left with a blank canvas.
Remove the hellobean registry in the xml file. And delete all the java files.
<bean id="helloBean" class="com.mycompany.camel.blueprint.HelloBean"> <property name="say" value="Hi from Camel"/> </bean>
Remove everything under
src/java/* and src/test/*
Setup the dependencies in pom.xml
<!-- For Web Service with CXF -->
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-cxf</artifactId>
<version>2.12.0.redhat-610379</version>
<exclusions>
<exclusion>
<groupId>asm</groupId>
<artifactId>asm</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxrs</artifactId>
<version>2.7.0.redhat-610379</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http-jetty</artifactId>
<version>2.7.0.redhat-610379</version>
</dependency>
<!-- Data transformation -->
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-jackson</artifactId>
<version>2.12.0.redhat-610379</version>
</dependency>
<!-- Messging with AMQ and JMS -->
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-camel</artifactId>
<version>5.9.0.redhat-610379</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-jms</artifactId>
<version>2.12.0.redhat-610379</version>
</dependency>
And because we already have an webservice wsdl, we are going to use it to generate all the classes we need, so add the plugin to your pom.xml too.
<!-- to generate source code from the wsdl file -->
<plugin>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-codegen-plugin</artifactId>
<version>2.7.0.redhat-610379</version>
<executions>
<execution>
<id>generate-sources</id>
<phase>generate-sources</phase>
<configuration>
<sourceRoot>${basedir}/target/generated/src/main/java</sourceRoot>
<wsdlOptions>
<wsdlOption>
<wsdl>${basedir}/src/main/resources/wsdl/HotelWS.wsdl</wsdl>
<extraargs>
<extraarg>-impl</extraarg>
</extraargs>
</wsdlOption>
</wsdlOptions>
</configuration>
<goals>
<goal>wsdl2java</goal>
</goals>
</execution>
</executions>
</plugin>
As you can see, we need to point the plugin to a wsdl, so place our Hotews.wsdl in src/main/resources/wsdl and click save, you should see all the classes generated.
Next up, all we have to do, is tell our Camel CXF component where the service address is going to locate, it's service class and the WSDL file location.
<cxf:cxfEndpoint id="hotelEndpoint"
address="/acme-hotel-service-2.0"
serviceClass="acme.service.soap.hotelws.HotelWS"
wsdlURL="wsdl/HotelWS.wsdl"/>
Rather then just a simple connection to the messaging queue, this small application needs interact with messaging a lot, so we are going to create a pool to the broker
<bean id="jmsConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
<property name="brokerURL" value="tcp://localhost:61616"/>
<property name="userName" value="admin"/>
<property name="password" value="admin"/>
</bean>
<bean id="pooledConnectionFactory" class="org.apache.activemq.pool.PooledConnectionFactory" init-method="start" destroy-method="stop">
<property name="maxConnections" value="2" />
<property name="connectionFactory" ref="jmsConnectionFactory" />
</bean>
<bean id="jmsConfig" class="org.apache.camel.component.jms.JmsConfiguration">
<property name="connectionFactory" ref="pooledConnectionFactory"/>
<property name="concurrentConsumers" value="2"/>
</bean>
<bean id="activemq" class="org.apache.activemq.camel.component.ActiveMQComponent">
<property name="configuration" ref="jmsConfig"/>
</bean>
Take a look at the WSDL, here you see it has three services, with different inputs, so we are going to implement these services.
The first route is the universal endpoint, where it will take in the entire request, and dispatch them to the routes that actually implements the web service.
Create the route to handle booking
Create route to handle canel booking
The last service requires us to return a specific type of object, so we need to process with our custom code.
Create a Java class
Package: org.blogdemo.travelagency.hotelwsendpoint
Class name: ListHotelBean
package org.blogdemo.travelagency.hotelwsendpoint;
import java.util.Map;
import acme.service.soap.hotelws.Resort;
public class ListHotelBean {
public Resort getResort(Map<String, Object> promotedResorts){
Resort resort = new Resort();
resort.setHotelId((Integer)promotedResorts.get("hotelId"));
resort.setHotelName((String)promotedResorts.get("hotelName"));
resort.setHotelCity((String)promotedResorts.get("hotelCity"));
resort.setAvailableFrom((String)promotedResorts.get("availableFrom"));
resort.setAvailableTo((String)promotedResorts.get("availableTo"));
resort.setRatePerPerson(((Double)promotedResorts.get("ratePerPerson")));
return resort;
}
}
Register bean in camel context:
<bean id="hotelBean" class="org.blogdemo.travelagency.hotelwsendpoint.ListHotelBean" />
Create route to handle available hotel request
Lab Complete!