Thursday, March 25, 2010

Bookmark and Share

When I started blogging on JSR 303 ("Bean Validation"), there was not too much information available on the web concerning the BV API, its usage and its integration with other technologies.

In between JSR 303 got approved, BV is part of Java EE 6 and as it generally gains wider adoption, more and more blog posts and other information related to Bean Validation come available.

That's why I thought it might be a good idea to collect the most interesting pieces and publish those links here every once in a while.

And there you go, here is the first couple of links related to JSR 303:

I plan to post follow-ups, whenever I gathered some interesting links, so stay tuned.

Tuesday, March 16, 2010

Bookmark and Share

Recently I received an IntelliJ IDEA code style settings file for Hibernate Validator, the reference implementation of JSR 303 ("Bean Validation"), to which I'm contributing.

I wanted to import it into IntelliJ in order to format any code changes I make in the project's standard style. But as it turned out, there is no functionality within the IDE for importing code style settings. Instead one has to do the following:

  • Copy the settings XML file to INTELLIJ_SETTINGS_DIR/config/codestyles (where INTELLIJ_SETTINGS_DIR is the folder containing your IntelliJ settings; typically it is situated within your home directory, the name depends on your version of IntelliJ; in my case the complete path is "~/.IdeaIC90/config/codestyles")
  • Start IntelliJ
  • Go to "File" - "Settings" - "Code Style", select "Use global settings" and choose the previously imported style from the drop-down box
  • Optionally apply the style to one project only by clicking on "Copy to Project" and selecting "Use per project settings" afterwards

Tuesday, March 9, 2010

Bookmark and Share

When working with XML-based web services, it usually a good idea to validate all requests and responses against their associated XML schema in order to ensure the integrity of the incoming/outgoing messages.

Unfortunately JAX-WS, the standard API for SOAP-based web services of the Java Platform doesn't specify a standard way for schema validation. Therefore most of the JAX-WS implementations such as Metro or CXF provide a proprietary mechanism to perform that task.

Using Metro, this is simply done by annotating the endpoint class with @SchemaValidation:

1
2
3
4
5
@WebService(endpointInterface = "...")
@SchemaValidation
public class VideoRentalPort implements VideoRentalPortType {
    //...
}

This works as expected, but has one big flaw in my eyes: to enable or disable validation for a given endpoint, the application code must be modified, followed by a re-deployment of the application.

This is not viable in many scenarios. Taking a large enterprise application with a whole lot of services for example, schema validation might be turned off by default for performance reasons. But for the purpose of bug analysis it might be required to temporarily enable validation for single endpoints. Re-deploying the application is not an option in this scenario.

That's why I had a look into Metro's implementation of the validation feature and tried to find a way to make schema validation configurable during runtime.

Custom Metro tubes

Schema validation in Metro is realized using in form of a so-called "tube". Metro tubes are conceptually similar to JAX-WS message handlers, but a magnitude more powerful. Since Metro 2.0 the tubes to be applied for a given application can be configured by providing so-called custom "tubelines".

So the basic idea is to extend the standard validation tube provided by Metro in a way which makes it runtime-configurable and register this customized tube instead of the original one.

Note: Before going into details, it should be said that as of Metro 2.0 the tube-related APIs are regarded as Metro-internal APIs, so they could be changed in future versions, causing the approach described here not to work anymore. But as we don't write very much code, this shouldn't really scare us.

Managing configuration state

First of all, some sort of data structure is needed, which will store whether validation is enabled for a given web service endpoint. For this purpose a simple map is sufficient (as this class must be accessible for multiple threads at the same time, a ConcurrentMap is used):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class ValidationConfigurationHolder {

    private static ConcurrentMap<String, Boolean> configuration = 
        new ConcurrentHashMap<String, Boolean>();

    public static boolean isValidationEnabled(String portName) {

        Boolean theValue = configuration.get(portName);
        return theValue != null ? theValue : Boolean.TRUE;
    }

    public static void setValidationEnabled(String portName, boolean enabled) {
        configuration.put(portName, enabled);
    }
}

Next we need a way to manipulate this structure during application runtime. Java's standard API for management purposes as the one at hand is JMX. The following listing shows a JMX MBean, which later can be invoked to enable or disable validation for a given port:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
//MBean interface
public interface EndpointConfigurationMBean {

    public String getName();

    public boolean isSchemaValidationEnabled();

    public void setSchemaValidationEnabled(boolean enabled);

}

//MBean implementation
public class EndpointConfiguration implements EndpointConfigurationMBean {

