Archive

Posts Tagged ‘quick post’

Protecting your services with a simple fuse..

Michael Nygard, in his book Release It! Design and Deploy Production-Ready Software describes a pattern he called Circuit Breaker. It is based on the idea of fuses, that is, anything that may be dangerous should be put around a safe structure, that may disable the operation requests if it has any chance to do any harm to the application itself or others. It is best described through the image (click to enlarge):

The Circuit breaker pattern, as described by Michael Nygard

The flow is like that: the dangerous operation has the fuse as a shell. The first state, “closed fuse”, has a counter of failed invocations and a threshold. When the client produces an invocation, it allows the invocation to pass through. If the call succeeds, then resets the counter. If it fails, increment the counter. If the counter reaches the threshold, it disables the fuse, going to the “open fuse” state. This state has a variable that represents an ammount of time and another one representing the moment in time when it has become the active state. Any call to the dangerous operation in this state will cause it to fail without even invoking the operation. When it is in this state for the amount of time specified in the variable, it decides that the call deserves another chance. So the invocation goes to the “half open fuse”. This state tries to invoke the operation again. If it fails, go to the open state again, resetting the timer. If it succeeds, go to the closed state again, resetting the counter of failed invocations.

OK, nice pattern, but what does it have to do with SOA?

The magic in this pattern (and the whole book) is that it brings light to subjects that most developers don´t give enough attention. One of these subjects is that you cannot rely on the network. Final. I have never seen any thrustable network (and I believe you haven´t, too!), so, as long as SOA is a kind of distributed architecture that relies on the network and we cannot rely on the network, so we can´t rely on services either! So, as long as services are unthrustable, we can apply this pattern, to:

  • Ensure that we won´t get stuck waiting for services that might never return;
  • Ensure that, if the server that is holding the web service is drowning from lots of invocations, at least we are not the ones that are gonna disable it for good;
  • And many many other good reasons to do so. Read the book 😉

As Michael himself doesn´t give any hints on the implementation of such a pattern, I decided to implement it, and you can download it from the downloads section. It is very simple, as it doesn´t allow only web services to be invoked via the pattern, but any other kind of dangerous operation too. You can modify the code the way you want to achieve your desire. My hint is that, allied to stuff like AOP and interceptors in general, you may do it the ultimate solution to never, ever have this kind of problem again.

Cheers!

Quick Post: Integrating Spring and Jersey

02/02/2011 2 comments

When: When you need Spring to manage Jersey´s libraries, but still want to be free to develop your services using JAX-RS.

When not: If your team does not know REST, maybe it´s not a good idea to use it in development, because REST has its own culture – Uniform Interfaces, Hypermedia, the concept of Resource-Oriented, etc.

How:

BaseEntity.java

package com.alesaudate.domain;

import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
import javax.persistence.Version;

import org.hibernate.validator.ClassValidator;
import org.hibernate.validator.InvalidValue;


@MappedSuperclass
public abstract class BaseEntity {
	
	@Id
	@GeneratedValue(strategy=GenerationType.AUTO)
	private Long id;
	
	@Version
	private Long version;

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public Long getVersion() {
		return version;
	}

	public void setVersion(Long version) {
		this.version = version;
	}
	
	
	
	/**
	Validation code, that is valid for all subclasses.
	*/
	public void validate () throws ValidationException {
	
		ClassValidator validator = new ClassValidator(getClass());		
		
		InvalidValue[] invalidValues = validator.getInvalidValues(this);
		
		if (invalidValues != null && invalidValues.length > 0) {
			throw new ValidationException(buildValidationExceptionMessage(invalidValues));
		}
	}
	
	
	public String buildValidationExceptionMessage (InvalidValue[] invalidValues) {
		StringBuilder builder = new StringBuilder();
		
		for (InvalidValue value : invalidValues) {
			builder.append(value.toString()).append("\n");
		}
		
		return builder.toString();
	}
	
}


BaseService.java

package com.alesaudate.services;

import java.util.ArrayList;
import java.util.List;

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

import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import com.alesaudate.domain.BaseEntity;
import com.alesaudate.domain.InvalidStateException;
import com.alesaudate.domain.Person;
import com.alesaudate.services.support.collections.Collection;



