Archive

Posts Tagged ‘Web Services’

An overview of a SOA Architecture

09/11/2012 1 comment

Hi, Folks!

I know it’s been quite a while since I’ve last posted in here… lots of projects ­čÖé

As things are evolving on SOA, I would like to give my two cents here about SOA Architectures. So, just to begin the subject, I would like to introduce…

What is SOA?

SOA stands for Service-Oriented Architecture (as you probably know by now ­čśë ). But, WTH is a service?

The efforts to define a service have gone really far, but no one seems to be able to really define a service. People are able to describe a service by how it should be, not by what it actually is. According to Thomas Erl (http://www.soaglossary.com/service_orientation.php), a service should:

  • Have a standardized service contract
  • Promote loose coupling
  • promote abstraction
  • be reusable
  • be autonomous
  • be stateless
  • be discoverable
  • be composable

OK, but what does it mean in terms of real-world services?

It means that you should design your services to be as granular as possible to promote composability and reusability. It also means that these services should be stateless (i.e., they should not assume that the server is in a state a previous request set it on); these services should be autonomous (i.e., they should not depend on other services to perform it’s actual task – unless, of course, we are talking about a composition); they should be discoverable (i.e., you should have some kind of directory where you can find the service that performs the task you are looking for); they should be loose coupled to each other; and last but not least, they should have a contract you can rely on – one that is standardized such as your clients will not have trouble when using your service.

Note that, so far, no one has talked about WS-* or REST. That’s because SOA is not defined in terms of technology, or tools, or whatever. SOA is based on a set of good practices, in order to ensure ROI (Return of Investment). BTW, of course SOA is not that cheap (studies prove that a brand new implementation of SOA is 30% more expensive in the initial phases, but they pay off over time).

But, getting back to technology… nor WS-* nor REST define SOA. You can have lots of WS-* Web Services on your architecture, or lots of REST services on your architecture, but still have no SOA. Again: SOA is based on practices, not technology. Of course, enterprises over the world have developed tools to help achieve the goals (some of them don’t even give so much help ;)), but the tools are not the end – they are the means.

If you define your architecture such as enough business logic is exposed as services (again, no one is talking about technology here), then you will have SOA.

Buuuut… here comes the little lines at the bottom.

Why my company always talk about technology and vendors when it comes to SOA?

The truth is that it can be very hard to promote SOA within the terms mentioned above (or, at least, to do so without tools). That’s why companies almost always have SOA with WS-* and tooling. It’s really hard to have directories of services without any kind of tools, and it’s very hard to promote service discovery without WSDL’s (OK, REST has got WADL, but it hasn’t got to a level where every REST service has one. Actually, REST doesn’t need WADL, and that’s not the case with WS-* services).

Also, even that your company decides to make its own tooling to promote these practices, it can be very hard as well to comply with non-functional requirements, such as performance, monitorability, scalability, etc. Remember that these services are granular, and that the traffic over network is XML/JSON. Imagine lots of services doing marshalling / unmarshalling of these data everywhere.

So, the first tool that came around to solve these problems is the ESB.

WTH is an ESB?

ESB stands for Enterprise Service Bus. As the name says, it is nothing but a bus to your services. But, wait… a bus that takes what to what?

The responsability of an ESB is to map requests from a client (usually, these clients see a service, with a contract and everything else) to… somewhere. Really, the ESB may lead to a WS-*, a REST service, the file system, BPEL (I’ll talk about this one later), JMS, and lots of other protocols. Actually, it should be able to transform any protocol to any protocol. But, of course, this very core of an ESB may lead to accomplish several other purposes. Take monitorability, for example: if an ESB will map these protocols, and data will pass through it, it may take metrics over it, and map response times, success rate, failure rates, fire alerts when these metrics reach a given threshold, and so on. Also, it may guarantee security to these services (by exposing only the ESB for clients, and inserting some assertions to routings), as well as several other things.

Also, an ESB may promote security by an application level. They usually have a feature known as throttling, which prevents a client from sending too much data (so much it can cause service failure). Of course, these kind of stuff should be ensured within XML Schemas, but they know detailed schemas are hard to maintain inside an ecosystem of dozens, hundreds or even thousands of web services.

But what an ESB does not do is to recompose requests. Remember service composability? That’s not the function of an ESB (although some of them even do it). Service composability requires a more business-oriented tool, something like…

BPEL

BPEL stands for Business Process Execution Language. It is the industry’s standard for composing workflows, made of several web service calls. What it does is not only the workflow, but handling of several issues, like:

  • expose the composition as a web service itself;
  • rolling back of failed transactions (known as compensatory transactions);
  • keeping the state of transactions, both in case of server failure as for auditing;
  • optimizing the calls to the several web services it may compose;
  • keeping the flow visual, i.e., to ease the development and/or auditing.

