Friday, May 29, 2009

Acegi Clustering on JBoss

Again about Acegi ....... Acegi does not support for clustering , but in many ceases it is not a necessary feature . but one of my current project requirement is to limit the concurrent session creation in the cluster environment. One way to achieve this is implement a Acegi "SessionRegistry" based on JGroup , i found this blog entry by Mert Akkan and tried for the proposed solution based on Jgroup DistributedHashtable . Unfortunately in our JBoss 4.2.1.GA (JGroup 2.4.1-sp3) environment gave a method not found exception for DistributedHashtable , I guess this is a version mismatch issue. so only remaining solution was dig in to JGroup framework for alternative solution , After several attempts i could able to get the successful results with ReplicatedHashtable .

This is the modified "DistributableSessionRegistryImpl" class based on JGroup ReplicatedHashtable.



public class DistributableSessionRegistryImpl
implements SessionRegistry,
ApplicationListener {


private Map sessionIds = new HashMap();
String channelName = "Acegi Cluster";
private String clusterOptions = null;
private static final int TIME_OUT = 0;

private boolean distributable=false;

public void setDistributable(boolean distributable) {
this.distributable = distributable;
}

public void setClusterOptions(String clusterOptions) {
this.clusterOptions = clusterOptions;
}


public void setChannelName(String channelName) {
this.channelName = channelName;
}

public Object[] getAllPrincipals() {
Collection collection = sessionIds.values();
Set principals = new HashSet();
for (Iterator iterator = collection.iterator();
iterator.hasNext();) {
DistributableSessionInformation sessionInformation = (DistributableSessionInformation) iterator.next();
principals.add(sessionInformation.getPrincipal());
}
return principals.toArray(new String[principals.size()]);
}

public SessionInformation[] getAllSessions(Object principal,
boolean includeExpiredSessions) {
Set sessionsUsedByPrincipal = getSessionIds(principal);

List list = new ArrayList();
Iterator iter = sessionsUsedByPrincipal.iterator();

while (iter.hasNext()) {
synchronized (sessionsUsedByPrincipal) {
String sessionId = (String) iter.next();
SessionInformation sessionInformation = getSessionInformation(sessionId);

if (includeExpiredSessions || !sessionInformation.isExpired()) {
list.add(sessionInformation);
}
}
}

return (SessionInformation[]) list.toArray(new SessionInformation[]{});
}

public SessionInformation getSessionInformation(String sessionId) {
Assert.hasText(sessionId, "SessionId required as per interface contract");

DistributableSessionInformation sessionInformation = ((DistributableSessionInformation) sessionIds.get(sessionId));
if(sessionInformation==null)return null;
return sessionInformation.sessionInformation(this);
}

public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof HttpSessionDestroyedEvent) {
String sessionId = ((HttpSession) event.getSource()).getId();
removeSessionInformation(sessionId);
}
}

public void refreshLastRequest(String sessionId) {
Assert.hasText(sessionId, "SessionId required as per interface contract");

SessionInformation info = getSessionInformation(sessionId);

if (info != null) {
sessionIds.put(sessionId, new DistributableSessionInformation(info,new Date()) );

}
}
public void expireSession(String sessionId) {
Assert.hasText(sessionId, "SessionId required as per interface contract");

SessionInformation info = getSessionInformation(sessionId);

if (info != null) {
sessionIds.put(sessionId, new DistributableSessionInformation(info,new Date(),true) );

}
}

public synchronized void registerNewSession(String sessionId, Object principal) {
Assert.hasText(sessionId, "SessionId required as per interface contract");
Assert.notNull(principal, "Principal required as per interface contract");

if (getSessionInformation(sessionId) != null) {
removeSessionInformation(sessionId);
}

sessionIds.put(sessionId,new DistributableSessionInformation(principal, sessionId, new Date()));


}