@Component
public abstract class BaseService<T extends BaseEntity> {
	
	
	@Autowired
	private HibernateTemplate hibernateTemplate;
	
	
	@Transactional
	public T createOnDatabase (T entity) throws InvalidStateException {
		entity.validate();
		getHibernateTemplate().persist(entity);
		return entity;
	}
	
	
	@POST
	@Produces({MediaType.TEXT_XML, MediaType.APPLICATION_XML})
	public T create (T entity) throws InvalidStateException {
		return createOnDatabase(entity);
	}
	
	
	@Transactional
	public T updateOnDatabase (T entity) throws InvalidStateException {
		entity.validate();
		getHibernateTemplate().update(entity);
		return entity;
	}
	
	@PUT
	@Produces({MediaType.TEXT_XML, MediaType.APPLICATION_XML})
	public T update (T entity) throws InvalidStateException  {
		return updateOnDatabase(entity);
	}
	
	
	@Transactional(readOnly=true)
	public T findOnDatabase (Long id) {
		
		DetachedCriteria criteria = DetachedCriteria.forClass(getManagedClass()).add(Restrictions.eq("id", id));
		List entities = getHibernateTemplate().findByCriteria(criteria);
		if (entities.isEmpty()) 
			return null;
		return (T)entities.get(0);
	}
	
	@GET
	@Path("{id}")
	@Produces({MediaType.TEXT_XML, MediaType.APPLICATION_XML})
	public T find (@PathParam("id")Long id) {
		T entity = findOnDatabase(id);
		loadEntity(entity);
		return entity;
	}
	
	
	@Transactional(readOnly=true)
	public List<T > findAllFromDatabase () {
		
		DetachedCriteria criteria = DetachedCriteria.forClass(getManagedClass());
		List<T> all = getHibernateTemplate().findByCriteria(criteria);
		loadList(all);
		return all;
	}
	
	@GET	
	@Produces({MediaType.TEXT_XML, MediaType.APPLICATION_XML})	
	@Collection
	public List<T> findAll() {
		return findAllFromDatabase();
	}
	
	
	@Transactional
	public void deleteFromDatabase (T toDelete) {
		getHibernateTemplate().delete(toDelete);
	}
	
	

	@DELETE
	@Produces({MediaType.TEXT_XML, MediaType.APPLICATION_XML})
	public void delete (T toDelete) {
		deleteFromDatabase(toDelete);
	}
	
	public abstract Class<? extends BaseEntity> getManagedClass();
	
	
	public abstract void loadEntity (T data);
	
	public abstract void loadList (java.util.Collection<T> data);
	
	
	public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {
		this.hibernateTemplate = hibernateTemplate;
	}
	
	public HibernateTemplate getHibernateTemplate() {
		return hibernateTemplate;
	}

}

PersonService.java

package com.alesaudate.services;

import java.util.Collection;

import javax.ws.rs.Path;

import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Restrictions;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.alesaudate.domain.Address;
import com.alesaudate.domain.BaseEntity;
import com.alesaudate.domain.Person;




@Component
@Path("/person")
public class PersonService extends BaseService<Person>{

	@Override
	public Class<? extends BaseEntity> getManagedClass() {
		return Person.class;
	}

	@Override
	public void loadEntity(Person data) {
		//Load addresses
		data.getAddresses();
	}

	@Override
	@Transactional(propagation=Propagation.MANDATORY)
	public void loadList(Collection<Person> data) {
		for (Person p : data) {			
			getHibernateTemplate().find("select p.addresses from Person p");
			for (Address address : p.getAddresses()) {
				getHibernateTemplate().evict(address);
				address.makeXMLCompatible();
			}
			getHibernateTemplate().evict(p);
		}
		
	}

	
	
	
	
	
	
}

applicationContext.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:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">

	

	<context:component-scan base-package="com.alesaudate.services" />

<!-- Other bean definitions... -->		


</beans>

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
  <display-name>Architecture</display-name>
  
  <context-param>
       <param-name>contextConfigLocation</param-name>
       <param-value>classpath:applicationContext.xml</param-value>
   </context-param>

 
   <listener>
          <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
   </listener>
   <listener>
          <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
   </listener>

 <servlet>
 	<servlet-name>Jersey Servlet</servlet-name>
 	<servlet-class>com.sun.jersey.spi.spring.container.servlet.SpringServlet</servlet-class>
 </servlet>
 
 <servlet-mapping>
 	<servlet-name>Jersey Servlet</servlet-name>
 	<url-pattern>/*</url-pattern>
 </servlet-mapping>
  
</web-app>

End.

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!