As you may have realized, BPEL is specialized in keeping state of stuff. I know, web services should be stateless, and BPEL is – from the point of view of the client. But it keeps the state of the compositions for more pragmatic stuff like the mentioned above. It is conceptually different from an ESB as ESB’s should not keep the state of the requests, anywhere.

So, how to organize these together?

A good architecture should leverage all non-functional requirements and, at the same time, be able to change whenever it is needed. It’s a bit hard to talk about this subject in a single blog post, but within the mentioned features above, a good architecture could be like this:

Yes, I totally suck at drawing =/

As the picture doesn’t make justice to the thought, let me explain it:

As an ESB does every kind of transformation, protocol A -> protocol B (doesn’t mean, of course, that A is different from B), it is fair to place all data traffic over it, just to place metrics, alerts, throttling, and everything else, onto it. BPEL, WS-* services, REST services, and so on, will be accessible through it, and BPEL will not see directly the other services, but will reference the services that are already placed inside the ESB.

Of course this architecture has a huge drawback: too much overhead inside one piece. The ESB, here, must be intensively took care of (I hope your company has some baby sitters! =D). It means that maybe a few network cards, some gigabytes of RAM, and clustered to some four, five nodes. But believe me, depending on the number of services your company has (maybe the very size of the company), it totally pays off. Of course, maybe does not make sense if you have only a few services, but I’m talking here of a few hundreds (or thousands) of services.

Conclusion

You should not believe a single word that’s written here =D (Just kidding!)

Architectures don’t come inside a box. You need to be very very extra judiciously to analyze whether you need to place these kind of stuff in your company. Perhaps you don’t really need BPEL. Perhaps you don’t really need an ESB at all. Perhaps you need it but you can’t afford it. Perhaps it makes more sense having REST services than WS-* and these bunch of stuff. Every single aspect of SOA comes with positives and negatives. What you need to do is to analyze these points and carefully think if you really need the positives and if you can handle the negatives.

How to develop a standalone SSL web service

12/08/2010 14 comments

How to develop a standalone SSL web service

Hi! Today, I┬┤m gonna show you how to develop a simple SSL web service. Please note that this is not a “enterprise” way of developing a secure web service, but this may be very useful for testing purposes.

Constraints

To develop this service, you need to use a Sun/Oracle JVM (I tested with 1.6 VM, but should work with 1.5, too). This is not gonna work in any other kind of VM. Also, you need to have JAX-WS in your classpath.

The code

The code begins with the development of the web service itself. I used a standard JAX-WS service as an example, so my service looks like this:


@WebService
public class SOAPService {

	public String test() {
		return "Hello, SSL world!";
	}	
}

Next, we may use Java┬┤s Endpoint class to create our object as an web service. The code is like

Endpoint endpoint = Endpoint.create(new SOAPService());

At this point, you need to create the server, and to create the server, you need a .jks (Java Keystore) file. You may create this file using JDK┬┤s (or JRE┬┤s) tooling, but I prefer using a GUI to do so. Personally, I like Lazgo┬┤s KeyStore Explorer (available here). I won┬┤t get in details here on how to create the JKS file; if you don┬┤t know how to do it, you may want to have a look here.

Note: be aware that the CN attribute of your certificate must be equal to your host┬┤s name!

After creating the JKS file, we are ready to create our HTTPS server. I won┬┤t explain this code very much, as it should be pretty self-explanatory:


public static void main(String[] args) throws Exception {
		Endpoint endpoint = Endpoint.create(new SOAPService());
		SSLContext ssl =  SSLContext.getInstance("SSLv3");
		
		
		KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); 
		KeyStore store = KeyStore.getInstance(KeyStore.getDefaultType());


		//Load the JKS file (located, in this case, at D:\keystore.jks, with password 'test'
		store.load(new FileInputStream("D:\\keystore.jks"), "test".toCharArray()); 

		//init the key store, along with the password 'test'
		kmf.init(store, "test".toCharArray());
		KeyManager[] keyManagers = new KeyManager[1];
		keyManagers = kmf.getKeyManagers();
		
		

		//Init the trust manager factory
		TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());

		//It will reference the same key store as the key managers
		tmf.init(store);
		
		TrustManager[] trustManagers = tmf.getTrustManagers();
		
		
		ssl.init(keyManagers, trustManagers, new SecureRandom());

		//Init a configuration with our SSL context
		HttpsConfigurator configurator = new HttpsConfigurator(ssl);
		

		//Create a server on localhost, port 443 (https port)
		HttpsServer httpsServer = HttpsServer.create(new InetSocketAddress("localhost", 443), 443);
		httpsServer.setHttpsConfigurator(configurator);
		
		
		//Create a context so our service will be available under this context
		HttpContext context = httpsServer.createContext("/test");
		httpsServer.start();
		

		//Finally, use the created context to publish the service
		endpoint.publish(context);
		
		

	}


