Tuesday, 14 April 2015

Extending Arquillian Graphene


With Arquillian Graphene, you can write tests which inspect the GUI of your web application (HTML based ones) right from within your familiar Unit Test code structure.

And there are already many nice features available, but sometimes, you want to extend the concepts of Arquillian Graphene. So that you can write cleaner code in some use cases.

The good thing is that you can achieve this quite easily due to the internal structure of the framework which uses 'Enricher's and Service extensions.

Extended Page Fragments

The concept of Page Fragments is described here and allows you to encapsulate the HTML structure of your widget.

As an example, we have a look at the inputText widget from PrimeFaces.  When the validation of the field fails, the element gets an ui-state-error CSS class set. So instead of checking if the class attribute contains the text as in this statement:


You can create a Page Fragment for the component where you encapsulate this check.
Your test looks now much cleaner and more descriptive


But for more complex components, like for example the PrimeFaces dataTable, it is nearly impossible to reference all parts of the component using the FindBy annotation within your Page Fragment.

It would be much easier if we could have a method which is executed the first time our proxy of the Page Fragment is accessed.
In Java EE terminology, we would like to have a @PostConstruct annotated method executed.

To achieve this, we have to define our extension (through the org.jboss.arquillian.core.spi.LoadableExtension file) and add a TestEnricher.

The TestEnricher can be used to add additional functionality to a Page Object or Page Fragment.  In our case we define an interceptor which gets executed every time we invoke a method on our Proxy page fragment.

In this interceptor we can verify if this is the first time we invoke something on the proxy (a bit tricky to know as there is no real identifier in our proxy) and if so, with the help of a bi reflection, find the method annotated with @PostConstruct and execute it.

See GrafacesInterceptor for the code.

In this initialisation method, we can search for other components in our widget on the screen using the findElements method available in the WebElement class.

List<WebElement> headers = root.findElements(By.tagName("th"));

The above example finds all the column headers of our table.

Validating the Page fragment

Now we can have a powerful Page Fragment, by using the default Graphene capabilities and adding our @PostConstruct initialisation method.

But what happens if we assign the PrimeFaces DataTable Page Fragment to a completely different type of widget, like a button?  In fact, the assignment is just done by specifying an id.  And mistakes are easily made.

If you have written your code in a proper way, defensive where you perform plenty checks on null pointers and non existing components, you can end up with a test which just fails without telling you that you actually made a mistake in the @FindBy to identify the widget.

The second extension which we discuss here, is that you can implement a detector method, to verify if you assigned the Page Fragment to the correct widget on the screen.
You can use all kind information available on the root (tag name, CSS classes, etc) to decide if the assignment is correct.
And if not, you can fail the test with a descriptive message what happened.

Injecting non visual helpers

Selenium WebDriver has support for checking web browser alerts.
One of the drawbacks is the not trivial code you have to write to verify for example if the alert is shown.

WebDriverWait wait = new WebDriverWait(driver, 5);if (wait.until(ExpectedConditions.alertIsPresent()) == null) {

    fail("Alert not showing as feedback for user");}

When you want to encapsulate this in a helper class, you need to pass the WebDriver instance into it. 

But we can't use the regular Arquillian Graphene way of working (using injection).  Because we don't have an ID on the screen which we can link to. So we need a custom annotation for injection, without an ID.

Besides the TestEnricher I have discussed earlier, there also exist a SearchContextTestEnricher.  The name is a bit confusing but it allows you to 'enrich' the test class as a whole.  And thus here we can search for fields which are annotated with our custom annotation, like @Grafaces.
Our enricher instantiates the object and also injects the regular Arquillian Grafaces artefacts like WebDriver instances annotated with @Drone.

This allows us then to write nicely readable test code like 

assertEquals("You choose JSF", alertHandling.checkForAlert().switchToAlert().getAlertText());


Arquillian Graphene is a great framework for testing your HTML based GUI directly within the browser.  Due to the open structure, you can write easily extensions for it.
In this text, 3 examples are presented to have 
  • Java based initialisation of the Page Object/Page Fragment
  • Validation of the assignment of the Page Fragment to the HTML widget
  • Wrapping the Selenium WebDriver alert handling functionality in a helper class which can be injected into your test class.

