My Garbage Collector

Hamdi Makni's Blog

Our more repeated code in classes is the data input validations perform, because it’s very important to validate transported object between applications, and between application layers.
On a classic web context, we have some validation form framework like Struts Validator Framework, who can validate form in the client side and server side, based on xml files. On web service context, payload validation is a basic function proposed with the most web service framework. These classic web and web services frameworks send formatted message to client if any data validations fail, and block performing the standard processing. Otherwise, processing continues.
In my case, I have an application core class with a public method invoked from other internal classes, or from another application layer, for example, a DAO method invoked from a service layer. Usually, we need to validate input parameters in your public methods. So we have generally to write some code like this, in the top of your method:


public void myMethod (MethodIN inParameter){
//input method validation
if(inParameter==null)
throw new Exception(…);
if(inParameter.getSimpleProperty()==null)
throw new Exception(…);
if(inParameter.aMyFirstBean!=null){
if(inParameter.aMyFirstBean.getCodeAsString() == null)
throw new Exception(…);
if(inParameter.aMyFirstBean.getCodeAsString().length() <2 || inParameter.aMyFirstBean.getCodeAsString().length() > 40)
throw new Exception(…);
//do something with the input parameters
…………

}

This code is repeated every time when you have to use a mandatory input or strict formatted parameters.
Spring-modules have a validation package witch can used to validate data beans property with annotation or with xml document. In the xml file we must define the validation rules for every class and every property you want to validate. So I think that we can use spring-modules validator to validate input methods by using a method interceptor. The interceptor, wired in an aop-proxy of any service bean of my application, intercepts some methods, when you want to validate inputs, and proceed with the validation perform. The validator is configured in the application context file, and uses an xml file to get the validation rules.
So when the method is called, we fetch received object as input parameter, and put it to the “validation machine”. When fails, the interceptor throw an exception and stop method execution.

import java.util.Iterator;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.validation.BindException;
import org.springframework.validation.Errors;
import org.springframework.validation.FieldError;
import org.springmodules.validation.bean.BeanValidator;

/**
* @author Hamdi MAKNI
*/
public class InputBeanValidator implements MethodInterceptor {

private BeanValidator beanValidator;
private Log log = LogFactory.getLog(this.getClass());

public Object invoke (MethodInvocation methodInvocation) throws Throwable {
Object[] arguments = methodInvocation.getArguments();
Errors errors = new BindException(this, this.getClass().toString());
String errorMessage = "";
for (int i = 0; i < arguments.length; i++) {
Object object = arguments[i];
if (object != null) {
Errors errorss = new BindException(object, object.getClass().toString());
beanValidator.validate(object, errorss);
// errors.getAllErrors().addAll(errorss.getAllErrors());
for (Iterator j = errorss.getAllErrors().iterator(); j.hasNext();) {
FieldError err = (FieldError ) j.next();
log.error(err.toString());
}
if (errorss.hasErrors())
errorMessage+=errorss.toString();
}
}
for (Iterator j = errors.getAllErrors().iterator(); j.hasNext();) {
Error err = (Error ) j.next();
log.debug(err.toString());
}
if(!errorMessage.equals(""))
throw new Exception(errorMessage);
Object out = (Object ) methodInvocation.proceed();
return out;
}

}


And then, we need a proxy creator to create your service with a method interceptor. The interceptor






MyServiceBeanDefinition




inputBeanValidatorInterceptor










.*myMethod*











classpath:validation.xml









and we have to write an xml file whith the validation rules, like that:



xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="validator.xsd">













One of the most important phases in the web service request execution process is the SOAP document validation. In fact, like forms in web application, it is recommended to validate received information from client before proceeding to the real action.
One year ago, I had a consulting mission with a firm specialised in booking train ticket services.
The project consisted of exposing some services to a WAP application. We chose Xfire framework as a web service stack, because the competitive intelligence team advise it as the best framework in java web services implementation word (they says).
I already know that we can make web service payload validation in SpringWS with an interceptor. The interceptor called PayloadValidator, is wired in a web service endpoint, and validates automatically the payload document, based on a schema definition document, and using an xml framework with validation function like Jaxb.
I looked into Xfire implementation, but I didn't find a satisfactory solution. So I decided to pick up the Spring-Ws Interceptor idea and code, and adapt it to work as an Xfire handler. I just made some changes on the spring code, especially to read the document and write fault in the response.

Like the Spring-WS Interceptor, I have an abstract super class named AbstractPayloadValidator, with an invoke abstract method, implemented by the subclasses. This method is the main handler method.


import java.util.Locale;
import javax.xml.namespace.QName;
import org.codehaus.xfire.MessageContext;
import org.codehaus.xfire.handler.AbstractHandler;
import org.jdom.Document;
import org.springframework.core.io.Resource;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.xml.namespace.QNameUtils;
import org.springframework.xml.validation.XmlValidator;
import org.springframework.xml.validation.XmlValidatorFactory;

public abstract class AbstractPayloadValidator extends AbstractHandler {

public static final QName DEFAULT_DETAIL_ELEMENT_NAME = QNameUtils
.createQName("http://springframework.org/spring-ws",
"ValidationError", "spring-ws");
public static final String DEFAULT_FAULTSTRING_OR_REASON = "Validation error";
private boolean addValidationErrorDetail = true;
private QName detailElementName = DEFAULT_DETAIL_ELEMENT_NAME;
private String faultStringOrReason = DEFAULT_FAULTSTRING_OR_REASON;
private Locale faultStringOrReasonLocale = Locale.ENGLISH;
private String schemaLanguage = XmlValidatorFactory.SCHEMA_W3C_XML;
private Resource[] schemas;
protected XmlValidator validator;
protected Document doc;
public AbstractPayloadValidator() throws Exception {
super();
System.setProperty(
"javax.xml.validation.SchemaFactory:http://www.w3.org/2001/XMLSchema",
"org.apache.xerces.jaxp.validation.XMLSchemaFactory");
}

public void afterPropertiesSet() throws Exception {
Assert.notEmpty(schemas,"setting either the schema or schemas property is required");
Assert.hasLength(schemaLanguage, "schemaLanguage is required");
for (int i = 0; i < schemas.length; i++) {
Assert.isTrue(schemas[i].exists(), "schema [" + schemas[i] + "] does not exist");
}
if (log.isDevLevelEnabled()) {
log.debug("Validating using " + StringUtils.arrayToCommaDelimitedString(schemas));
}
validator = XmlValidatorFactory.createValidator(schemas, schemaLanguage);
}
public abstract void invoke(MessageContext messageContext) throws Exception;
}

RequestPayloadValidator is the request validator implementation of my abstract class. Normally, I must implement another class to validate the response.
In the invoke method, It will call the handelRequest method to do the validation. In the validation fails, a SOAP fault is sent to the client with the detailed message of the validation rules.

import java.io.IOException;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.transform.Source;
import javax.xml.transform.TransformerException;
import org.codehaus.xfire.MessageContext;
import org.codehaus.xfire.exchange.InMessage;
import org.codehaus.xfire.fault.XFireFault;
import org.codehaus.xfire.handler.Phase;
import org.codehaus.xfire.soap.handler.ReadHeadersHandler;
import org.codehaus.xfire.util.jdom.StaxBuilder;
import org.codehaus.xfire.util.stax.JDOMStreamReader;
import org.jdom.Element;
import org.jdom.transform.JDOMSource;
import org.springframework.util.ObjectUtils;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;

import ….PayloadValidationException;

public class RequestPayloadValidator extends AbstractPayloadValidator {

public RequestPayloadValidator() throws Exception {
super();
setPhase(Phase.PARSE);
before(ReadHeadersHandler.class.getName());

}

protected Source getValidationRequestSource(MessageContext request)
throws XMLStreamException {
InMessage message = request.getInMessage();
XMLStreamReader streamReader = message.getXMLStreamReader();
StaxBuilder builder = new StaxBuilder();

doc = builder.build(streamReader);
Element body = ((Element) doc.getRootElement().getChildren().get(0));
if(!body.getName().equals("Body")) body = (Element) doc.getRootElement().getChildren().get(1);
Element payload = (Element) body.getChildren().get(0);
return new JDOMSource(payload);
}
protected boolean handleRequestValidationErrors(
MessageContext messageContext, SAXParseException[] errors)
throws TransformerException, XFireFault, PayloadValidationException {
String faultMessage = "";
for (int i = 0; i < errors.length; i++) {
faultMessage += errors[i].getMessage();
log.debug("XML validation error on request: " + errors[i].getMessage());
}

messageContext.getExchange().getFaultMessage().setBody(new XFireFault(faultMessage, new PayloadValidationException(),XFireFault.SENDER));
return false;

}

public boolean handleRequest(MessageContext messageContext)
throws IOException, SAXException, TransformerException,
XMLStreamException, XFireFault, PayloadValidationException {
Source requestSource = getValidationRequestSource(messageContext);
if (requestSource != null) {
SAXParseException[] errors = validator.validate(requestSource);
if (!ObjectUtils.isEmpty(errors)) {
return handleRequestValidationErrors(messageContext, errors);
} else if (log.isDevLevelEnabled()) {
log.debug("Request message validated");
}
}
return true;
}

public void invoke(MessageContext messageContext) throws Exception {
afterPropertiesSet();
if (handleRequest(messageContext))
log.debug("Validation of requested payload finished by SUCCESS");
else
log.debug("Validation of requested payload finished by FAULT");
messageContext.getInMessage().setXMLStreamReader(
new JDOMStreamReader(doc));

}
}

I used this handler named ErrorValidationHandler to throw the fault and log it.

import org.codehaus.xfire.MessageContext;
import org.codehaus.xfire.fault.XFireFault;
import org.codehaus.xfire.handler.AbstractHandler;
import org.codehaus.xfire.handler.Phase;
import org.codehaus.xfire.soap.handler.SoapBodyHandler;

public class ErrorValidationHandler extends AbstractHandler {

protected final Log log = new Log(getClass());

public ErrorValidationHandler() {
super();
setPhase(Phase.DISPATCH);
after(SoapBodyHandler.class.getName());
}

public void invoke(MessageContext messageContext) throws Exception {
XFireFault fault = (XFireFault) messageContext.getExchange()
.getFaultMessage().getBody();
if (fault != null){
log.debug("fault received from the payload validator handler.");
throw fault;
}
}
}

In my spring applicationContext file, I wired my handlers in the service exporter, as an inHandlers.






com…...MYWs


myWs.wsdl









I set the schema file location in the validator bean

class="com…...validation.RequestPayloadValidator">




class="com…...validation.ErrorValidationHandler">

Like the other web service stacks, Xfire make a first level validation of received request document, but with this handler we can validate any type of rules with a rich xsd file.
An amelioration of this solution is to get dynamically the shema definition part from the WSDL file.

Après quelques mois de préparation, le JUG tunisien est enfin crée.
Le Java User Group Tunisien porte le nom de TeeJUG.
Le but est d'avoir une vrai communauté java tunisienne, active, reférencée par sun
TeeJUG commence par un google groupe et un blog sous blogger.
http://groups.google.com/group/teejug
http://teejug.blogspot.com/


Presented by Tareq Abed Rabbo
April 2007- tunis-Tunisia

I am interested this period to reporting tool, since a month ago I am searching the best tool to generate easily and perfectly a good report.
After Business Object and Cristal Report, JfreeChart, then Birt, finally I found jasper Report and his report design tool iRreport.
I choose jasper Report for three reasons. First, Jasper report is easily integrated with Spring framework, in fact, Spring offer a view class to integrate jasper report in your web application.Second, Jasper report use JrfeeCchart to generate some chat. Third, iReport is very good tool, easy to use, rich with his variety of chart. And finally, because with Jasper Report I can generate cross tabs.