And voilà! That should be enough to your service be available under SSL. With this code, the wsdl of the service should be available under https://localhost:443/test?wsdl.

Please note that, at the time that I developed this service, I had some trouble with the generated WSDL, specifically with the port address and references to schema files. A reasonable work around for this problem (if you have it too) is to download the files (WSDL, schemas, and so on) and fix it by hand.

See ya!

How to intercept web services ingoing/outgoing messages

Hi, everybody! I┬┤m just passing around to show a technique to easily intercept JAX-WS web services messages. It is a quick piece of knowledge, and it is based on three simple steps.

I know that you always say, first, what I need to know…

That┬┤s right. First of all, be aware that I tested it with EJB┬┤s services, and I don┬┤t know if it works with other types of exposed web services. Also, note that I present here a solution that works with annotated web services.

Ok, show me the solution

Step #1: Annotate your web service┬┤s class with @HandlerChain:

package com.alesaudate.webservices;

@WebService
@HandlerChain(file="handlers.xml") //Here, you need to reference a configuration file. In this case, it got to be in the same package as the class
public class MyService {

//...


}

Step #2: Create a configuration file, like:

<?xml version="1.0" encoding="UTF-8"?>
<jws:handler-chains xmlns:jws="http://java.sun.com/xml/ns/javaee">

  <jws:handler-chain>
    <jws:handler>
      <jws:handler-name>MimeHandler</jws:handler-name>
      <jws:handler-class>com.alesaudate.webservices.MimeTypeHandler</jws:handler-class>      
    </jws:handler>
</jws:handler-chain>
  
</jws:handler-chains>

(Note that it need to be named “handlers.xml”, as referenced in the annotation)

Step #3: Create a interceptor for the class:

package com.alesaudate.webservices;

import java.util.Set;

import javax.xml.namespace.QName;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPMessage;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;

public class MimeTypeHandler implements SOAPHandler<SOAPMessageContext>{

	public Set<QName> getHeaders() {
		return null;
	}

	public void close(MessageContext context) {
		
	}

	public boolean handleFault(SOAPMessageContext context) {
		return true;
	}

	public boolean handleMessage(SOAPMessageContext context) {
		try {
                                          context.getMessage().getMimeHeaders().setHeader("Content-Type", "text/xml");
		} catch (SOAPException e) {
			throw new RuntimeException(e);
		}
		return true;
	}
	

}

Pretty easy, right? I┬┤m taking for granted that the interceptor and the configuration file are pretty self-explanatory, but if you have any doubts, don┬┤t hesitate asking me, OK?

Bye!

Patterns of System Integration #1: Services mediator

Disclaimer: this pattern does not refer to Oracle┬┤s SOA Suite 11g Mediator, nor any Thomas Erl┬┤s Patterns (although it looks like the implementation of pieces of some of his patterns).

So, give me a brief description on what it is about.

People who are used to work with SOA are, usually, used to work with ESB┬┤s – I say “ESB┬┤s”, plural, to mean different kinds from different vendors of ESB – and BPEL. ESB┬┤s are often used to justify decoupling of clients from service providers. I think it is great, but people usually forget that ESB┬┤s, as long as they are too decoupled from the system, do not provide so much advantages as it should. So, usually, ESB┬┤s are a layer of extra complexity to systems (the exception are some odd situations that don┬┤t fit the usual description). Sometimes, you need some piece of software that is more intimate to the system, that can interact in an easier way to the system (like some easy way to audit calls, log them, place warns on whether systems are responding or not – therefore avoiding issues on being overloaded due to slow responsiveness of external services -, etc.). So, thinking about it, I developed this pattern.

Explain it better, what is it about?

People need to be in control of their applications. People should be in control of their applications. Usually, that┬┤s not what happens to a SOA-based app, because we rely too much on external tools and forget that good things may be done at home, too. So, you don┬┤t need to use a service composition to audit external services I/O, for example. If you would do so by today┬┤s standards, you would build a service to do the auditing, then group the external service and the audit service into one piece of service composition, then offer the composition┬┤s contract to the client… too much work. You should not build separate services unless you need them as services (after all, SOA is about getting the IT to work along with the business, right? So, it should not try to add extra pieces of complexity, like one more service, to the business, right?); so, you should approach the problem with another solution, like intercepting the messages according to your programming language way of doing so.