    private String name;

    public EndpointConfiguration() {}

    public EndpointConfiguration(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public boolean isSchemaValidationEnabled() {
        return ValidationConfigurationHolder.isValidationEnabled(name);
    }

    public void setSchemaValidationEnabled(boolean enabled) {
        ValidationConfigurationHolder.setValidationEnabled(name, enabled);
    }

}

The customized validation tube

The schema validation support of Metro is basically realized in three classes: AbstractSchemaValidationTube and ServerSchemaValidationTube resp. ClientSchemaValidationTube which extend the former. To make schema validation configurable on the server side, we create a sub-class of ServerSchemaValidationTube:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
public class ConfigurableServerSchemaValidationTube extends ServerSchemaValidationTube {

    private String name;

    public ConfigurableServerSchemaValidationTube(WSEndpoint<?> endpoint, WSBinding binding,
            SEIModel seiModel, WSDLPort wsdlPort, Tube next) {

        super(endpoint, binding, seiModel, wsdlPort, next);

        name = seiModel.getServiceQName().getLocalPart() + "-" + wsdlPort.getName().getLocalPart();
        ValidationConfigurationHolder.setValidationEnabled(name, true);
        registerMBean();
    }

    private void registerMBean() {

        MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); 

        try {
            mbs.registerMBean(
                new EndpointConfiguration(name),
                new ObjectName("de.gmorling.moapa.videorental.jmx:type=Endpoints,name=" + name));
        }
        catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    protected boolean isNoValidation() {
        return !ValidationConfigurationHolder.isValidationEnabled(name);
    }

    protected ConfigurableServerSchemaValidationTube(ConfigurableServerSchemaValidationTube that, TubeCloner cloner) {
        super(that,cloner);
        this.name = that.name;
    }

    public ConfigurableServerSchemaValidationTube copy(TubeCloner cloner) {
        return new ConfigurableServerSchemaValidationTube(this, cloner);
    }

}

The important thing here is, that the method isNoValidation() is overridden. This method is defined within the base class AbstractSchemaValidationTube and is invoked whenever a request/response is processed by this tube. The implementation of this method simply delegates to the ValidationConfigurationHolder shown above.

Within the constructor an instance of the EndpointConfiguration MBean for the given endpoint is registered with the platform MBean server, which later can be used to toggle validation for this endpoint.

Providing a TubeFactory

Metro tubes are instantiated by implementations of the TubeFactory interface. The following implementation allows the Metro runtime to retrieve instances of the ConfigurableServerSchemaValidationTube:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class ConfigurableValidationTubeFactory implements TubeFactory {

    //...

    public Tube createTube(ServerTubelineAssemblyContext context)
            throws WebServiceException {

        ServerTubeAssemblerContext wrappedContext = context.getWrappedContext();
        WSEndpoint<?> endpoint = wrappedContext.getEndpoint();
        WSBinding binding = endpoint.getBinding();
        Tube next = context.getTubelineHead();
        WSDLPort wsdlModel = wrappedContext.getWsdlModel();
        SEIModel seiModel = wrappedContext.getSEIModel();

        if (binding instanceof SOAPBinding && binding.isFeatureEnabled(SchemaValidationFeature.class) && wsdlModel != null) {
            return new ConfigurableServerSchemaValidationTube(endpoint, binding, seiModel, wsdlModel, next);
        } else
            return next;
    }
}

The code resembles Metro's instantiation logic for the standard validation tube, the only difference being that a ConfigurableServerSchemaValidationTube is created. Note that we also check whether the SchemaValidationFeature is enabled or not. That way given endpoints can be completey excluded from validation by simply not annotating them with @SchemaValidation.

To register the tube factory with Metro as part of a custom tubeline the configuration file META-INF/metro.xml has to be provided:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?xml version="1.0" encoding="UTF-8"?>
<metro  xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
   xmlns='http://java.sun.com/xml/ns/metro/config'
   version="1.0">
    <tubelines default="#custom-tubeline">
        <tubeline name="custom-tubeline">
            <client-side>
                ...
            </client-side>
            <endpoint-side>
                ...
                <tube-factory className="com.sun.xml.ws.assembler.jaxws.HandlerTubeFactory" />
                <tube-factory className="de.gmorling.moapa.videorental.metro.ConfigurableValidationTubeFactory" />
                <tube-factory className="com.sun.xml.ws.assembler.jaxws.TerminalTubeFactory" />
            </endpoint-side>
        </tubeline>
    </tubelines>
</metro>

As suggested in a post by Metro developer Marek Potociar it's a good idea to take Metro's standard tube configuration, metro-default.xml, as template and adapt it as needed. In our case the ConfigurableValidationTubeFactory is registered instead of the standard ValidationTubeFactory.

Configuring Schema Validation using VisualVM

Having registered the tube factory, it's time to give the whole thing a test run. A complete project containing all sources of this post together with an examplary video rental web service can be found in my Git repo.

When starting the project's main class the service will be fired up and waiting for requests. Any JMX client such as VisualVM can now be used to connect to the running JVM. The following screenshot shows VisualVM connected to the video rental application:

By setting the value of the "SchemaValidationEnabled" property of the MBean named "VideoRentalService-VideoRentalPort", schema validation now can be enabled or disabled for the corresponding endpoint.

Update (march 10, 2010): I created an request for enhancement for that feature: Allow schema validation to be enabled/disabled at runtime. So let's see, whether this will be part of some future Metro version :-)

Tuesday, February 16, 2010

Bookmark and Share

One question I'm being asked pretty often when talking about the Bean Validation API (JSR 303) is, how cross-field validation can be done. The canonical example for this is a class representing a calendar event, where the end date of an event shall always be later than the start date.

This and other scenarios where validation depends on the values of multiple attributes of a given object can be realized by implementing a class-level constraint.

That basically works pretty well, nevertheless this is one part of the BV spec, I'm not too comfortable with. This is mainly for two reasons:

  • You'll probably need a dedicated constraint for every reasonably complex business object. Providing an annotation, a validator implementation and an error message for each can become pretty tedious.
  • Business objects typically know best themselves, whether they are in a consistent, valid state or not. By putting validation logic into a separate constraint validator class, objects have to expose their internal state, which otherwise might not be required.

To circumvent these problems, I suggested a while ago a generic constraint annotation, which allows the use of script expressions written in languages such as Groovy to implement validation logic directly at the validated class.

This approach frees you from the need to implement dedicated constraints for each relevant business object, but also comes at the cost of losing type-safety at compile-time.

The constraint presented in the following therefore tries to combine genericity with compile-time type safety. The basic idea is to implement validation logic within the business objects themselves and to invoke this logic from within a generic constraint class.

In order to do so let's first define an interface to be implemented by any validatable class:

1
2
3
4
public interface Validatable {

    public boolean isValid();
}

Next we define a constraint annotation, @SelfValidating, which we'll use later on to annotate Validatable implementations:

1
2
3
4
5
6
7
8
9
10
11
12
13
@Target( { TYPE })
@Retention(RUNTIME)
@Constraint(validatedBy = SelfValidatingValidator.class)
@Documented
public @interface SelfValidating {

    String message() default "{de.gmorling.moapa.self_validating.SelfValidating.message}";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};

}

Of course we also need a constraint validator implementation, which is able to evaluate that constraint:

1
2
3
4
5
6
7
8
9
10
11
public class SelfValidatingValidator implements
    ConstraintValidator<SelfValidating, Validatable> {

    public void initialize(SelfValidating constraintAnnotation) {}

    public boolean isValid(Validatable value,
        ConstraintValidatorContext constraintValidatorContext) {

        return value.isValid();
    }
}

The implementation is trivial, as nothing is to do in initialize() and the isValid() method just delegates the call to the validatable object itself.

Finally we need a properties file named ValidationMessages.properties containing the default error message for the constraint:

1
de.gmorling.moapa.self_validating.SelfValidating.message=Validatable object couldn't be validated successfully.

Taking the calendar event example from the beginning, usage of the constraint might look as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
@SelfValidating
public class CalendarEvent implements Validatable {

    @NotNull
    private final String title;

    private final Date startDate;

    private final Date endDate;

    public CalendarEvent(String title, Date startDate, Date endDate) {

        this.title = title;
        this.startDate = startDate;
        this.endDate = endDate;
    }

    public boolean isValid() {
        return startDate == null || endDate == null || startDate.before(endDate);
    }

    @Override
    public String toString() {
        DateFormat format = new SimpleDateFormat("dd.MM.yyyy");

        return 
            title + 
            " from " +  (startDate == null ? "-" : format.format(startDate)) + 
            " till " + (endDate == null ? "-" : format.format(endDate));
    }

}

A short unit test shows that the constraint works as expected:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
public class SelfValidatingTest {

    private static Validator validator;

    private static Date startDate;

