2010-07-20

In this article I will show you some basic Bean Validation examples. You may want to (you should) read the official JSR 303 document to learn more. First, a quote from that document.

Validating data is a common task that occurs throughout an application, from the presentation layer to the persistence layer. Often the same validation logic is implemented in each layer, proving to be time consuming and errorprone. To avoid duplication of these validations in each layer, developers often bundle validation logic directly into the domain model, cluttering domain classes with validation code that is, in fact, metadata about the class itself.

This JSR defines a metadata model and API for JavaBean validation. The default metadata source is annotations, with the ability to override and extend the meta-data through the use of XML validation descriptors.

Built-in constraints

To use built-in constraints your project must import the javax.validation dependency. Maven:

It could be a lot better, because I only check the size of the violations set here. You might check the actual error message (still not so elegant...).

Error messages

Error messages are customizable. They can be modified if you provide a ResourceBundle called ValidationMessages (so, you can create a ValidationMessages .properties file and make if available in the classpath root).

When does validation occur?

Very good question! The specification doesn’t explicitly say when; instead it provides a clue in form of Appendices D, E and F.

Different JEE technologies launch Bean Validation. But when?

JPA calls validation upon:

pre-persist

pre-update

pre-remove

And these are entity lifecycle events. See Section 3.6 of JSR 317 for more details.

@Produces

The @Produces annotation can be applied to a (private or other) field or a method. That means that you can inject not only beans, but also collections etc. Using the @Produce annotation you may also fine the criteria when you combine it with qualifiers.

Here’s an example from the official JSR 299 document. My sample application also utilizes the annotation but in a simpler manner.

@Alternative

You may have a few possibilities for a dependency injection. You can either use qualifiers (see Part 1) or the @Alternative annotation (you have to pick either approach or your CDI implementation will complain).

If you decide to use alternatives, you choose one default bean and annotate the rest with the @Alternative annotation. Then, you can change the one to be injected using your beans.xml file.

@RunWith(Arquillian.class) - we need this for Arquillian to be activated for the tests

@Deployment - it is an Arquillian’s requirement for one method with this annotation to be present. It builds an archive which contains all our tests need to run. You must manually specify which classes it should use. We are also loading the other beans.xml with alternative beans specified

@Inject - here a bean will be injected by our combination of Arquillian and Weld (namely, DogsDaoMockImpl)

The test method only checks if anything was injected

Summary

I showed you how to use the @Produce and @Alternative annotations. You can check out the source code to see it working. NOTE: I removed qualifiers so that @Alternative can work.

2010-07-12

It seems that the current Weld implementation has an error - when no faces-config.xml is present in the deployment, but beans.xml is - you may get a StackOverflowError. At least I did with JBoss 6 RC3.

In fact, we wouldn’t have to use the @Named annotation to make it a managed bean, because according to the specification (consult JSR) most Java classes are managed beans (i.e. you can use dependency injection in them or inject them). We need @Named, however, to reference that bean from JSF. You can specify another name (the default one is dogsBean in this case).

Accessing a managed bean from JSF

And that’s it. Our bean is request scoped (CAUTION: make sure you import @RequestScoped from the correct package! That is javax.enterprise.context and not javax.faces.bean) so there will be a new instance of it per request.

Great! This bean is Application scoped, so there is going to be one instance of it per application. Note: the constructor will be called twice, actually. One for the actual object, one for the proxy. Read more about this behavior or consult JSR 299, Section 5.4.

Now, let’s inject it.

@Inject
private DogsDao dogsDao;

That’s it. You ask for an interface injection. The container sees there is only one implementation, and injects it. But what if you want to have two implementations of DogsDao?

With the current configuration, you’d get an exception - the container would not be able to decide which one to instantiate for you. How can you further specify which implementation you need? You should use...

Qualifiers

Qualifiers are a CDI concept that allows you to have more sophisticated criteria for selecting the implementation. Let’s create two qualifiers.

Now, when we inject, we must specify which implementation we want, with the same qualifier.

@Inject
@Actual
private DogsDao dogsDao;

And now it works.

Summary

I explained how to use basic CDI which is a new feature of JEE6. Remember that this is a JSF example, so I assumed you run it on an application server. However, CDI itself can be run without a server, so long as you provide an implementation for it (like Weld; the situation is similar to JPA).

The means

Normally I code in Eclipse, but this time I decided to use IntelliJ IDEA since it has a free community edition now and in my opinion it handles Scala better than the plugin available for Eclipse. You can download IntelliJ IDEA (I got version 9.0.2), but if you want to stick to Eclipse (or Notepad), it's fine.

Should you choose IntelliJ IDEA, you're going to have to (well, not really, but since you are using an IDE...) get the Scala plugin (which you should do through File -> Settings -> Plugins -> Available).