So, my pattern is about intercepting outgoing messages / incoming responses by building transparent, language-friendly units, in a manner that, if you need extra capabilities but do not want (or do not need) to build extra services, you should consider applying this pattern.

How to do it?

First, you should take the original WSDL and override it, replacing the original address – a technique shown here. I┬┤m gonna call this service “shell service”, from now on. The shell service┬┤s purpose is to provide the capability of adding this extra logic, which means it should be built in the main programming language you use in your application. To build it, you should use the same logic as the mentioned post, but should modify the provider to something like the following:



package com.alesaudate.webservices;

import javax.xml.soap.SOAPMessage;
import java.net.URL;
import java.util.Iterator;
import javax.xml.namespace.QName;
import javax.xml.ws.Dispatch;
import javax.xml.ws.Service;


public class SOAPProvider {

	public Dispatch<SOAPMessage> getDispatcher (String wsdl, String namespace, String servicename, String portName){

		try {
			//create a representation of the service
			Service service = Service.create(new URL(wsdl), new QName(
					namespace, servicename));

			final Iterator<QName> ports = service.getPorts();

			QName methodToBeCalled = null;

			//Select the port to be called
			if (portName == null)
				methodToBeCalled = ports.next();

			else {
				while (methodToBeCalled == null || !methodToBeCalled.getLocalPart().equals(portName)) {
					methodToBeCalled = ports.next();
				}
			}

			//Create the dispatcher, given the data.
			Dispatch<SOAPMessage> dispatch = service.createDispatch(
					methodToBeCalled, SOAPMessage.class, Service.Mode.MESSAGE);

			return dispatch;
		} catch (Exception e) {
			throw new RuntimeException("Error calling web-service", e);
		}
	}
}
package com.alesaudate.webservices;

import javax.xml.soap.SOAPMessage;
import javax.xml.ws.Provider;
import javax.xml.ws.ServiceMode;
import javax.xml.ws.WebServiceProvider;
import javax.xml.ws.Service.Mode;

@ServiceMode(Mode.MESSAGE)
@WebServiceProvider(portName="blogSOAP",
		serviceName="blogService",
		targetNamespace="http://alesaudate.com/webservices",
		wsdlLocation="WEB-INF/wsdl/blog.wsdl")
public class MySOAPProvider implements Provider<SOAPMessage>{


	public static final String ORIGINAL_WSDL = "http://localhost/SampleService?wsdl";
	public static final String ORIGINAL_SERVICE = "sampleService";
	public static final String ORIGINAL_PORT = "samplePort";
	public static final String ORIGINAL_NAMESPACE = "sampleNamespace";

	private SOAPProvider provider;
	
	public MySOAPProvider() {
		this.provider = new SOAPProvider();
	}


	//You may add any extra logic here.
	@Override
	public SOAPMessage invoke(SOAPMessage request) {
		Dispatch<SOAPMessage> dispatcher = provider.getDispatcher(ORIGINAL_WSDL, ORIGINAL_NAMESPACE , ORIGINAL_SERVICE,ORIGINAL_PORT);
		SOAPMessage response = dispatcher.invoke(request);
		return response;
	}

}

Just to remind the reader, I would like to mention that this technique has been shown here.

Conclusion

I have shown here a design pattern that I call Services Mediator. Basically, it is the same that an Enterprise Service Bus does, but with the difference that it must be implemented in the same language that the application uses, providing, then, more control to the application programmer. So, at any time the services need some business logic, but does not necessarily need to use services to do so, the programmer may add this logic inside the services shell.

How to create a contract-first web service (or: how to create a web service that handles XML)

08/31/2010 1 comment

Hello! Today, I┬┤m gonna show you a sample on how to develop a contract-first web service in java. To do so, you are gonna need:

  • An Apache Tomcat (or any Application Server that is compatible with JAX-WS)
  • A JAX-WS runtime (I used the RI, that I got from here – most application servers already have)