    private static Date endDate;

    @BeforeClass
    public static void setUpValidatorAndDates() {

        ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();
        validator = validatorFactory.getValidator();

        startDate = new GregorianCalendar(2009, 8, 20).getTime();
        endDate = new GregorianCalendar(2009, 8, 21).getTime();
    }

    @Test
    public void calendarEventIsValidAsEndDateIsAfterStartDate() {

        CalendarEvent testEvent = 
            new CalendarEvent("Team meeting", startDate, endDate);

        assertTrue(validator.validate(testEvent).isEmpty());
    }

    @Test
    public void calendarEventIsInvalidAsEndDateIsBeforeStartDate() {

        CalendarEvent testEvent = 
            new CalendarEvent("Team meeting", endDate, startDate);

        Set<ConstraintViolation<CalendarEvent>> constraintViolations = 
            validator.validate(testEvent);
        assertEquals(1, constraintViolations.size());

        assertEquals(
            "Object couldn't be validated successfully.",
            constraintViolations.iterator().next().getMessage());
    }
}

This works like a charm, only the error message returned by the BV runtime is not yet very expressive. This can easily be solved, as the BV API allows to override error messages within constraint annotations:

1
2
3
4
@SelfValidating(message="{de.gmorling.moapa.self_validating.CalendarEvent.message}")
public class CalendarEvent implements Validatable {
    ...
}

Again we need an entry in ValidationMessages.properties for the specified message key:

1
de.gmorling.moapa.self_validating.CalendarEvent.message=End date of event must be after start date.

Conclusion

Providing dedicated class-level constraints for all business objects that require some sort of cross-field validation logic can be quite a tedious task as you need to create an annotation type, a validator implementation and an error message text.

The @SelfValidating constraint reduces the required work by letting business objects validate themselves. That way all you have to do is implement the Validatable interface, annotate your class with @SelfValidating and optionally provide a customized error message. Furthermore business objects are not required to expose their internal state to make it accessible for an external validator implementation.

The complete source code can be found in my GitHub repository. As always I'd be happy about any feedback.

Saturday, February 6, 2010

Bookmark and Share

JAX-WS as Java's standard API for web services comes with a close integration of JAXB as XML binding framework. More precisely JAXB is actually the only binding technology directly supported by JAX-WS. As JAXB basically does its job pretty well, that's nothing bad per se.

Nevertheless there might be situations where you would like to integrate JAX-WS with other XML binding solutions such as Apache XmlBeans.

For instance you might have used another web service stack and binding framework in the past and now want to migrate your services to JAX-WS. Depending on the number of services, changing your XML binding framework can create quite a lot of work, as you have to rewrite the mapping code which converts between the types generated by the binding framework and your domain objects.

Provider-based endpoints

The key idea for integrating JAX-WS with another binding framework is to create a Provider based endpoint for your web service. Contrary to standard SEI (service endpoint interface) implementations, which solely operate on JAXB generated classes, a provider endpoint has access to the raw XML of incoming and outgoing messages.

That way you can take care of XML marshalling yourself, e.g. by converting incoming XML messages into their corresponding XmlBeans types and the other way around.

In the following a web service for a video rental store shall be built. The service has a single operation, getMovieById, with request and response types in an accompanying XML schema (the service's WSDL and all other sources for this post can be found in my Git repository):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?xml version="1.0" encoding="UTF-8"?>
<schema 
    targetNamespace="http://www.gunnarmorling.de/moapa/videorental/types"
    xmlns="http://www.w3.org/2001/XMLSchema"
    xmlns:videorental="http://www.gunnarmorling.de/moapa/videorental/types">

    <element name="GetMovieByIdRequest" type="videorental:GetMovieByIdRequest" />
    <element name="GetMovieByIdResponse" type="videorental:GetMovieByIdResponse" />

    <complexType name="GetMovieByIdRequest">
        <sequence>
            <element name="Id" type="long" />
        </sequence>
    </complexType>

    <complexType name="GetMovieByIdResponse">
        <sequence>
            <element type="videorental:Movie" name="Movie" minOccurs="0" />
        </sequence>
    </complexType>

    <complexType name="Movie">
        <sequence>
            <element name="Id" type="long" />
            <element name="Title" type="string" />
            <element name="RunTime" type="int" />
        </sequence>
    </complexType>
</schema>

XmlBeans will generate two document types for the elements (GetMovieByIdRequestDocument, GetMovieByIdResponseDocument) as well as types for each of the complex types.

For the service implementation I recommend to work only with the classes representing the complex types (instead of the document types). An interface representing the service's port type and its implementation therefore might look like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public interface VideoRentalPortType {

    public GetMovieByIdResponse getMovieById(GetMovieByIdRequest request);

}