The code is available a GitHub and was presented at the ConFESS 2015 conference. Slides are at SlideShare.

Monday, 12 January 2015

Using groups with Bean Validation in the context of JAX-RS


Using Bean Validation for the validation of the JSON you send to a Java EE server is very easy. With the @Valid annotation, you can easily specify that all validations specified in the java object must be checked.

But how should you proceed when the same JSON is send to different controllers in your application and that each of these endpoint should validate the JSON differently?  After all, you can’t specify the groups in the @Valid annotation.

Describing the use case

So lets imagine we have a resource, employee, which you can create and update in our application.  In the case of the update command, you should specify the id of employee which you obviously don’t have in the case of the create. 

   "firstName": "Rudy",
   "lastName": "De busscher"
 for the creation and the following JSON for the update:

   "lastName":"De Busscher"
(see also appendix at the end, for a best practice remark)

In this case, I can use the entity class for Employee and have the @NotNull and @Size annotations to indicate the required first and last name fields.

@Size(min = 1)
private String firstName;
@Size(min = 1)
private String lastName;

In the JAX-RS controller, where we have defined the @Path annotation, we can take the JSON from a POST request by using a method definition like this.

public Response create(@Valid Employee employee) {

And as shown in the example, by specifying the @Valid annotation on the method parameter, we can guarantee that the first and last name will be specified and is at least 1 character long.  If not, a response with a HTTP status 4xx will be thrown.

Using validation groups

So how can we now support the use case of the update of an employee name? 

Each bean validation constraint, like @NotNull and @Size has a groups member where you can specify to which group this validation belongs.  These groups are classes, interfaces are mostly used in this situation. Remember classes and not just Strings because the type safety aspect of your code is very important topic for Java EE.

So in the case we have defined an UpdateGroup interface, we can specify the id property of Employee as follows:

@NotNull(groups = UpdateGroup.class)
private Long id;

But there is no option to specify the validation groups together with the @Valid annotation.  So we have to trigger this validation ‘manually’, but as the next code snippet shows you, it is very easy. 

private Validator validator;
public Response update(@Valid Employee employee) {
    validate(employee, UpdateGroup.class);


protected void validate(Object data, Class... groups) {
    Set<ConstraintViolation<Object>> violations = validator.validate(data, groups);
    if (!violations.isEmpty()) {

        // Inform client of validation issue
The Validation object, central in Bean Validation, can be easily injected in your controller.  Asking for validating your object is then as simple as calling a method where you supply the validation group interface class, in our case UpdateGroup.

Informing client of problem

The last step we then have to perform is inform the client in the case he forgot to supply the id property in the JSON object when he asked for an update of the resource.

Also this can be achieved in a few lines of code.  In our simple example here, we just take the default message, or the message we specify on the constraint with the message member, and combine this together with a HTTP Status 409.

When we assembling that in a Response object of JAX-RS, we can just throw that object with a WebApplicationException (funny name, don't you find that also ?). And that is all we need to inform the client (HTTP status 4xx with an indication what went wrong)

protected void validate(Object data, Class... groups) {
    Set<ConstraintViolation<Object>> violations = validator.validate(data, groups);
    if (!violations.isEmpty()) {

        String message = buildMessage(violations);
        Response response = Response.status(409).entity(message).build();
        throw new WebApplicationException(response);    }


Although @Valid annotation has no possibility to specify the validation group it should take, with a few lines of codes, different validations of the same object can be performed easily. 
And the best of all, it can be encapsulated in a method located in your super class of the controller and you just need to supply the data with a list of validation groups which are classes.


The example with the update and the create of an employee isn’t the best possible example.  Because in both cases you could use the id-less version of the JSON and put the id in the URL path for the update.  This is according to the REST way of working better.

POST to URL xxx/employee with 
   "firstName": "Rudy",
   "lastName": "De busscher"

and PUT to URL xxx/employee/123 with

   "firstName": "Rudy",
   "lastName": "De Busscher"