Now, as it is a contract-first web service, we need the contract. I used this one:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://alesaudate.com/webservices" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="blog" targetNamespace="http://alesaudate.com/webservices">
  <wsdl:types>
    <xsd:schema targetNamespace="http://alesaudate.com/webservices">
      <xsd:element name="operation">
        <xsd:complexType>
          <xsd:sequence>
            <xsd:element name="request" type="xsd:string"/>
          </xsd:sequence>
        </xsd:complexType>
      </xsd:element>
      <xsd:element name="operationResponse">
        <xsd:complexType>
          <xsd:sequence>
            <xsd:element name="response" type="xsd:string"/>
          </xsd:sequence>
        </xsd:complexType>
      </xsd:element>
    </xsd:schema>
  </wsdl:types>
  <wsdl:message name="operation">
    <wsdl:part element="tns:operation" name="parameters"/>
  </wsdl:message>
  <wsdl:message name="operationResponse">
    <wsdl:part element="tns:operationResponse" name="parameters"/>
  </wsdl:message>
  <wsdl:portType name="blog">
    <wsdl:operation name="blogOperation">
      <wsdl:input message="tns:operation"/>
      <wsdl:output message="tns:operationResponse"/>
    </wsdl:operation>
  </wsdl:portType>
  <wsdl:binding name="mySOAPBinding" type="tns:blog">
    <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
    <wsdl:operation name="blogOperation">
      <soap:operation soapAction="http://alesaudate.com/webservices/SampleOperation"/>
      <wsdl:input>
        <soap:body use="literal"/>
      </wsdl:input>
      <wsdl:output>
        <soap:body use="literal"/>
      </wsdl:output>
    </wsdl:operation>
  </wsdl:binding>
  <wsdl:service name="blogService">
    <wsdl:port binding="tns:mySOAPBinding" name="blogSOAP">
      <soap:address location="http://localhost:8080/WebServices/provider"/>
    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>

Now, we must provide an implementation class (or, how I like to call, where the magic happens =P ). Here is my implementation:

package com.alesaudate.webservices;

import javax.xml.soap.SOAPMessage;
import javax.xml.ws.Provider;
import javax.xml.ws.ServiceMode;
import javax.xml.ws.WebServiceProvider;
import javax.xml.ws.Service.Mode;

@ServiceMode(Mode.MESSAGE)
@WebServiceProvider(portName="blogSOAP", 
		serviceName="blogService",  
		targetNamespace="http://alesaudate.com/webservices", 
		wsdlLocation="WEB-INF/wsdl/blog.wsdl")
public class MySOAPProvider implements Provider<SOAPMessage>{

	@Override
	public SOAPMessage invoke(SOAPMessage request) {
		try {
			request.writeTo(System.out);
		} catch (Exception e) {
			e.printStackTrace();
		} 
		return request;
	}

}

Please note that this refers to a WEB-INF directory. So, as you may have guessed by now, it MUST run on a web project (.war). Other forms of java files, like .jar or .ear are unable to run this code.

Now, we must provide what I call “the glue”: files that provide the binding. For the RI implementation, we must provide a file called sun-jaxws.xml and place it under the WEB-INF directory. For our project, it has the following structure:

<endpoints
    xmlns="http://java.sun.com/xml/ns/jax-ws/ri/runtime"
    version="2.0">

    <endpoint
        name="example"
        implementation="com.alesaudate.webservices.MySOAPProvider"
        wsdl="WEB-INF/wsdl/blog.wsdl"
        service="{http://alesaudate.com/webservices}blogService"
        port="{http://alesaudate.com/webservices}blogSOAP"
        url-pattern="/provider" />

</endpoints>

We also need to insert the right entries into web.xml:

<listener>
        <listener-class>com.sun.xml.ws.transport.http.servlet.WSServletContextListener</listener-class>
    </listener>
    <servlet>
        <servlet-name>provider</servlet-name>
        <servlet-class>com.sun.xml.ws.transport.http.servlet.WSServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>provider</servlet-name>
        <url-pattern>/provider</url-pattern>
    </servlet-mapping>

The URL pattern, here, is the address where our web service will answer requests and will provide it┬┤s contract.

Having reached this point so far, we need to place JAX-WS lib┬┤s on the common library directory under Tomcat (for application servers like JBoss, you may skip this step).

And that┬┤s all! Accessing the address http://localhost:8080/WebServices/provider?wsdl has shown me the WSDL that I quoted above, how about you?

You may check the code that I used here at the downloads section.

See ya!

A Simple Explanation on what an ESB is…

Today, I would like to say just a few words on ESB┬┤s. As you may know, I┬┤m a Java developer, but I work specifically with SOA (Service-Oriented Architectures) and Service-Oriented Computing in general. So, my day-by-day tools include not only those of Java, but some known as belonging to SOA stack, like BPM, BPEL and ESB.

ESB ?

ESB is an acronym for Enterprise Service Bus. It is a tool designed to provide flexibility to SOA, and refers often to the Message Broker pattern. It┬┤s use often provides flexibility to SOA, but, indeed, adds more complexity to the overall architecture.

Generally, an ESB must provide or enhance the following features:

  • Services virtualization
  • Services security
  • Services management
  • Services availability
  • (other) SOA Messaging Patterns
  • WS-* specs support

Services virtualization