private Set getSessionIds(Object principal) {
Collection collection = sessionIds.values();
Set principals = new HashSet();
for (Iterator iterator = collection.iterator(); iterator.hasNext();) {
DistributableSessionInformation sessionInformation = (DistributableSessionInformation) iterator.next();
if (sessionInformation.getPrincipal().equals(principal))
principals.add(sessionInformation.getSessionId());
}
return principals;

}

public void removeSessionInformation(String sessionId) {
Assert.hasText(sessionId, "SessionId required as per interface contract");

SessionInformation info = getSessionInformation(sessionId);

if (info != null) {
sessionIds.remove(sessionId);


}
}

public void init() throws ChannelException {

if(!distributable)return;
JChannel jChannel;
ReplicatedHashtable hashtable;

if (clusterOptions == null) {
jChannel = new JChannel();

} else {
jChannel = new JChannel(Thread.currentThread().getContextClassLoader().getResource(clusterOptions));
}

jChannel.connect(channelName);
hashtable=new ReplicatedHashtable(jChannel,TIME_OUT);
System.out.println(" Members are "+ jChannel.getView().getMembers());
sessionIds = hashtable;




}

public void destroy() throws ChannelException {
if (sessionIds instanceof ReplicatedHashtable) {
ReplicatedHashtable o = (ReplicatedHashtable) sessionIds;
o.getChannel().close();


}
}
}
download the source code from here

Acegi (Spring Security) and Rampart integration

If you involved to any Spring based web application project, Acegi or Spring Security is not a new thing for you. Acegi is a grate framework that simplifies lot of security headache related to web application. I wrote several blog posts about some of the useful features of Aceigi .

Meanwhile Apache Rampart is a very efficient web service security module for Apache Axis2 that based on Apache WSS4J. I have used Axis2 as a part of Spring J2EE web application rojects, for all those projects I had one common challenge for security integration. Our user/role/access management modules were developed based on Acegi , when a user access to a web page ,Acegi invoke its“AuthenticationManager” to authorize the page access rights based on the provided user credentials . In web service context, same user send a web service request along with same credentials (as an example user name name /password) as a security headers and it is required to invoke “AuthenticationManager” through Rampart to authorize the access rights.

“CallbackHandler” is the underline Rampart mechanism to inject our security logic in to the Rampart module. But one of the critical problem here is there is no way to access to Axis2 MessageContext within the CallbackHandler and hence not possible to access either Spring security context or Spring AppicationContext.

Recently I saw number of post on the mailing list pointing out same requirement without having proper answer. In those days with our tide schedule I end up with a simple but little ugly solution for this.
I used same database table (that contains user security information) for both Acegi and Rampart, in Acegi I injected my user information using “UserDetailService” and for Rampart I wrote small JDBC based DAO service and injected into “CallbackHandler”. But later I could come up with a smart approach for this, in this approach the same acegi AuthenticationManager will used by the Rampart also without reloading. Following steps will help out to any one facing to similar problems.

Step -1
Create a class called “Axis2AwareContextLoaderListener” that extend from Spring ContextLoaderListener . Then in the contextInitialized method set Spring ApplicationContext in to Axis2 ApplicationContextHolder as follows.