...

public class VideoRentalPort implements VideoRentalPortType {

    private MovieRepository movieRepository = new MovieRepositoryMockImpl();

    public GetMovieByIdResponse getMovieById(GetMovieByIdRequest request) {

        GetMovieByIdResponse response = GetMovieByIdResponse.Factory.newInstance();

        de.gmorling.moapa.videorental.domain.Movie movie = movieRepository.getMovieById(request.getId());

        if(movie != null) {
            response.setMovie(convert(movie));
        }       

        return response;
    }

    private Movie convert(de.gmorling.moapa.videorental.domain.Movie movie) {

        Movie theValue = Movie.Factory.newInstance();

        theValue.setId(movie.getId());
        theValue.setTitle(movie.getTitle());
        theValue.setRunTime(movie.getRunTime());

        return theValue;
    }
}

This looks pretty similar to a typical SEI-based implementation. The only difference is, that the types in use are generated by XmlBeans instead of JAXB. The implementation is straight forward. It takes the movie id from the incoming request, invokes some backend business service and creates a GetMovieByIdResponse from the result.

Next we need to create the actual Provider implementation which will be called by the JAX-WS runtime, whenever the service is invoked:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
@WebServiceProvider
@ServiceMode(value=Mode.MESSAGE)
public class VideoRentalProvider implements Provider<SOAPMessage> {

    private VideoRentalPortType videoRentalPort = new VideoRentalPort();

    public SOAPMessage invoke(SOAPMessage request) {

        try {

            Node root = request.getSOAPBody().getFirstChild();

            if(root.getNodeName().contains(GetMovieByIdRequest.class.getSimpleName())) {

                GetMovieByIdRequestDocument requestDocument = GetMovieByIdRequestDocument.Factory.parse(root);
                GetMovieByIdResponseDocument responseDocument = GetMovieByIdResponseDocument.Factory.newInstance();
                responseDocument.setGetMovieByIdResponse(videoRentalPort.getMovieById(requestDocument.getGetMovieByIdRequest()));

                return createSOAPMessage(responseDocument);
            }
            else {
                throw new UnsupportedOperationException();
            }
        }
        catch(Exception e) {
            throw new RuntimeException(e);
        }
    }

    private SOAPMessage createSOAPMessage(XmlObject responseDocument) {

        try {

            SOAPMessage message = MessageFactory.newInstance().createMessage();
            Node node = message.getSOAPBody().getOwnerDocument().importNode(responseDocument.getDomNode().getFirstChild(), true);
            message.getSOAPBody().appendChild(node);
            return message;
        }
        catch(Exception e) {
            throw new RuntimeException(e);
        }
    }

}

A provider implementation must be annotated with @WebServiceProvider. By binding the type parameter to SOAPMessage (a comparison with the alternatives Source and DataSource can be found here) and specifying Mode.MESSAGE within the @ServiceMode annotation we achieve, that we can access complete SOAP messages within the implementation.

The Provider interface defines only one method, invoke(). This method is called whenever any of the service's operations is invoked. Therefore we first have to determine the currently invoked operation, which can be done by peeking at the node name of the first body element.

In case of the getMovieById operation then a GetMovieByIdRequestDocument instance representing the contents of the message body is created using a XmlBeans-generated factory class. From that document we retrieve the actual request element and pass it to the port implementation.

The result is put into a new GetMovieByIdResponseDocument instance, which itself is finally wrapped into a SOAPMessage by importing the root DOM node into the message body.

Conclusion

Creating Provider-based endpoints makes it possible to use JAX-WS together with binding frameworks other than JAXB. Whether it should be done depends as always on the specific circumstances.

For new projects working with SEI endpoints and therefore JAXB should be preferred. The JAX-WS tooling will smoothly generate JAXB binding classes as well as port type interfaces, making the creation of new web services pretty simple.

In migration scenarios things can be different though. Re-writing a whole lot of mapping code originally created for another binding framework such as XmlBeans can be quite a time-consuming and error-prone task. In that case implementing Provider-based services can be an interesting alternative.

When pursuing that approach some performance tests should be executed first. A short load test on my machine didn't show significant execution time differences between JAXB/XmlBeans for the video rental service. But things might look different for larger message types due to the involved DOM manipulations.