To be succeeded on its intent, the Enterprise Service Bus must have the ability to “hide” the underlying services. Such capability is achived by deploying services on the very own ESB, with abstract service contracts, or by “hiding” them, providing a new service contract and then routing messages to the underlying implementation. This capability is very important because by doing so, the ESB can:

  • Re-route messages (for example, if a service is not available, it may call another one instead)
  • Add security and SLA (Service Level Agreements) layers
  • Group (or split) service capabilities from (or to) several different service contracts
  • Hide informations on implementations (for example, suppose that that we don┬┤t want the client to know that the underlying implementation is a JMS service – yes, it can be one!)
  • And the main purpose: provide service decoupling

The last quoted capability is so important that it deserves its own explanation: the structure of a concrete service contract includes a section where the service address is specified. But, suppose that I can not guarantee that this address will always be the same. If this service address changes, all clients will be impacted, and, for sure, that is not what we expect when implementing SOA. Also, suppose that a service model changes (which, of course, is highly undesirable if someone wants to succeed when adopting SOA, but it may happen in the real world). The ESB may completely override service contracts, routing messages to the real implementation and even transforming messages so the can be compliant to the real implementation (just a note here: transformations, in SOA, are very undesirable as they decrease the system performance, but, still, they may be neccessary).

Services security

Suppose that you want a given service to be secure. This service needs muthual authentication through certificates, but still, it needs to be very, very, very (very!) fast, as you cannot tolerate it to delay too much. Now, consider that this same service is going to be consumed both from the inside of your application (still being used as a service) and from outside. The outside requests must be handled in a secure way in opposite to the inside ones. Then, you can place the whole security stuff in the ESB, as it does the rest. This approach has a bonus, which is that you are sppliting processing need through layers and machines, as the ESB machine processes the security layer and the service layer machine processes the logic itself (along with some XML parsing, for both of them).

Services management

Well, services management is pretty wide term, but as far as I concern, the main pieces that an ESB provides in this sense are:

  • Services “split” capability
  • Services “regroup” capability (in oppose to the previous topic)
  • message filtering
  • add SLA capabilities

So, the “split” and “regroup” has been mentioned in the topic of services virtualization, as the ability to “rewrite” service contracts. Message filtering is in the sense that, generally, the ESB transcends the web services capabilities and that it can filter messages. A practical example of this filtering is that, suppose that you set in place a query service and that a malicious user place a query that intends to cause overflow on the server, making it to crash. The ESB can cut off the request and/or the response, limiting, for example, the size of the message, allowing to pass only messages below 8 megabytes.

Services availability

An ESB can enable high availability / load balancing capabilities for web services, increasing the failure recovery hability of the SOA application. Just in case you ask: this is an example of why one of the services design principles is to make statelss services. So, if any of you ask me how to make a stateful service, it is more likely that I answer you something like “you don┬┤t need this” rather than “do x, y, and z”.

SOA Messaging Patterns

There are lots of SOA (and Enterprise Integration in general) patterns that an ESB implements. I would be here for at least a couple of hours writing about them, but I would be repeating what is already catalogued, and you can check these patterns at SOAPatterns.org website.

WS-* specs support

A good ESB must comply with a few standards, as this is one of the major goals of SOA. The WS-* specs are a couple of specs to address some common issues related to web services, like distributed transactions (WS-Transaction), dynamic addressing (WS-Addressing) and security (WS-Security), just to mention a few. You can check a more complete list of specifications here.

So, what am I waiting for? I want to use an ESB!!

Hold on. There are lots and lots of discussions on whether it is good or not to place an ESB over a SOA architecture, and how far the benefits go and how far the headaches go. I would only be awakening the flame war of “to ESB or not to ESB” by exposing my opinion here, so I would like to keep it for myself. If you want to check it for yourself, have a look at this google query.

How to dynamically select a certificate alias when invoking web services

08/09/2010 11 comments

Hi, boys and girls! First of all, I would like to say that, yes, this blog┬┤s posts are gonna be all written in English, so they can affect more people around the world. That said, I also would like to say that, although the language has changed, the content is gonna be the same, so I will write and, where it fits, make a critical analysis on the solution.

So, what is the problem?

Web services that use certificates are specially tough to invoke. Along with the complexity that involves almost everything that concern to web services, it also involves the complexity that involves almost everything that concerns to secure communication over the web. So, putting these problems together may give a very strong headache to whoever that wishes to invoke secure web services in Java. Invoking services in a secure way is relatively easy when they do not use more than one certificate in the same VM. But, when it involves more than one certificate, it may be useful to give aliases to the certificates, and to have the ability to select between these certificates in runtime. Also, it may be useful even to change from keystore to keystore in runtime. So, the intent, here, is to provide a simple solution to this problem.

What am I gonna need?