public class Axis2AwareContextLoaderListener
extends ContextLoaderListener {

/** The holder. */
ApplicationContextHolder holder;

public void contextInitialized(ServletContextEvent event) {
super.contextInitialized(event);
ApplicationContext appCtx = (ApplicationContext) event
.getServletContext()
.getAttribute(
WebApplicationContext.
ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
holder = new ApplicationContextHolder();
holder.setApplicationContext(appCtx);

}

public void contextDestroyed(ServletContextEvent event) {
super.contextDestroyed(event);
holder = null;
}

}

Step -2
Now in the CallbackHandler implmentaion class we can access to Spring ApllicationContext as follows through the getContext() method of ApplicationContextHolder.

ApplicationContext secCtx = ApplicationContextHolder.getContext();
AuthenticationManager am = (AuthenticationManager) secCtx
.getBean(AUTHENTICATION_MANAGER_BEAN_NAME);


Step -3
Create an instance of Acegi Authentication object with credentials values of Rampart Callbacks object.


public class ServerPWCBHandler
implements CallbackHandler {

/** The Constant AUTHENTICATIONMANAGER_BEAN_NAME. */
public static final String
AUTHENTICATIONMANAGER_BEAN_NAME =
"authenticationManager";

public void handle(Callback[] callbacks) throws IOException,
UnsupportedCallbackException {

ApplicationContext secCtx = ApplicationContextHolder.getContext();
AuthenticationManager am = (AuthenticationManager) secCtx
.getBean(AUTHENTICATIONMANAGER_BEAN_NAME);

for (int i = 0; i < callbacks.length; i++) {

// When the server side need to authenticate the user
WSPasswordCallback pwcb = (WSPasswordCallback) callbacks[i];

if (pwcb.getUsage() == WSPasswordCallback.
USERNAME_TOKEN_UNKNOWN) {
try {
Authentication aut =
new UsernamePasswordAuthenticationToken(
pwcb.getIdentifier(), pwcb.getPassword());
am.authenticate(aut);

} catch (Exception e) {
throw new UnsupportedCallbackException(callbacks[i], e
.getMessage());
}

}

}
}

}



If you want to look at any sample you can download it from here, this sample is a combination of Spring/Acegi/Tapestry5 web application and a Axis2 /Rampart based web service, both web application and web service use values of users.properties file for user authentication.

Monday, May 25, 2009

Guice Axis2 integration

Google Guice is a dependency injection (DI) framework, it provides somewhat different configuration option than spring. Axis2’s spring support is already proven, in this post I will explain how to integrate Guice beans in to Axis2 services.

To integrate Guice with axis2 we have to fulfill flowing two requirements,
  1. Load the relevant Guice “Module “(similar to ApplicationContext in Spring) at the service start up time.
  2. Above Guice beans should be accessible by Axis2 services during the run time.
We can achieve above two requirements as follows.
  1. It is possible to use an implementation of ServletContextListener interface to load the Guice module at the start-up time.
  2. Axis2 provide a interface called ServiceObjectSupplier, it is possible to use this interface to provide a custom beans for axis2 web services. Axis2 – Spring support is already based on this concept.
You can access to source code form here or possible to download binary JAR file directly from here.

Please see the following simple example.

I have following interface to expose as a Axis2 web service, but the actual implementation will provide by the Guice framework.

public interface SimpleService {

public String sayHello();
}

This is our Guice module class..

public class SimpleModule extends AbstractModule {

protected void configure() {
bind(SimpleLogger.class).to(SimpleLoggerImpl.class);
bind(SimpleService.class).to(SimpleServiceImpl.class);

}

}

Next step is to configure our service.xml file for Guice integration, in this case I used a new parameter name called “GuiceBeanName” to define the Guice service bean.



Actually we don’t need to have this parameter "GuiceBeanName" , “ServiceClass” parameter can be used for Guice integration too ,but I used two parameters to clearly separate each task we assign for each parameters, “ServiceClass” Is only used as the service interface to generate WSDL definition for our service where “GuiceBeanName” is used to define Guice bean name for “ServiceObjectSupplier” implementation.

<parameter name="ServiceObjectSupplier" locked="false">
org.apache.axis2.integration.guice.GuiceContextObjectSupplier<
/parameter>
<parameter name="GuiceBeanName" locked="false">org.google.guice.sample.SimpleService<
/parameter>
<parameter name="ServiceClass" locked="false">org.google.guice.sample.SimpleService</parameter>

Final step is to define our “GuiceServletContextListener” in the web.xml as follows.

<context-param>
<param-name>module</param-name>
<param-value>org.google.guice.sample.SimpleModule
</param-value>
</context-param>

<listener>
<listener-class>
org.apache.axis2.integration.guice.
GuiceServletContextListener
</listener-class>
</listener>

here, context parameter called “module” is used to provide the Guice module name , GuiceServletContextListener will try to load this “module” within it’s contextInitialized method.


You can download the complete example from here.

Monday, May 18, 2009

It's a new day

It's been a long time waitin'
Waiting for this moment
It's been a long time praying
Praying for this moment

We hope for this moment
And now that we own it
For life I will hold it
And I ain't gonna let it go

It's for fathers, our brothers,
Our friends who fought for freedom
Our sisters, our mothers,
Who died for us to be in this moment

Stop and cherish this moment
Stop and cherish this time

It's time for unity
For us and we
That's you and me together

I woke up this morning
Feeling brand new
Cause the dreams that I've been dreaming
Have finally came true
Yea, I woke up this morning
Feeling alright

'Cause we weren't fighting for nothing
And the soldiers weren't fighting
For nothing
No, President MR wasn't dreaming for nothing
And Gota didn't change it for nothing
And children weren't crying for nothing

It's a new day
It's a new day
A new day


Thursday, May 07, 2009

Axis2M Released

Yesterday I managed to release first version of Axis2M , Axis2M is not a big framework and does not provide any thing new , it's try to simplify Axis2 web service development with Maven2 . Few months ago I have created some Maven plug-ins for Axis2 to use myself and within my working place , those tools helped me to save lot of my time , so I thought to put them into the Sourceforge so that it will help to other people also . Here i describe some of those plug-ins and rationales behind them .

(1) Qickstart Archetype for Axis2

Maven Archetype is a great concept provide by Maven , Java products/projects can offer own Maven archetypes to their community so that users can easily start- up with preconfigured sample application that can be run within few seconds .

Normally I cant get any confidence about a framework until I see the first working sample , I know it's a personal attitude but there are lot of people feel the same. When I start with Tapestry5 it's only take 4 or 5 minutes to see the result of first application , after that it will only take some few minutes to add extra pages and complete my sample , so far I haven't try out Tapestry5 without this archetype. Now lot of open source projects provide such archetypes and it becoming a necessary feature.

Still we cant see such a archetype provide by web services framework such as Axis2 ,CXF . But Spring -WS provide a archetypes and when I try for Spring-WS I used this archetype.

By the way now Axis2M provide a " Qickstart Archetype" archetype for Axis2 , with this newbies can see the result of their first service within few minutes even after that point they can use this as a template for Axis2 projects. you can try out for Axis2M archetype from here .

Axis2 documantation much more consider about AAR based approach, but my personal view is WAR based approach is more practically useful . Generally lot of people use web services as a part of a web application . I have used Axis2 as a part of several Tapestry and Struts based applications, to address such scenarios we have to use WAR based approach. Axis2M archetype use stranded J2EE web project layout as the project layout to facilitate to above requirement .

when we go along with stranded J2EE web layout ,it is possible to use some of the popular options with Maven build system. such as

  • Use embedded Jetty server to run the service.
  • Use Maven package plug-in to create WAR archive.
  • HSQL based test databases, JUnit test case automation etc .

(2.) Set of useful Maven plug-ins

It is possible to run Axis2 services with Jetty server , but people who familiar with Axis2 like to use it's Simple HTTP server . Axis2M "run" goal facilitate to run Simple HTTP server as a Maven plug-in just like running Jetty server . Axis2 already provide WSDL2Java Maven plug-in but it required several configuration options also by default generated code does not follow the Maven layout , so I have modified original WSDL2Java Maven plug-in so that it will follow the Maven project layout , also it only required configuration when user want to override the default settings, this will enable well-known concept of "Convention over the configuration "

Axis2M currently support to run following servers in embedded mode .
  1. Jetty server.
  2. Axis2 Simple HTTP server.
  3. Apache Tomcat. (from M2 version)
  4. Sun Galssfish (from M2 version)
Further other Axis2 plug in such as Maven AAR and WAR plug-ins already configured with Axis2M archetype.


You can try out for Axis2M from here . Also you are always welcome for any kind of a comments about Axis2M.

Wednesday, May 06, 2009

Early look at Spring REST Support

As Spring announced REST support is one of the important feature of upcoming Spring 3 version , this week I could try out for some of these REST features with a SNAPSHOT release.

Basically we can divide this in to two parts as

1.server side REST support
2.Client side REST support

Server side REST support
This will enable to develop REST services at server side. JAX-RS is the most popular approach for this , there are several project available that supports for JAX-RS , I have used Jersey and they provide good set of tools to build REST services easily. Spring does not directly supports for JAX-RS , in this blog post Arjen Poutsma explained some of the rationales behind this decision. So far I haven't try out for REST service with Spring . Also Apache effort for JAX-RS called Apache Wink still in it's early proposal stage. we can expect good competition among these projects in future .

Client side REST support
For client side REST supports Spring handle it's own way using template concept, if you are familiar with Spring definitely you came a cross with those templates like JMSTemplate , HibernateTemplate etc .

As same way they provide a RESTTemplate to handle REST services in client side , this template hide the low level operations such as commons HttpClient based operations. “messageConverters” property is a one of the important property in this context , the actual message conversion in to HTTP requests/Response is done through this . I tried to use this template to a access a Axis2 REST service , here I described my experience with this .

Here I used “MarshallingHttpMessageConverter” as a “messageConverters” with JAXB databinding . This is how I define RESTTemplate in context file.


<bean id="restTemplate" class="org.springframework.
web.client.RestTemplate">
<constructor-arg ref="httpClientFactory" />
<property name="messageConverters">
<list>
<bean
class="org.springframework.http.converter
.xml.MarshallingHttpMessageConverter">
<property name="marshaller" ref="jaxbMarshaller" />
<property name="unmarshaller" ref="jaxbMarshaller" />
</bean>
</list>
</property>
</bean>

then I have to define jaxbMarshaller bean as follows and add my beans using “classesToBeBound” property.

<bean id="jaxbMarshaller" class="org.springframework.
oxm.jaxb.Jaxb2Marshaller">
<property name="classesToBeBound">
<list>
<value>axis2.client.model.StudentServiceResponse</value>
<value>axis2.client.model.Student</value>
</list>
</property>
</bean>


then in my client class I can access my RESTTemplate and perform the service call as follows .

RestTemplate restTemplate = (RestTemplate) applicationContext
.getBean("restTemplate");
StudentServiceResponse res = restTemplate.getForObject(url,
StudentServiceResponse.class, "100");


Like most of other Spring templates, we can access internal of this template using getRequestFactory() method.

in this case we can access to commons HttpClient as follows.

CommonsClientHttpRequestFactory factory = (CommonsClientHttpRequestFactory) restTemplate
.getRequestFactory();
HttpClient client = factory.getHttpClient();

you can download this example from here

Sunday, May 03, 2009

EIP Gateway pattern with Spring Integration

Spring Integration (SI) is a one of the new addition to enterprise integration field; it can be seen as an implementation of EIP patterns or as a ESB. But at the moment SI is much more care about java based implementation of EIP patterns instead of being a generic ESB product. Apache Camel also implement those EIP patterns in nice way specially through it’s java based DSL routing , until recent past Apache Camel didn’t have good competitor , according to my point of view Spring Integration and Apche Camel are real competitors because both of these project much more consider about EIP patterns and both project address Java based community .

SI is still in its younger age but already provides good set of features; one of the existing futures with SI is it try to extends the Spring’s POJO based approach in to enterprise integration. You can keep all of your business logic as POJOs and possible to convert them in to component of SI in the configuration level.

There are several getaway implementation availbe with SI such as JMS Gateway, Web services gateway …etc, and also it has a generic massaging getaway implantation where you can use it to write your own gateway, in this post I will use this generic getaway to access HTTP IP look-up service provide by HostIP. I wrote my own service at the end point for the simplicity, but it is possible to use HttpInvoker or HTTP Support for this.

The most important feature with this gateway pattern is we can send a POJO message as a request and possible to receive a POJO as a response. This will hide how does message is transform in to the protocol specific format and how does reply message is realize by the system, how to access the service at endpoint and how to configure the endpoint etc.
In other words, other modules of your application do not aware with anything about the integration component or how we communicate with it.

In this sample this is our service interface …
public interface ILocationService {
public Location getLocationbyIP(String IP);
}
As you can see this , getLocationbyIP() method take String argument and return a POJO instance called Location , it hide all integration and transport specific details from other modules , practically this is a great advantage .

Here I go through each of the component one by one …

MIn and MOut are wrapper classes used to send and receive messages for service implementation; in this example these two classes add some extra complexity but I used them to demonstrate the message transformation.

Creater
This will create a request message for our service invocation; you may use Creater to transform your POJO request in to a protocol specific message. In out case Creater create a MIn as a request message.

Mapper
This is use to transform incoming response message in to our application specific message, in this example our Mapper receive XML Document (as a JDOM element) and it will return “Location” object after successful processing .

ILocationService
This is our Service interface other modules of our application only interest about this interface and its services, they don’t want to worry about actual implementation of this interface.

LocationService
As usually this is the implementation of above interface, but if you go through the following code segment you may notice a big difference.
public class LocationService {

public MOut getLocationbyIP(MIn in) {
}
}
  1. Unlike normal Java practice, LocationService does not implement ILocationService.
  2. Method signatures of getLocationbyIP method are not identical.
Then how we can tell that LocationService implant ILocationService
…..?

This is a interesting story behind this gateway pattern implementation of SI , with support of Spring AOP framework; it will create a JdkDynamicAopProxy based object to perform our invocation. If you are interesting about this concept refer the AOP section of Spring documentation and AspectJ documentation.

HelloWorldDemo
This is like a Client class for our gateway; here you can see how easy we can access to our location service through the ILocationService interface.
ILocationService helloService = (ILocationService) context
.getBean("locationGateway");
Location location = helloService.getLocationbyIP("64.236.16.20");
You can download complete sample from here as a Eclipse project .Refer the app.xml file to understand how we configure above POJOs as SI components. Here I used traditional XML based configuration option because personally I like that approach, but you are free to use Annotations instead of XML configuration.
Download the sample from here .

Sunday, April 19, 2009

Axis2 ride with Camel

Ride on a camel is a very attractive adventure, in the same way ride with Apache Camel also very attractive. Most of the middleware systems like EAI and ESB are closely deal with web services frameworks.Apache Synapse: one of the fasted ESB available today powered with Axis2 and Apache Camel provide a component for CXF. I don’t like to see Camel as just a another ESB, it’s very useful reusable framework that implements most of EIP patterns, it’s possible to integrate Camel with a application as a integration middleware to integrate different system or different transports , Even we could use it within a ESB too, Apache ServiceMix already does.

Camel DSL and transport supports for JMS and Mail are brilliant features, one thing I have noticed when I go through the Camel documentation and samples is most of the samples only discuss about CXF integration unlike discussing about more generic web service support.

I’m familiar with Axis2 and I’m happy with its features but in order to try out those camel samples I had to have some CXF experience, I think they should address to broad community with more generalize samples that doesn’t depend on specific implementation.

After reading those samples I wanted to try out for Axis2 with those samples instead of CXF. Camel is developed based on Spring and thanks to the Axis2’s Spring support I could implement those samples with Axis2 without any pain.

Here I describe how to implement “reportincident “sample application with Axis2, but it is important to read the original tutorial from here to get clear idea about the use case before try out for this.

(source - http://camel.apache.org/)

First let’s start with Web service implementation, it is possible to use either contract –first or code-first approach for this, here I used code-first approach to create a service quickly.
public class SimpleService {
public OutputReportIncident reportIncident(InputReportIncident parameters) {
// return an OK reply
OutputReportIncident out = new OutputReportIncident();
out.setCode("OK");
return out;

}
}
As you can see only a POJO method here, with Service.xml we can convert this class a s a web service, before going to that we need to integrate CamelContext : entry point for Camel Framework to our service by adding following field and setter/getter methods.
And also you can see we route our incoming message to Camel using ProducerTemplate within our method .

Note : If your are not familiar with POJO based Axis2 web service development please refer this tutorial.
public class SimpleService {

** The context. */
private CamelContext context;


public OutputReportIncident reportIncident(InputReportIncident parameters) {
// create the producer template to use for sending messages
ProducerTemplate producer = context.createProducerTemplate();
// send the body and the filename defined with the special header key
try {
producer.start();
Object mailBody = producer.sendBody("direct:start", parameters);
System.out.println("Body:" + mailBody);
} catch (Exception e) {

e.printStackTrace();
}
// return an OK reply
OutputReportIncident out = new OutputReportIncident();
out.setCode("OK");
return out;

}

public CamelContext getContext() {
return context;
}

public void setContext(CamelContext context) {
this.context = context;
}

}
We have routed our incoming messages to “direct:start” endpoint URI , so what is next …?

For Camel routing there are two options available.
  1. Use Camel java DSL.
  2. Use Spring configuration.
In Spring configuration approach we don’t need to write any java code , this is our camel router with the context file .
<!-- create a camel context as to start Camel -->

<camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
<route>
<from uri="direct:start"/>
<to uri="velocity:MailBody.vm"/>
<to uri="file://files"/>
</route>

<route>
<from uri="file://files"/>
<setOutHeader headerName="subject">
<constant>new incident reported</constant>
</setOutHeader>
<to
uri="smtp://axisClient@localhost:25?password=axisClient&to=axisServer@localhost"/>
</route>
</camelContext>

<bean id="service" class="start.SimpleService">
<property name="context" ref="camel"/>
</bean>
Note: for SMTP URI you have to provide correct values for two email accounts.

Next step is define our POJO service as a web service using Service.xml , we use following two lines to add Spring bean as a web service.
<parameter name="ServiceObjectSupplier" locked="false">
org.apache.axis2.extensions.spring.receivers.SpringServletContextObjectSupplier</parameter>
<parameter name="SpringBeanName" locked="false">service</parameter>
There is one more thing to do, we have to add Spring ContextLoaderListener in to web,xml file in order to load Camel context at startup time .
<!-- location of spring xml files -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:camel-config.xml</param-value>
</context-param>

<!-- the listener that kick-starts Spring -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
Note : This tutorial describe the approach we used to embed Axis2 in to our web application.

You can download complete example from here.

Now using Maven you can start the Jetty server using “jetty:run”

In the http://localhost:8080/services/SimpleService?wsdl you can see the WSDL content for our service.

Now you can run Client.java and check your email to see the email about the reportincident.


As you can see above we integrated SMTP transport to our service using one line in configuration file, if you want change it in to JMS transport , again it is simple as change the URI. Also we have used Velocity temples to format our Email message within configuration file. This is the real power of Camel you can achieve most of the difficult tasks with few lines in the context file, happy ride with Camel...!!

If you want you can use Camel Java DSL to write the router instead of Spring configuration approach , this sample shows how you could do that.

Also note that at this point I have discussed the topic that equivalent with up to part 4 of original tutorial. In there, they have part 5 that discuss how you can use Camel CXF component to enhance this sample application; with that particular component we can implement web service endpoint within the configuration file without having any Java codes but unfortunately there is no such Camel component for Axis2 at the moment so we can’t cover that part.

download link for Spring based example.
download link for Java DSL based example.