SOA

EA Vs SOA – Part (1)

I recently found this article on the TOGAF Open Group web site relating SOA with TOGAF EA reference model. As EA / SOA practitioners, I guess this article would give anyone a complete picture how an EA reference architecture can map to SOA.

http://www.opengroup.org/soa/source-book/togaf/entsoa.htm

The following link will give another perspective about EA and might be useful:

http://grahamberrisford.com/01EAingeneral/EA%20in%20general.htm

VN:F [1.9.22_1171]
Rating: 0.0/10 (0 votes cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)

Enterprise Integtation Patterns

In the Enterprise Application Integration (EAI) space, we do find a lot of middleware, which may be proprietary or open source. Irrespective of the licensing or the technology application of these products, all these products do support the “de-facto” design pattern set, which we basically comply with the popular “Enterprise Integration Patterns” book by Gregor Hohpe and Bobby Woolf. (http://www.eaipatterns.com) This book basically talks about 65 patterns. under 6 categorizations.

1. Message Endpoints

2. Message Construction

3. Message Transformation

4. Message Channels

5. Message Routing

6. System Management

To ease the application of these patterns set, most of the vendors do publish relatively very informative documentations along with their products. A few of those are given below. You may search the same in your selected middle-ware in google, that I am sure will certainly ease the configurations headaches.

WSO2 ESB: http://docs.wso2.org/wiki/display/IntegrationPatterns/Enterprise+Integration+Patterns+with+WSO2+ESB

http://samisa-abeysinghe.blogspot.com/2013/05/wso2-esb-enterprise-integration.html

Ultra ESB: http://docs.adroitlogic.org/display/esb/Enterprise+Integration+Patterns

Apache Camel: http://camel.apache.org/enterprise-integration-patterns.html

Happy Coding!

VN:F [1.9.22_1171]
Rating: 10.0/10 (1 vote cast)
VN:F [1.9.22_1171]
Rating: +1 (from 1 vote)

The Web Services Trust Model (WS-Trust)

The relationship with [WS-Security]

[WS-Security] defines the basic mechanisms for providing the message level security. This specification uses the base mechanisms and defines additional primitives and extensions for security token exchange to enable the issuance and dissemination of credentials within different trust domains.

In order to secure a communication between two parties, the two parties must exchange security credentials. However, each party needs to determine if they can “trust” the asserted credentials of the other party. [WS-Trust] is there to fulfill that process.

The Goal of [WS-Trust]

The main goal of [WS-Trust] is to enable applications to construct trusted [SOAP] message exchanges. This trust is represented through the exchange and brokering of security tokens. This specification provides a protocol agnostic way to issue, renew, and validate these security tokens. In order to facilitate this process, [WS-Trust] introduces a standard run-time component called Security Token Service (STS).

STS (Security Token Service)

In a typical [WS-Security] scenario, the client and the server can exchange keys between them in order to complete a secure communication. However, in a much larger enterprise level application, If we are going to take that approach, the relevant service needs to remember all the client locations and needs to update one by one when there is a key change happens at the service level.

In this kind of a scenario a STS can be quite a help, With STS around, the web service consumer doesn’t need to know the art of creating security tokens. Instead, it sends a request to the STS containing the requirements of the service consumer and the service provider and later attaches the returned security token to the outgoing SOAP message to the service provider. All the service consumer needs to do is to grab the returned token from the STS and attach it to the SOAP message. This basically eases the burden from the service consumer and they can concentrate on the business logic rather than the security aspects revolve around them.

SAML (Security Assertion Markup Language)

Although WS-Trust specification is having a protocol agnostic security token feature, SAML has been the preferred option mainly because of it is inter-operable capability over other protocols. SAML token assertions can provide three kinds of information related to service consumers.

1. Authentication Assertion – limit the service access for some authentication credentials (Name, Id, etc) of the service consumer.

2. Authorization Assertion – limit the service access for some authorization capabilities of the service consumer.

3. Attribute Assertion – limit the service access for certain attributes of the service consumer.

How it works

Now we are in a position to explain the basic flow of the “Web Service Trust Model”. Lets assume that both STS and service consumers are in an agreement to “trust” each other. Therefore, the given STS provider is able to issue security tokens (SAML) to service consumers to access their services. Basically this trust process can be explained in three steps as follows.

1. RST (Request Security Token) – Service Consumer request a security token from STS.

2. RSTR – (RequestSecurityTokenResponse) – STS will send the response as a SAML token with relevant security assertions

3. Now the service consumer is in a position to access the service provider with the SAML token, which was provided by STS.

All these SAML assertions are governed by policies defined (with the help of WS-SecurityPolicy) at service consumer, STS and service provider levels.

The above process is explained in the following diagram as well.

The above pattern creates an indirect trust relationship between the service provider and the STS instead of between the service provider and service consumer. As long as the service consumer is in the possession of a security token issued by a trusted STS, the service consumer is able to access the services provider.

So, this web service trust model is the base for the most of the Single Sign On and other Federated Identity Management systems in the SOA world. My next articles will discuss more into each of the technologies in a very detailed manner. Until then Happy SOA!

References:

1. WS-Trust Specification – http://specs.xmlsoap.org/ws/2005/02/trust/WS-Trust.pdf

2. WS-Trust with Fresh Banana Service – http://blog.facilelogin.com/2010/05/ws-trust-with-fresh-banana-service.html

3. Advanced SOA Security – SAML and WS-Trust – http://www.youtube.com/watch?v=YZNVyUc-3fQ

VN:F [1.9.22_1171]
Rating: 5.5/10 (2 votes cast)
VN:F [1.9.22_1171]
Rating: +2 (from 2 votes)

Ensuring End-End Security via ESB Secure Proxy

In my previous article about ensuring end-end security via ESB, primarily used a “Pass Through Proxy”. In that scenario, the message was not decrypted at the ESB and only decrypted at the service end. That is the easiest way to implement the message level end-end security, mainly because you do not do any message mediations at the ESB level and it was just a pass through.

But, in real world scenarios, ESBs are mostly used for message mediation activities. In such situations, we need the plain message at the ESB level and a decryption at the ESB level is required.

Typically a message will go through the following steps in this scenario.

1. The message is encrypted at the client.

2. The encrypted message is decrypted at the ESB.

3. Apply any mediations to the messages (if required)

4. Encrypt the message again at the ESB.

5. Decrypt the message at the service.

In order to apply above changes, you are required to do following configuration changes to the ESB. (We use WSO2ESB 4.0.0 here)

1. Add a security policy at the ESB Proxy. (For the decryption of the original message from the client)

2. Add a security policy at the ESB End Point. (For the encryption of the mediated message at the ESB)

Therefore, you are required to create a “Secure Proxy” at the ESB level and apply the above two policies for the secure proxy created and the respective end point.

Creating the Secure Proxy in ESB

Please do the following steps at the ESB. (WSO2ESB 4.0.0 is used here) The two policies should be created in the Registry prior executing these options.

1. Create a “Secure Proxy” and add the security policy for client message decryption.

2. Then select the created proxy and click the “Edit” link of the proxy. Then enter the rest of the required fields (i.e. WSDL URL, etc) and continue. When you reach “Step 2″, then click the “Edit” link of the Define End Point -> Define Inline. That will prompt you to the “Address End Point” configuration page. There, select the “Show Advanced Options” and check the “WS-Security” option. That will prompt you to enter the client Security Policy related to the back end service.

An Example

My previous article related to “Ensuring End-End security via ESB Pass through Proxy” was based on “SignEncr” Policy. which is basically Signing and Encrypting the message between both ends. If we apply the same scenario here, The two policies defined at the ESB level can be named here as “SignEncrClient” and “SignEncrService”.

SignEncrClient – This refers to the Step 1 of ESB Configurations.(See previous section)

SignEnctService – This referes to the Step 2 of ESB Configurations.

Respectively, in each above policy, you are required to set private key and public key alases correctly in order to make this communication happen.

In SignEncrClient the rampart configurations can be shown below.

<ramp:RampartConfig xmlns:ramp="http://ws.apache.org/rampart/policy">
	<ramp:user>server</ramp:user>
	<ramp:encryptionUser>client</ramp:encryptionUser>
	<ramp:passwordCallbackClass>com.crishantha.esb.security.ESBCallbackHandler</ramp:passwordCallbackClass>
	<ramp:signatureCrypto>
		<ramp:crypto provider="org.apache.ws.security.components.crypto.Merlin">
  		      <ramp:property name="org.apache.ws.security.crypto.merlin.keystore.type">JKS</ramp:property>
		      <ramp:property name="org.apache.ws.security.crypto.merlin.file">repository/samples/resources/security/esb.jks</ramp:property>
		      <ramp:property name="org.apache.ws.security.crypto.merlin.keystore.password">password</ramp:property>
		</ramp:crypto>
	</ramp:signatureCrypto>
	<ramp:encryptionCypto>
		<ramp:crypto provider="org.apache.ws.security.components.crypto.Merlin">
			<ramp:property name="org.apache.ws.security.crypto.merlin.keystore.type">JKS</ramp:property>
			<ramp:property name="org.apache.ws.security.crypto.merlin.file">repository/samples/resources/security/esb.jks</ramp:property>
			<ramp:property name="org.apache.ws.security.crypto.merlin.keystore.password">password</ramp:property>
		</ramp:crypto>
	</ramp:encryptionCypto>
</ramp:RampartConfig>

In SignEncrService the rampart configuration can be shown as follows

<ramp:RampartConfig xmlns:ramp="http://ws.apache.org/rampart/policy">
	<ramp:user>client</ramp:user>
	<ramp:encryptionUser>server</ramp:encryptionUser>
	<ramp:passwordCallbackClass>com.crishantha.esb.security.ESBCallbackHandler</ramp:passwordCallbackClass>
	<ramp:signatureCrypto>
		<ramp:crypto provider="org.apache.ws.security.components.crypto.Merlin">
  		      <ramp:property name="org.apache.ws.security.crypto.merlin.keystore.type">JKS</ramp:property>
		      <ramp:property name="org.apache.ws.security.crypto.merlin.file">repository/samples/resources/security/esb.jks</ramp:property>
		      <ramp:property name="org.apache.ws.security.crypto.merlin.keystore.password">password</ramp:property>
		</ramp:crypto>
	</ramp:signatureCrypto>
	<ramp:encryptionCypto>
		<ramp:crypto provider="org.apache.ws.security.components.crypto.Merlin">
			<ramp:property name="org.apache.ws.security.crypto.merlin.keystore.type">JKS</ramp:property>
			<ramp:property name="org.apache.ws.security.crypto.merlin.file">repository/samples/resources/security/esb.jks</ramp:property>
			<ramp:property name="org.apache.ws.security.crypto.merlin.keystore.password">password</ramp:property>
		</ramp:crypto>
	</ramp:encryptionCypto>
</ramp:RampartConfig>

Please check <ramp:user> and <ramp:encryptionUser> parameters to see the difference. In this example the keystore is named as esb.jks for both the policies. You can replace this by the default keystore of the ESB or can maintain a separate keystore to maintain the communication with other parties.

The ESBCallbackHandler

As you already know, in order to validate token based authentications, WS-Security uses the CallBack Handler classes especially for token/ password validations. Since the decryption happens at the ESB level, it is required to specify the Call Back Handler class within the ESB. For that you are required to specify the modified ESBCallBackHandler class and store as a jar file in the <ESB_HOME>/components/libs folder.

A sample ESBCallbackHandler class which we used is given below.

package com.crishantha.esb.security;

import java.io.IOException;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import org.apache.ws.security.WSPasswordCallback;

public class ESBCallbackHandler
  implements CallbackHandler
{
  public void handle(Callback[] callbacks)
    throws IOException, UnsupportedCallbackException
  {
    WSPasswordCallback pc = (WSPasswordCallback)callbacks[0];
    int usage = pc.getUsage();

    if (usage == 3) {
      pc.setPassword("password");
    }
    else if (usage == 1) {
      pc.setPassword("password");
    }
    else
      pc.setPassword("password");
  }
}

Actually the above created proxy service is stored in the <ESB_HOME>/repository/deployment/server/synapse-configs/default/proxy-services/ folder. You can re-check the configurations by moving to this folder. The following proxy configuration is the one for above configurations.

<proxy xmlns="http://ws.apache.org/ns/synapse" name="TestSecureProxy" transports="https,http" statistics="disable" trace="disable" startOnLoad="true">
   <target>
      <inSequence>
         <header xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" name="wsse:Security" action="remove" />
      </inSequence>
      <outSequence>
         <send />
      </outSequence>
      <endpoint>
         <address uri="http://localhost:8080/axis2/services/TemperatureConversionService">
            <enableSec policy="gov:/SignEncrService" />
         </address>
      </endpoint>
   </target>
   <publishWSDL uri="http://localhost:8080/axis2/services/TemperatureConversionService?wsdl" />
   <enableSec />
   <policy key="gov:/SignEncrClient" />
   <policy key="conf:/repository/axis2/service-groups/TestSecureProxy/services/TestSecureProxy/policies/urn:uuid:BAAA739BE65334FCD91420475175687" />
</proxy>
VN:F [1.9.22_1171]
Rating: 10.0/10 (2 votes cast)
VN:F [1.9.22_1171]
Rating: +2 (from 2 votes)

AMQP (Advanced Message Queuing Protocol) 1.0 released!

Very recently, OASIS has released the AMQP 1.0 standard. Here is some insight into this popular messaging protocol based on some literature around. Hope this will be helpful.

What is AMQP?

AMQP (Advanced Message Queuing Protocol) is an open standard and a wire-level protocol, which is designed to support messaging on the Internet.

Why AMQP is Important?

It is important mainly because that AMQP is the only open standard available so far for the cross platform interoperability between heterogeneous messaging systems and message brokers. For example, Java Message Producer (JMS Client) can send message to a .NET/C# consumer with the help of a AMQP Message Broker. (See picture below)

In a nutshell, it is inter-operable, reliable, open, standardized, complete and safe [3].

Open Source AMQP Message Broker Implementations

Apache Qpid

RabbitMQ

Before AMQP: JMS

In the Java perspective, prior to AMQP, JMS was heavily used between messaging systems and message brokers. Basically over the years, JMS has been the de facto standard for interoperability within the Java platform. (See picture below)


However, JMS has the ability to communicate with non-Java platforms like Ruby by using Message Bridges. But this is a bit of a complex situation and can cause a lot of chaos in the Enterprise Integration. (See picture below)

By looking at this, one can assume that even using JMS we can assure the cross platform message interoperability. It is easy to said than done. With those message bridges sometimes you may need to handle data inconsistencies, custom property issues, etc. Hence, the integration party might need to customize these specific bridges for specific integrations. This may lead to a lot of integration issues and a complete vendor locking. That is why the industry is slowly making towards a wire level protocol, which can take care of the cross platform interoperability. So far AMQP has given the answer.

References

1. AMQP Web Site – www.amqp.org

2. AMQP Specification – http://www.amqp.org/resources/download or https://www.oasis-open.org/standards#amqpv1.0

3. AMQP in 3 minutes (video) – http://amqp.org/video

4. Understanding the difference between AMQP and JMS - http://www.wmrichards.com/amqp.pdf

5. AMQP Transport for WSO2 ESB based on RabbitMQ – http://kishanthan.wordpress.com/2013/03/26/amqp-transport-for-wso2-esb-based-on-rabbitmq-java-client/

VN:F [1.9.22_1171]
Rating: 10.0/10 (1 vote cast)
VN:F [1.9.22_1171]
Rating: +1 (from 1 vote)

Why Message Brokers?

This article talks about the basic Service Invocation Types, Service Communication Styles and how these are related to the Message Brokers.

Service Invocation Types

As we all know, there are basically two types of service invocations.

1. Synchronous – The consumer uses a single thread to invoke the service. The thread sends the request, blocks it until it gets the response from the service.

2. Asynchronous – The consumer uses a pair of threads to invoke the service. The first thread sends the request and releases itself. The second thread gets the response from the service once it completes its task.

Service Communication Styles

When it comes to service communication, there are three main styles.

1. Synchronous Direct Invocation

2. Synchronous Brokered Invocation

3. Asynchronous Brokered Invocation

Synchronous Direct Invocation

The SOAP over HTTP style of invoking a Web service is said to be direct, much like performing a function call. The consumer knows the address of the endpoint and invokes it directly. For the invocation to succeed, the Web service must be operational when the consumer invokes the endpoint and must respond before the consumer times out.

Here, in order to keep track of all the web service end points, a UDDI server can be used in between the service consumer and the service provider. However, the downside of this approach is that all the time the UDDI server is sending the endpoint of the service provider URI for service invocations. Whenever there is a service end point change, the changed URI should be returned to the service consumer for the invocation. That means each time at a service invocation, the service consumer needs to query the UDDI server for service URIs. That may slow down the service invocations and can be a governance level issue.

Synchronous Broker Invocation

To get over the above issue, the “Message Broker” was introduced primarily. The message brokers have the ability to create “Service Proxies” to handle the above issue. Here, irrespective of service URI changes, the UDDI of the message broker always returns a single URI, which is the service proxy URI to the service consumer.

By adopting to this approach, the responsibility of a service client is totally parked at the Message Broker’s side. In this approach, the Message Broker service proxies are responsible for any service URI changes, service load issues, service failures. That basically takes off a lot of burden form any service client.

Asynchronous Broker Invocation

In this approach, the shortcoming of the synchronous approach, which is “waiting until the service is performed” can be eliminated. Here, the consumer uses one thread to send the request and another to receive the response. This way the consumer doesn’t have to wait for the response and can perform other work in the meantime. To achieve this, the message brokers do implement message queues for sending the request and receiving the response.

Additionally it is important to note, in this approach, you do not see the use of a UDDI server. The service consumer is directly is dealing with the request and reply queues. For each service, there is a separate request-reply queue in the message broker.

The Bus Architecture

The message brokers are an integral part of any Message Oriented Middleware (MOM). These MOMs are basically following the “Bus Architecture” design pattern, which consists of the following components. [2]

1. Message Channels

2. Message Brokers

3. Message Filters

Message channels can be unidirectional or bidirectional. It can be broadcast-oriented, point-point or subscription based.

Broadcast-oriented means that all the messages go to all applications, which are connected to the bus architecture. Point-point means that all the messages go to one specific application. Subscription based means that all the messages are going to a selected set of applications, which are subscribed to a particular topic in the setup.

Filters are basically used to intercept messages, which go through message channels. These interceptions can be a logging, transformation, translation, etc.

Push or Pull Messages

Any bus architecture handles following two kinds of messages.

push messages – known as “event notifications”. This model can be ideal for applications, which are connected to the bus all the time.

pull messages – the typical messages that are sent by applications to the bus in order to get a response. This model can be used to messages, which do not interact with the bus all the time. It basically deploys a “queue” to handle messages.

Popular Message Brokers and Standards

There are basically two popular standards available today.

1. JMS

2. AMQP

These two standards are being implemented by several implementations such as below. Each implementation basically adopts to one of those standards discussed above.

1. Apache ActiveMQ (JMS)

2. RabbitMQ (AMQP)

3. Apache Qpid (AMQP)

4. JBoss HornetQ (JMS)

5. ZeroMQ (AMQP)

6. Websphere WMQ (JMS)

Message Brokers in SOA

Now there are web service standards to implement web service based event notifications via message brokers as well. The well known two specifications are WS-Eventing and WS-Notification. This were in detailed explained in one of my previous articles.

References:

1. Why developers do need an Enterprise Service Bus? – http://www.ibm.com/developerworks/webservices/library/ws-whyesb/

2. The Message Bus Pattern – http://www.ibm.com/developerworks/webservices/library/ws-tip-altdesign4/

3. Eventing in SOA – http://crishantha.com/wp/?p=885

4. Message Broker Comparison – http://lifecorporatedev.blogspot.com/2012/07/recently-i-have-been-given-task-to-find.html

5. RabbitMQ – http://www.rabbitmq.com/

6. Apache ActiveMQ – http://activemq.apache.org/

7. Apache Qpid – http://qpid.apache.org/

8. JBoss HornetQ – http://www.jboss.org/hornetq

9. ZeroMQ – http://www.zeromq.org/

10. WebSphere WMQ – http://www-01.ibm.com/software/integration/wmq/

VN:F [1.9.22_1171]
Rating: 10.0/10 (1 vote cast)
VN:F [1.9.22_1171]
Rating: +2 (from 2 votes)

Eventing in SOA

With the introduction of the Message Oriented Middleware (MOM), we could see the Publisher-Subscriber Message Exchange Pattern (MEP) is applied extensively. This push delivery pattern establishes a unique relationship between the service providers and service requesters. This relationship ensures the dynamic notification mechanism between these two entities.

Publisher-Subscriber Pattern

This involves a publisher service that makes information categorized by different topics for registered subscribers. Subscribers can select which that they are willing to subscribe by interacting directly with a publisher. Here, When a new piece of information on a given topic is available, the publisher broadcasts this information to all those subscribers/ services that have subscribed to that topic.

Alternatively, a message broker can be used to perform the broadcast on the publishers’ behalf. With this approach it can reduce the dependency between the publisher and the subscriber allowing it for a complete decoupled architecture. It basically provides the much required flexibility and the scalability.

Eventing in SOA

“Event notification systems enable asynchronous communications among different entities in any distributed enterprise system.”

When it comes to SOA, applying the web services based specifications/ technologies ensure the interoperability aspect in event notifications. There are already two WS-* specifications widely used in SOA world.

1. WS-Eventing

2. WS-Notification

Although there are two specifications discussed here, they basically follow the same concept underneath though they do not compatible with each other. Prior to these specifications, there were a few notification systems used widely.

1. CORBA Notification Service

2. JMS

3. Open Grid Services Infrastructure (OGSI)

“In general, WS-Eventing specification is simpler than the WS-Notification specification.”

So lets discuss about WS-Eventing and WS-Notification specification a little bit more detail. If you want to get an idea about these specifications in detail, it is advisable to read through the specifications, which are specified under the “References” section.

WS-Eventing

[Click the image to expand]

Event Source:

The publishers role is handled by the “Event Source” here. Event Sources are “receiving subscription requests” and “issuing notification messages” about occurred events.

Event Sink:

This is the service designed to receive notification messages.

Subscriber:
Subscribers issue various types of subscription requests to the Event Source.

Subscription Manager:

The Subscription Manager comes into action when there is a heavy load and when the Event Source cannot itself handle the volume. Hence, the operations related to Event Source such as subscriptions are delegated to Subscription Manager. Therefore in a simple eventing scenario, Subscription Manager tasks are usually handled by Event Sources.

WS-Notification

WS-Notification specification itself consists of 3 more specifications.

1. WS-BaseNotification – This defines the basic interactions between notification producers (publishers) and notification consumers (subscribers).

2. WS-BrokeredNotification – This defines interfaces for notification brokers.

3. WS-Topics – This defines a hierarchical topic space.

WS-Eventing and WS-BaseNotification are basically following the same WS-based architectures.  They both follow the “Publish/Subscriber Model”.

[Click the image to expand]

Situation:

This is the event

Notification Message:

Situations/ events can generate one or more Notification Messages. These are categorized based on the available topics.

Publisher:

This is responsible for generating event notifications. This may not be a web service.

Notification Producer:

Distribution of notification messages are done by this. In the normal circumstances the publishers will not do that and delegated to Notification Providers. This should be a web service.

Notification Consumer:

The notification messages are delivered to this. This is a web service.

Subscriber:

This submits the subscribe request message to the notification producer.

The WS-Notification specification can be further extended to have a Message Broker. (See diagram below) In this process, three more services (web services) are introduced to the specification.

1. The Notification Broker (Web Service) – Acts on behalf of the publisher to perform the role of Notification Producer.

2. The Publisher Registration Manager (Web Service) – This provides an interface for subscribers to search through and locate items available for registration

3. The Subscription Manager (Web Service) – This allows notification producers to access and retrieve required subscriber information for a given notification message broadcast.

[Click the image to expand]

References:

1. WS-Eventing Specification: http://www.w3.org/Submission/WS-Eventing/

2. WS-Notification Specification: https://www.oasis-open.org/committees/tc_home.php?wg_abbrev=wsn

3. A Comparative Study of Web Services-based Event Notification Specifications , by Yi Huang and Dennis Gannon , Department of Computer Science, Indiana University

4. Service Oriented Architecture Concepts, Technology and Design by Thomas Erl

VN:F [1.9.22_1171]
Rating: 10.0/10 (3 votes cast)
VN:F [1.9.22_1171]
Rating: +2 (from 2 votes)

Developing JAX-RS Web Services with Apache CXF

Apache CXF JAX-RS development

In my previous article I have discussed about how Apache CXF can be used to develop JAX-WS web services. In this article I am going to discuss about its JAX-RS support. Along with that, it will discuss the Apache CXF WADL support as well.

The Development Environment

- JDK1.6 or above

- IDE: Eclipse Galelio / Helios / Indigo (JEE Enterprise)

- Application Server: Tomcat 5.5 or above

- JAX-RS Framework: Apache CXF (The download link is http://cxf.apache.org/download.html. Here I have used the CXF 2.4.8)

- MySQL connector for the database connectivity. (Copy the mysql connectivity JAR file to the WEB-INF/lib folder of the Eclipse Project space)

P.NOTE: It is not required to use all JAR files in CXF 2.4.8 lib folder in your development environment. The following selection would be enough.

asm-3.1.jar
jackson-core-asl-1.9.2.jar
jackson-jaxrs-1.9.2.jar
jackson-mapper-asl-1.9.2.jar
jackson-xc-1.9.2.jar
jersey-client-1.12.jar
jersey-core-1.12.jar
jersey-json-1.12.jar
jersey-server-1.12.jar
jersey-servlet-1.12.jar
jettison-1.1.jar
jsr311-api-1.1.1.jar

For Eclipse Galelio Users only …

If you are using Eclipse Galelio, the CXF plugin is not installed as the default feature. It is available only after Helios. Therefore, the Galelio users need to carry out following.

1. Go to Help -> Install New Software on Eclipse Galelio menu. Then in the drop down ‘Work With’ select : The Eclipse Web Tools Platform (WTP) Project update site – http://download.eclipse.org/webtools/updates.

2. In the ‘type filter text’, type in ‘cxf’ and select the SDK and other results and install them.

3. Restart Eclipse and you will get CXF 2.x preferences under Window –> Preferences –> Web Services

Example

Step 1: Create the StudentDB database and StudentDetails table – Please refer the source code.

Step 2: Create the Bean/ POJO class (Student.java) – Please refer the source code.

Step 3: Create the DAO class (StudentDAO.java) – Please refer the source code.

Step 4: Create the interface class (StudentDetails.java)

package crishantha.cxf.service;

import crishantha.cxf.beans.Student;

public interface StudentDetails {
	Student getStudentDetails(String studentId);

}

Step 5: Create the service implementation (StudentDetailsImpl.java)

package crishantha.cxf.service;

import java.sql.SQLException;

import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

import crishantha.cxf.beans.Student;
import crishantha.cxf.storage.StudentDAO;

@Path("/students")
public class StudentDetailsImpl implements StudentDetails {

	@Override
	@GET
	@Consumes({MediaType.APPLICATION_JSON})
	@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
	@Path("{studentId}")
	public Student getStudentDetails(@PathParam("studentId") String studentId) {

		StudentDAO studentDao = new StudentDAO();
	       Student student = null;
	       try {
	            student = studentDao.getStudentDetails(studentId);
	       } catch (SQLException e) {
	           e.printStackTrace();
	       }

	       return student;
	}
}

Step 6: Create the beans.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxrs="http://cxf.apache.org/jaxrs"
	xmlns:jaxws="http://cxf.apache.org/jaxws"
	xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans.xsd

http://cxf.apache.org/jaxrs

http://cxf.apache.org/schemas/jaxrs.xsd

http://cxf.apache.org/jaxws

	http://cxf.apache.org/schemas/jaxws.xsd">
	<import resource="classpath:META-INF/cxf/cxf.xml" />
	<jaxrs:server id="base" address="/">
		<jaxrs:serviceBeans>
			<ref bean="StudentService" />
		</jaxrs:serviceBeans>
	</jaxrs:server>
	<bean id="StudentService" class="crishantha.cxf.service.StudentDetailsImpl" />
</beans>

Step 7: Change the web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>WEB-INF/beans.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <servlet>
        <servlet-name>CXFServlet</servlet-name>
        <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>CXFServlet</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
</web-app>

P.NOTE: You are required to manually create beans.xml and change the web.xml mainly because the current CXF Eclipse plugin does not have an automatic code generation for JAX-RS unlike for JAX-WS web services.

Step 8: Create the WAR file and deploy it in the Tomcat server

Right click the Dynamic Web Project (cxf_jaxrs_service) and export it to a WAR file (cxf_jaxrs_service.war) and deploy it to the TOMCAT_HOME/webapps folder. After that do a restart.

Testing

1. Type the following URL on your favorite browser.

http://localhost:8080/cxf_jaxrs_service/services

(Here cxf_jaxrs_service is the JAR-RS web app with the service)

You will see a WADL link for the developed REST service.

Then click the WADL link and you would see the following.

Now you can test the Apache CXF service by typing the following URL.

http://localhost:8080/cxf_jaxrs_service/students/1

(See the following image for more information)

Source Code

The source code can be found here

VN:F [1.9.22_1171]
Rating: 6.8/10 (9 votes cast)
VN:F [1.9.22_1171]
Rating: +8 (from 10 votes)

Developing JAX-WS Web Services with Apache CXF

Introduction to Apache CXF

In my previous blogs, I was mostly using the popular web service framework Axis2. However from its inception in the open source space, Axis2 was mostly compared by Apache CXF web service framework (Formerly XFire).  There are plenty of articles you may find on Internet related to this subject and me too planning to dig further into it in future as well.

Here, my main objective is to introduce one more web service framework to the audience in my series of web services articles. I hope you will enjoy them as much as I do.

The Development Environment

JDK1.6 or above

IDE: Eclipse Galelio / Helios / Indigo (JEE Enterprise)

Application Server: Tomcat 5.5 or above

JAX-WS Framework: Apache CXF (The download link is http://cxf.apache.org/download.html. Here I have used the CXF 2.4.8)

MySQL connector for the database connectivity. (Copy the mysql connectivity JAR file to CXF downloaded lib folder. Then it will be automatically added to the Eclipse workspace)

For Eclipse Galelio Users only …

If you are using Eclipse Galelio, the CXF plugin is not installed as the default feature. It is available only after Helios. Therefore, the Galelio users need to carry out following.

1. Go to Help -> Install New Software on Eclipse Galelio menu. Then in the drop down ‘Work With’ select : The Eclipse Web Tools Platform (WTP) Project update site – http://download.eclipse.org/webtools/updates.

2. In the ‘type filter text’, type in ‘cxf’ and select the SDK and other results and install them.

3. Restart Eclipse and you will get CXF 2.xPreferences under Window –> Preferences –> Web Services

Setting Up the Environment

1. Open up Eclipse and create a “Dynamic Web Project” – “cxf_jaxws_service”

2. Make sure Java and Apache Tomcat is properly configured in your Eclipse workspace. Just check the Window –> Preferences option to check those. Additionally you need to make sure Apache CXF runtime is configured properly to the Eclipse workspace. For that Check Window -> Preferences –> Web Services –> CXF 2.x Preferences. Here you need to set the CXF Home folder properly. This will add the CXF libraries to the Project workspace.

Now the environment is fully setup to test out Apache CXF JAX-WS features.

The Example

This is a simple example to show how to configure Apache CXF to retrieve Student Details.

Step 1: Create the StudentDB and the StudetDetails table by running the script attached to the source code.

Step 2: Create the bean class (Student.java)

@XmlRootElement
public class Student {

 private int studentID;
 private String studentName;
 private String studentAddress;
 private String studentTelNo;

 public Student() {}

 public Student(int id, String name, String address, String telno) {
   this.studentID = id;
   this.studentName = name;
   this.studentAddress = address;
   this.studentTelNo = telno;
 }

 public int getStudentID() {
   return studentID;
 }

 public void setStudentID(int studentID) {
   this.studentID = studentID;
 }

 public String getStudentName() {
   return studentName;
 }

 public void setStudentName(String studentName) {
   this.studentName = studentName;
 }

 public String getStudentAddress() {
   return studentAddress;
 }

 public void setStudentAddress(String studentAddress) {
   this.studentAddress = studentAddress;
 }

 public String getStudentTelNo() {
   return studentTelNo;
 }

 public void setStudentTelNo(String studentTelNo) {
   this.studentTelNo = studentTelNo;
 }
}

Step 3: Create the DAO Class (StudentDAO.java)

public class StudentDAO {

    Connection connection = null;
    Statement statement = null;
    ResultSet rs = null;

    public Student getStudentDetails(String studentID) throws SQLException {
        String studentName = null;
        String studentAddress = null;
        String studentTelNo = null;

        connection = getConnection();
        try {
            statement = connection.createStatement();
        } catch (SQLException e) {
        }

        String sqlStatement = "select * from StudentDetails where studentID = " + studentID + "";
        rs = statement.executeQuery(sqlStatement);

        Student student = null;
        while (rs.next()) {
            student = new Student();
            studentName = rs.getString("studentName");
            studentAddress = rs.getString("studentAddress");
            studentTelNo = rs.getString("studentTelNo");

            student.setStudentName(studentName);
            student.setStudentAddress(studentAddress);
            student.setStudentTelNo(studentTelNo);
        }

        statement.close();
        connection.close();

        return student;
    }

    private Connection getConnection() {

    	String driverName = "com.mysql.jdbc.Driver";
        String conectionURI = "jdbc:mysql://localhost:3306/StudentDB";
        String userName = "root";
        String password = "";

        try {
            Class.forName(driverName);

            try {
                connection = DriverManager.getConnection(conectionURI, userName, password);
            } catch (SQLException e) {
                e.printStackTrace();
            }
            try {
                connection.setAutoCommit(true);
            } catch (SQLException e) {
                e.printStackTrace();
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

        return connection;
    }
}

Step 4: Create the JAX-WS Web Service (StudentDetails.java)

package crishantha.cxf.service;

import java.sql.SQLException;

import crishantha.cxf.beans.Student;
import crishantha.cxf.storage.StudentDAO;

public class StudentDetails {

	public Student getStudentDetails(String studentId) {

	       StudentDAO studentDao = new StudentDAO();
	       Student student = null;
	       try {
	            student = studentDao.getStudentDetails(studentId);
	       } catch (SQLException e) {
	           e.printStackTrace();
	       }

	       return student;
	}
}

- Once you create the StudentDetails.java right click the class and select WebServices –> Create Web Service option.- Then you will be prompted with the usual web service creation screen on Eclipse. Here however unlike in Axis2, you are required to change the Web Services Runtime to Apache CXF 2.x. (Under the Service Implementation).

- Then on the same screen it is easy to create the Client project as well by moving up the progress bar to the “Deploy Client”. This will create both the service skeleton and the client stubs as well.

- Select the default options of next screens, if you do not need any changes. That will create Wrapper and Fault bean classes, WSDL and XSDs.

- After completing the above process, you will see a modified service class with JAX-WS annotations.

package crishantha.cxf.service;

import java.sql.SQLException;

import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;

import crishantha.cxf.beans.Student;
import crishantha.cxf.storage.StudentDAO;

@WebService(targetNamespace="http://service.cxf.crishantha/", portName="StudentDetailsPort", serviceName="StudentDetailsService")
public class StudentDetails {

	@WebMethod(operationName="getStudentDetails", action="urn:GetStudentDetails")
	public Student getStudentDetails(@WebParam(name="arg0") String studentId) {

	       StudentDAO studentDao = new StudentDAO();
	       Student student = null;
	       try {
	            student = studentDao.getStudentDetails(studentId);
	       } catch (SQLException e) {
	           e.printStackTrace();
	       }

	       return student;
	}
}
- If you had selected the “Deploy Client” that will create a new Client Dynamic Web Project in your workspace as well. That will most probably be “cxf_jaxws_serviceClient” in this scenario.
Step 5: If everything, had gone according to that plan, by typing the following WSDL URL you should be able to see the web service WSDL.

http://localhost:8080/cxf_service_02/services/StudentDetailsPort?wsdl

Step 6: As I mentioned above, the client web application also would have created on the same workspace if you had noticed before. Go inside the src folder and you can create a client leveraging the generated stub classes. Using this you can easily test the created web service.

package crishantha.cxf.service;

import java.net.MalformedURLException;
import java.net.URL;

public class MyClient {

	public static void main(String[] args) {
		StudentDetailsService ss = null;
		try {
			ss = new StudentDetailsService(new URL("http://localhost:8080/cxf_service_02/services/StudentDetailsPort?wsdl"));
		} catch (MalformedURLException e) {
			e.printStackTrace();
		}
		StudentDetails service = ss.getStudentDetailsPort();
		Student student = service.getStudentDetails("5");

		System.out.println("Student Name : " + student.getStudentName());
		System.out.println("Student Address : " + student.getStudentAddress());
		System.out.println("Student Name : " + student.getStudentTelNo());
	}

}

Source Code

The source code can be found here

VN:F [1.9.22_1171]
Rating: 6.5/10 (2 votes cast)
VN:F [1.9.22_1171]
Rating: +5 (from 5 votes)

Developing RESTful web services with Apache Wink

Introduction to Apache Wink

As I mentioned in my previous post, Apache Wink is another JSR 311 (JAX-RS) reference implementation. You are able to download the Apache Wink binaries from the link http://incubator.apache.org/wink.

The Development Environment

JDK1.6 or above

IDE: Eclipse Galelio (Enterprise)

Application Server: Tomcat 5.5

JAX-RS Framework: Apache Wink. (The downloaded location will be referred as WINK_HOME in this tutorial)

MySQL connector for the database connectivity.

Setting Up the Environment

1. Open up Eclipse and create a “Dynamic Web Project” – “jersey_service_student”

2. Make sure Java and Apache Tomcat is properly configured in your Eclipse workspace. Just check the Window –> Preferences option to check those.

3. Copy all jar files from WINK_HOME/lib and WINK_HOME/dist folders to WEB-INF/lib folder. Additionally it is required to copy MySQL connector JAR file also to WEB-INF/lib folder for the database connectivity.

Thats it! Now you are good to go!

The Example

This is a simple example to show how to configure Apache Wink to retrieve Student Details from a database.

Step 1: Create the Student database (StudentDB) and the StudentsDetails table with some records added to it. See the source code for the database script.
Step 2: Modify the web.xml to map with Apache Wink Framework.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
  <display-name>Wink REST Service</display-name>
  <servlet>
    <servlet-name>StudentServlet</servlet-name>
    <servlet-class>org.apache.wink.server.internal.servlet.RestServlet</servlet-class>
    <init-param>
      <param-name>javax.ws.rs.Application</param-name>
      <param-value>crishantha.wink.resources.StudentResourceApplication</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>StudentServlet</servlet-name>
    <url-pattern>/rest/*</url-pattern>
  </servlet-mapping>
</web-app>
Step 3: Define Resources

StudentResourceApplication.java

package crishantha.wink.resources;

import javax.ws.rs.core.Application;
import java.util.HashSet;
import java.util.Set;

public class StudentResourceApplication extends Application {

    @Override
    public Set<Class<?>> getClasses() {
        Set<Class<?>> classes = new HashSet<Class<?>>();
        classes.add(StudentResource.class);

        return classes;
    }
}

StudentResource.java

package crishantha.wink.resources;

import java.sql.SQLException;
import java.util.List;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

import crishantha.wink.storage.StudentDAO;
import crishantha.wink.beans.Student;

@Path("/students")
public class StudentResource {

    @GET
    @Produces(MediaType.APPLICATION_XML)
    public List<Student> getStudents() {
        StudentDAO studentDao = new StudentDAO();
        List<Student> students = null;

        try {
            students = studentDao.getStudents();
        } catch (SQLException e) {
            e.printStackTrace();
        }

        return students;
    }

    @GET
    @Path("{studentid}")
    @Produces(MediaType.APPLICATION_XML)
    public Student getStudentName(@PathParam("studentid") int studentID) {
        StudentDAO studentDao = new StudentDAO();
        Student student = null;
        try {
            student = studentDao.getStudentDetails(studentID);
        } catch (SQLException e) {
            e.printStackTrace();
        }

        return student;
    }
}

Step 4: Define the bean classes

The related bean class (Student.java) is given below.

Student.java

package crishantha.wink.beans;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Student {

 private int studentID;
 private String studentName;
 private String studentAddress;
 private String studentTelNo;

 public Student() {}

 public Student(int id, String name, String address, String telno) {
   this.studentID = id;
   this.studentName = name;
   this.studentAddress = address;
   this.studentTelNo = telno;
 }

 public int getStudentID() {
   return studentID;
 }

 public void setStudentID(int studentID) {
   this.studentID = studentID;
 }

 public String getStudentName() {
   return studentName;
 }

 public void setStudentName(String studentName) {
   this.studentName = studentName;
 }

 public String getStudentAddress() {
   return studentAddress;
 }

Step 5: Define the Data Access Layer

The Data Access Layer classes are given below. These are used to implement the data access layer. Here the simple SQL is used for GET requests. The other REST operations are not specified here for brevity.

StudentDAO.java

package crishantha.wink.storage;

import java.sql.*;
import java.util.ArrayList;
import java.util.List;

import crishantha.wink.beans.Student;

public class StudentDAO {

    Connection connection = null;
    Statement statement = null;
    ResultSet rs = null;

    public Student getStudentDetails(int studentID) throws SQLException {
        String studentName = null;
        String studentAddress = null;
        String studentTelNo = null;

        connection = getConnection();
        try {
            statement = connection.createStatement();
        } catch (SQLException e) {
        }

        String sqlStatement = "select * from StudentDetails where studentID = " + studentID + "";
        rs = statement.executeQuery(sqlStatement);

        Student student = null;
        while (rs.next()) {
            student = new Student();
            studentName = rs.getString("studentName");
            studentAddress = rs.getString("studentAddress");
            studentTelNo = rs.getString("studentTelNo");

            student.setStudentName(studentName);
            student.setStudentAddress(studentAddress);
            student.setStudentTelNo(studentTelNo);
        }

        statement.close();
        connection.close();

        return student;
    }

    public List<Student> getStudents() throws SQLException {
        String studentName = null;
        String studentAddress = null;
        String studentTelNo = null;
        int studentID = 0;

        connection = getConnection();
        try {
            statement = connection.createStatement();
        } catch (SQLException e) {
        }

        String sqlStatement = "Select * from StudentDetails";
        rs = statement.executeQuery(sqlStatement);

        List<Student> students= new ArrayList<Student>();

        while (rs.next()) {
            Student student = new Student();

            studentID = rs.getInt("studentID");
            studentName = rs.getString("studentName");
            studentAddress = rs.getString("studentAddress");
            studentTelNo = rs.getString("studentTelNo");

            student.setStudentID(studentID);
            student.setStudentName(studentName);
            student.setStudentAddress(studentAddress);
            student.setStudentTelNo(studentTelNo);

            students.add(student);
        }

        statement.close();
        connection.close();

        return students;
    }

    private Connection getConnection() {

    	String driverName = "com.mysql.jdbc.Driver";
        String conectionURI = "jdbc:mysql://localhost:3306/StudentDB";
        String userName = "root";
        String password = "";

        try {
            Class.forName(driverName);

            try {
                connection = DriverManager.getConnection(conectionURI, userName, password);
            } catch (SQLException e) {
                e.printStackTrace();
            }
            try {
                connection.setAutoCommit(true);
            } catch (SQLException e) {
                e.printStackTrace();
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

        return connection;
    }
}

So now you have completed the coding. Time to test!

Step 6: Deploy the Apache Wink Application to a web container (Tomcat).

This is simple, Just right click the Eclipse project and Select Export –> WAR file and specify the correct WAR file name and specify the location to be deployed. You can directly specify the webapps folder of the Tomcat engine that you wish to deploy this application. Restart the Tomcat server. Lets assume that the WAR file name as wink_service_01.war.

Step 7: Testing the Application

For this you can either use a simple browser or any other tool to carry out this task. If I use a normal browser to test this,
To list all the student details, –> http://localhost:8080/wink_service_01/rest/students
To list the student with StudentID “1″–> http://localhost:8080/wink_service_01/rest/students/1

The Source Code

The Source Code is available here

VN:F [1.9.22_1171]
Rating: 10.0/10 (2 votes cast)
VN:F [1.9.22_1171]
Rating: +4 (from 4 votes)
Go to Top