First, you need to assemble a key store and a trust store. I┬┤m not gonna show how to do it here; however, the reader may google it (using a query like this one) to find out how to do it. Second, you must (obviously) have the contract for the service to be invoked. Be warned that, probably, you won┬┤t be able to access it directly, because it will be protected by HTTPS. So, get in touch with the responsibles for the service that you want to invoke. Third, and finally, remember to read carefully the analysis that I am providing at the end of the text (the penalty for not accomplishing this requirement may be an incompatibility between environments).

I┬┤m aware of the requirements, let┬┤s go!

The code consists of the following pieces:

  • A SSL Socket Factory Generator
  • An Alias Selector
  • A Service Invoker

The code for the SSL Socket Factory Generator is like the one below:

import java.io.FileInputStream;
import java.io.IOException;
import java.net.Socket;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.Principal;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;
import java.util.logging.Logger;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509KeyManager;


public class SSLSocketFactoryGenerator {
	
	
	private String alias = null;
	private String keyStore = null;
	private String trustStore = null;
	
	public SSLSocketFactoryGenerator (String alias, String keyStore, String trustStore) {
		if (alias == null)
			throw new IllegalArgumentException("The alias may not be null");
		this.alias = alias;
		this.keyStore = keyStore;
		this.trustStore = trustStore;

	}
		

	public SSLSocketFactory getSSLSocketFactory() throws IOException, GeneralSecurityException {
    
		KeyManager[] keyManagers = getKeyManagers();
		TrustManager[] trustManagers =getTrustManagers();
    
    
		//For each key manager, check if it is a X509KeyManager (because we will override its 		//functionality
		for (int i=0; i<keyManagers.length; i++) {
			if (keyManagers[i] instanceof X509KeyManager) {
				keyManagers[i]=new AliasSelectorKeyManager((X509KeyManager)keyManagers[i], alias);
			}
      		}
    

		SSLContext context=SSLContext.getInstance("SSL");
		context.init(keyManagers, trustManagers, null);

    
		SSLSocketFactory ssf=context.getSocketFactory();
    		return ssf;
  	}	
		
	
	public String getKeyStorePassword() {
		return "keyStorePassword";
	}
	
	public String getTrustStorePassword() {
		return "trustStorePassword";
	}


	public String getKeyStore() {
		return keyStore;
	}

	public String getTrustStore() {
		
		return trustStore;
	}


	private KeyManager[] getKeyManagers()
	throws IOException, GeneralSecurityException
	{
		
		//Init a key store with the given file.
		
		String alg=KeyManagerFactory.getDefaultAlgorithm();
		KeyManagerFactory kmFact=KeyManagerFactory.getInstance(alg);

		
		FileInputStream fis=new FileInputStream(getKeyStore());
		KeyStore ks=KeyStore.getInstance("jks");
		ks.load(fis, getKeyStorePassword().toCharArray());
		fis.close();

		//Init the key manager factory with the loaded key store
		kmFact.init(ks,  getKeyStorePassword().toCharArray());


		
		KeyManager[] kms=kmFact.getKeyManagers();
		return kms;
	}

	
	protected TrustManager[] getTrustManagers() throws IOException, GeneralSecurityException
	{
    
		String alg=TrustManagerFactory.getDefaultAlgorithm();
		TrustManagerFactory tmFact=TrustManagerFactory.getInstance(alg);
    
    
		FileInputStream fis=new FileInputStream(getTrustStore());
		KeyStore ks=KeyStore.getInstance("jks");
		ks.load(fis, getTrustStorePassword().toCharArray());
		fis.close();

    
		tmFact.init(ks);

    
		TrustManager[] tms=tmFact.getTrustManagers();
		return tms;
	}
}

So, the SSLSocketFactory will act as a provider for our secure sockets. Note that the class AliasSelectorKeyManager is our alias selector. It┬┤s code is shown below:


import java.net.Socket;
import java.security.Principal;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;

import javax.net.ssl.X509KeyManager;

public class AliasSelectorKeyManager implements X509KeyManager{

	private X509KeyManager sourceKeyManager=null;
	private String alias;

	public AliasSelectorKeyManager(X509KeyManager keyManager, String alias)
	{
		this.sourceKeyManager=keyManager;	     
		this.alias = alias;

	}

	public String chooseClientAlias(String[] keyType, Principal[] issuers,
			Socket socket)
	{	
		boolean aliasFound=false;

		//Get all aliases from the key manager. If any matches with the managed alias,
		//then return it.
		//If the alias has not been found, return null (and let the API to handle it, 
		//causing the handshake to fail).

		for (int i=0; i<keyType.length && !aliasFound; i++) {
			String[] validAliases=sourceKeyManager.getClientAliases(keyType[i], issuers);
			if (validAliases!=null) {
				for (int j=0; j<validAliases.length && !aliasFound; j++) {
					if (validAliases[j].equals(alias)) aliasFound=true;
				}
			}
		}

		if (aliasFound) {
			return alias;
		}
		else return null;
	}


	public String chooseServerAlias(String keyType, Principal[] issuers,
			Socket socket)
	{
		return sourceKeyManager.chooseServerAlias(keyType, issuers, socket);
	}

	public X509Certificate[] getCertificateChain(String alias)
	{
		return sourceKeyManager.getCertificateChain(alias);
	}

	public String[] getClientAliases(String keyType, Principal[] issuers)
	{
		return sourceKeyManager.getClientAliases(keyType, issuers);
	}

	public PrivateKey getPrivateKey(String alias)
	{

		return sourceKeyManager.getPrivateKey(alias);
	}

	public String[] getServerAliases(String keyType, Principal[] issuers)
	{
		return sourceKeyManager.getServerAliases(keyType, issuers);
	}

}

So, at this point we have a custom SSLSocketFactory, that can generate a custom selection for aliases. The final step is to force our web services to use it. To do so, the trick is to generate a Dispatch, which is a JAX-WS interface responsible for calling web services. The Dispatch may accept custom parameters to do the invocations, and we may pass a SSLSocketFactory as parameter, by using a Sun interface called JAXWSProperties. The code is shown below:


public Dispatch<SOAPMessage> getDispatcher(String alias) throws IOException, GeneralSecurityException {
		String namespace = "http://alesaudate.com/Services/";
		String wsdlLocation = "http://alesaudate.com/Services/MyService?wsdl";
		String serviceName = "MyService";
		String portName = "MyServiceSoap";
		String soapActionUri = "http://alesaudate.com/Services/testAction";
		
		String keyStoreLocation = "C:\\chains\\myKeystore.jks";
		String trustStoreLocation = "C:\\chains\\myTrustStore.jks";
		

		//Load a dispatcher with the givend data.
		Dispatch<SOAPMessage> dispatcher = getDispatcher(wsdlLocation, namespace, serviceName, portName);
		
		//Create our custom SSLSocketFactory
		SSLSocketFactory socketFactory = new SSLSocketFactoryGenerator().generateSocketFactory(alias, keyStoreLocation, trustStoreLocation);

		//Be aware: don┬┤t use the com.sun.xml.internal.ws.developer.JAXWSProperties interface instead !!!!
		dispatcher.getRequestContext().put (com.sun.xml.ws.developer.JAXWSProperties.SSL_SOCKET_FACTORY, socketFactory);
		
		dispatcher.getRequestContext().put(BindingProvider.SOAPACTION_URI_PROPERTY, soapActionUri);
		
		return dispatcher;
	}
	
	
	public Dispatch<SOAPMessage> getDispatcher (String wsdl, String namespace, String servicename, String portName){
	
		try {
			//create a representation of the service
			Service service = Service.create(new URL(wsdl), new QName(
					namespace, servicename));
			
			
			final Iterator<QName> ports = service.getPorts();
			
			QName methodToBeCalled = null;
			

			//Select the port to be called
			if (portName == null)
				methodToBeCalled = ports.next();
			
			else {
				while (methodToBeCalled == null || !methodToBeCalled.getLocalPart().equals(portName)) {
					methodToBeCalled = ports.next();
				}
			}
			
			//Create the dispatcher, given the data.
			Dispatch<SOAPMessage> dispatch = service.createDispatch(
					methodToBeCalled, SOAPMessage.class, Service.Mode.MESSAGE);
			

			return dispatch;
		} catch (Exception e) {
			throw new RuntimeException("Error calling web-service", e);
		}
		
	}


Here, I create the dispatch to invoke the service. All I have to do, now, is to create a SOAPMessage and use the invoke method, on the Dispatch interface, to invoke the web service in a secure way. If it interests the reader, you may improve the code to use some sort of JAXB piece to create a SOAPMessage from an object.

What should I pay attention to?

The reader must be aware that JAXWSProperties is part of a Sun library and, so, may not work with some application servers and/or Virtual Machine implementations. I tested it using Sun┬┤s JDK 1.6.0_20, with a JBoss AS 5 (which already has the JAR that contains JAXWSProperties). Also, be aware that the solution presented here is not easy to use, and the reader may be interested in creating some sort of Object-to-SOAPMessage translator (maybe using Reflections?). Finally, be sure that speed is not critical, because this code is going to generate a new SSLSocketFactory (including a IO call) to every call, so it may be more interesting to use some kind of cache (of the SSLSocketFactory), in order not to create a new one at every call, but to reuse them.

Nice coding!