Categories
JSF

A renderer interceptor concept for Java ServerFaces

Introduction

A renderer is an important concept within JSF. It is responsible for creating the HTML output of a page from the Component tree but also processing the response from the browser is their responsibility.

It takes the values from the attributes of a component to do their job. So developers mostly don’t interact directly with them, unless you are writing custom components and write a renderer yourself.

But sometimes it could be handy if we could create some kind of interceptor for the renderers methods so that we could have

  • Generic logic for component-based security
  • Retrieve validation info (like required, max size) from Beans so that information isn’t defined multiple times.

That is what Jerry and Valerie provide for you.

Origin

The first RendererInterceptor is committed some 10 years ago within the MyFaces-Extensions-CDI project (ExtVal). A set of useful extensions for Java EE programs covering CDI, Bean Validation, and JSF.

With the RendererInterceptor you have a before and after method for every major method in a Renderer which is decode, encodeBegin, encodeChildren, encodeEnd and getConvertedValue.

About 3 years ago, I extracted the RendererInterceptor concept from ExtVal to become Jerry and rewrote it to have a deep integration with CDI and target it exclusively to JSF 2.x. The Validation extensions parts for Bean Validation were bundled into Valerie.

That way, the most powerful code from ExtVal could be used standalone and Jerry could become the heart of the Declarative Permissions based framework Octopus for the JSF component security.

Now, a new rewrite is performed to bring it within the Atbash project family and restrict its usage to Java EE 7 (and later) using the CDI 1.1 features. This is the new release version 0.9.0.

The ComponentInitializer is greatly enhanced which I will explain in this blog.

ComponentInitializer

The ComponentInitializer is a specialized form of a RendererInterceptor and can change the JSF component just before it is encoded (HTML is generated) by the Renderer.

This can be handy if you want to perform some cross-cutting concern, so for all JSF components or all components of a certain type (input type) without the need to actually know all these JSF components or even adjust the renderers.

Classic examples are

  • Change the rendered attribute based on the presence of an inner tag to have declarative Component security (This is what Octopus does)
  • Change the look of components, like setting the background color of all required input fields.
  • Retrieve information from bean properties (like @NotNull) and set the required property. That way information is only required on the model classes and doesn’t need to be duplicated on the JSF components (This is what Valerie does)
@ApplicationScoped
public class RequiredInitializer implements ComponentInitializer {

   @Override
   public void configureComponent(FacesContext facesContext, UIComponent uiComponent, Map<String, Object> metaData) {
      InputText inputText = (InputText) uiComponent;

      String style = inputText.getStyle();
      if (style == null) {
         style = "";
      }

      if (inputText.isRequired()) {
         style = style + " background-color: #B04A4A;");

      } else {
         style = style.replace("background-color: #B04A4A;","");

      }
      inputText.setStyle(style);
   }

   @Override
   public boolean isSupportedComponent(UIComponent uiComponent) {
      return uiComponent instanceof InputText;
   }
}

 

The above example sets the background color of all input fields if they are required. This is just an example and probably you should implement such a functionality using styleClasses so that color can be defined outside the code in CSS.
All CDI beans implementing the ComponentInitializer interface are picked up automatically and applied to the correct JSF components based on the return value of the isSupportedComponent() method.

Due to the enhanced functionality within this version, a ComponentInitializer can be executed multiple times and thus we need to ‘undo’ our changed style in case the component is not required.

Just as in the previous release, by default, the ComponentInitializer is executed only once. When due to AJAX request, for example, the component is rendered again, the ComponentInitializer isn’t executed anymore. This is done to minimize the overhead of the feature.

However, when the component is in some kind of repeatable parent component, the Initializer is executed multiple times. The repeatable constructs detected are <ui:repeat> and UIData constructs like <h:datatable>.
This is required because the information can be different for each row like the case where the input field required property depends on the row (required=”#{_row.field.required}”)
This logic is added in this release and important to know when you upgrade from an older version.

RepeatableComponentInitializer

The new RepeatableComponentInitializer construction in this release is always executed, regardless of the ‘location’ of the component.

A use-case for this situation is the fact that a PrimeFaces table footer is always present, although no pagination is shown (resulting in a thin colored line). With a RepeatableComponentInitializer you can remove this footer (or upgrade to the upcoming 6.2 version where this is fixed by PrimeFaces code.

Setting up

You just need to add the Jerry (and/or Valerie) maven dependency to your JSF application.

<dependency>
   <groupId>be.atbash.ee.jsf</groupId>
   <artifactId>jerry</artifactId>
   <version>${atbash.jerry.version}</version>
</dependency>

And you are ready to go.

Some more information can be found in the user manuals for Jerry and Valerie.

When you have an application using an older version of Jerry and/or Valerie (0.4.1 and older) you can use the code within the Atbash migrator project to help you convert the import statements, dependencies and JSF namespaces to the new Atbash values.

Conclusion

With the RendererInterceptor you can perform all kind of useful code in a generic way, without knowing or changing the Renderers. The new release has a greatly improved ComponentInitializer execution (detecting repeated structures like <ui:repeat> and <h:dataTable>), the new RepeatableComponentInitializer concept and is part of the ever-growing Atbash projects.

Have fun.

 

Categories
Configuration

Implicit converters for MicroProfile Config

Introduction

Last month (January 2018), an update of the MicroProfile Config specification, version 1.2, was released which makes it easier to convert the configuration values to class instances.
It adds the concept of implicit/automatic converters and removes the requirement for creating specific converters in many cases.
The first implementations are already available and Atbash Configuration is now also updated.
This blog describes what the implicit/automatic converters are and how you can use them.

Converters

The configuration values we define are Strings because they are defined as a set of Characters in the configuration files. Using the configuration could be limited to a system which is capable of reading those Strings and that the developers need to convert these values to the proper instance (like Integer, Boolean or application specific classes) themselves.
But in that case, each developer will write his own set of converters and in the case of Integers and Booleans, for example, they are all the same.
So the framework itself can take care of these converters. And since we have then already the concept of a convert, it is easy to foresee an SPI which allows the creation of custom Converters by the developer for their application specific classes.
These basic converters for Integer and Boolean for example where present since the first release of the spec. Just as the SPI to add your own converters.

Implicit Converters

But the creation of all those custom converters can be minimized further. Since our application specific classes can be created from a String, they probably have some means of instantiating them through a method which takes a String parameter
– The constructor
– A static method with names like valueOf or parse.
So with the new implicit/automatic converters feature, when we have some class like this
public class ClassWithStringConstructor {
    private String value;

    public ClassWithStringConstructor (String value) {
        this.value = value;
    }

    public String getValue() {
        return value;
    }
}
and have a parameter
some.key = Atbash

We can retrieve an instance of the class, with the value using

config.getValue("some.key", ClassWithStringConstructor.class)

or when we are in a CDI enabled context, we can also use injection

@Inject
@ConfigProperty("some.key")
private ClassWithStringConstructor parameterValue;

Collection type parameters

Another nice addition to this 1.2 release, is the use of collection type parameters. The ability to have multiple parameter values, like a list of values which is converted to an Array, List or Set.
It is quite common that a configuration value is, in fact, a list of value.
pets = dog,cat
previously, the developer needed to split the String and use the individual parts separately (although this is a very simple task with String.split() ), can be done automatically.
config.getValue("pets", String[].class)

With injection, we can automatically convert it to a List or a Set.

@Inject
@ConfigProperty(name = "pets")
private List<String> pets;

The List and Set variants can’t be used in a programmatic way (using config.getValue) since the second parameter doesn’t accept parameterized types (like List<String>).

When you have a value which contains a comma it in, you need to escape it
a,b,c\\,d

which results in 3 configuration values, where the last one is c,d.

Implicit combined with Collection.

We can even combine the collection type feature with the implicit/automatic converter feature. If we instead specify the class name like ClassWithStringConstructor instead of String, the configuration framework will use the appropriate way of converting.
config.getValue("pets", ClassWithStringConstructor[].class)

or

@Inject
@ConfigProperty(name = "pets")
private List<ClassWithStringConstructor> pets;

Octopus Config

As you could read in a previous blog, Octopus Config is a Java 7 port from Geronimo config. The support for the implicit/automatic converters and collections (like the arrays, List, and set) is taken from them.
Octopus Config itself is also updated so that the YAML usage supports the Collection type parameters. The example above with the pets can be written in the YAML equivalent format as
pets: [dog , cat]

The release 0.9.1 contains also some small other features are listed here. Most notable features are

– Improved Class converters based on different classloaders.
– Test artefact.
– Logging in Java SE environment
– Improvement information in logging with @ModuleConfigName
– Compatibility with another MicroProfile Config implementation on Java 8.

Conclusion

With the addition of the implicit/automatic converters, the need for writing custom converters can be dropped and conversion will take place by convention.
The Octopus Config version v0.9.1 is updated to incorporate these features together with some small other improvements and fixes.
Have fun.
Categories
Testing

Programmatic CDI access and Unit testing

Introduction

There are situations where you need to access the CDI system programmatically, instead of using annotations like @Inject

  • You want to retrieve a CDI bean within a context (class) which isn’t CDI-aware.
  • It is easier to retrieve an optional or multiple beans programmatically instead of using Instance.

Since CDI 1.1 (Java EE 6), this can be easily achieved by using

CDI.current();

The programmatic access is most useful if you are creating a library/framework or some reusable piece of functionality. But I guess everyone who creates more than 1 application is in the situation where things can be reused.

This blog shows the equivalent programmatic constructs but most importantly, how you can unit test your bean in those cases (no CDI container needed!)

Optional CDI bean

An optional bean is interesting in the situation where you define some basic functionality but in case the developer defines a CDI bean implementing the interface, that custom developer logic is executed.

public interface SomeInterface {}
// with classic injection
@Inject
private Instance<SomeInterface> optional;

   // Within a method
   if (!optional.isUnsatisfied()) {
      optional.get();
   }
// programmatic
// Within method
Instance<SomeInterface> instance = CDI.current().select(SomeInterface.class);
instance.isUnsatisfied() ? null : instance.get();

Multiple beans

Within a Chain of Responsibility pattern or the situation where you can have multiple add-ons which perform some logic in a certain situation, are the ideal situations for having multiple CDI beans implementing an interface.

// with classic injection
@Inject
private Instance<SomeInterface> addonInstances;

   // Within a method
   List<SomeInterface> addons = new ArrayList<>();
   addonInstances.iterator().forEachRemaining(
      addons::add
   );

// programmatic
// Within a method
List<SomeInterface> addons = new ArrayList<>();
for (SomeInterface addon : CDI.current().select(SomeInterface.class)) {
   result.add(addon);
}

Sending Events

One of the nice features of CDI is the ability to sends events between consumers and producers without the need of registering the consumers with the producer for example.

Producing the Event can be done using

// with classic injection
@Inject
private Event<Payload> payloadEvent;

   // Within a method
   payloadEvent.fire(new Payload());
// programmatic
// within a method
CDI.current().getBeanManager().fireEvent(new Payload());

Unit Testing

Now that you have used some CDI bean retrievals in a programmatic fashion, what happens when you execute a unit test?

java.lang.IllegalStateException: Unable to access CDI

When running with plain Java, without any CDI container, you get this message because the API doesn’t contain an implementation, only the specification of the behavior.

You can of course switch to integration testing, where you launch a proper CDI container. But you can, of course, stay with your basic unit testing and have a simple, minimalistic Cdi container implementation (which is by the way not very difficult to create)

Suppose we have following code

public SomeInterface readOptionalInstance() {
   Instance<SomeInterface> instance = CDI.current().select(SomeInterface.class);
   return instance.isUnsatisfied() ? null : instance.get();
}

And we like to test this piece of code then the optional bean is not defined with something like this

@Test
public void readOptionalInstance_NotPresent() {
   Assert.assertNull(viewBean.readOptionalInstance());
}

We need a simple CDI implementation. This is provided by the be.atbash.util.BeanManagerFake class, available in the tests artifact of atbash utils-cdi.

<dependency>
   <groupId>be.atbash.utils</groupId>
   <artifactId>utils-cdi</artifactId>
   <version>0.9.0</version>
   <classifier>tests</classifier>
   <scope>test</scope>
</dependency>

<dependency>
   <groupId>org.mockito</groupId>
   <artifactId>mockito-core</artifactId>
   <version>2.13.0</version>
   <scope>test</scope>
</dependency>

The CDI fake container (as in not real implementation, maybe not the correct term in the test concepts Dummy/Fake/Stub/Spy) is using Mockito underneath, so that is also a dependency we need to add to the project.

The test can then be adapted as follow

private BeanManagerFake beanManagerFake = new BeanManagerFake();

@After
public void cleanup() {
   beanManagerFake.deregistration();
}

@Test
public void readOptionalInstance_NotPresent() {
   beanManagerFake.endRegistration();
   Assert.assertNull(viewBean.readOptionalInstance());
}

We can instantiate the BeanManagerFake as a regular bean. Important here is the deregistration method after the test is finished. It is the idea to keep the fake CDI container between tests alive but only clear the contents. In the current version, the container is also unset which makes it necessary that the beanManagerFake variable is an instance variable (and not a class variable)

With the endRegistration method, we signal that all configuration of the CDI container has taken place and that the operational modus can start. It can give some instances of interfaces if needed as in our test example.

Here we didn’t register anything, so we get a null back.

This is updated test class which contains also a test in the case we specify an instance in the CDI container.

@RunWith(MockitoJUnitRunner.class)
public class ViewBeanTest {

   private ViewBean viewBean = new ViewBean();

   @Mock
   private SomeInterface mockClass;

   private BeanManagerFake beanManagerFake = new BeanManagerFake();

   @After
   public void cleanup() {
      beanManagerFake.deregistration();
   }

   @Test
   public void readOptionalInstance_NotPresent() {
      beanManagerFake.endRegistration();
      Assert.assertNull(viewBean.readOptionalInstance());
   }

   @Test
   public void readOptionalInstance_Present() {
      beanManagerFake.registerBean(mockClass, SomeInterface.class);
      beanManagerFake.endRegistration();
      Assert.assertNotNull(viewBean.readOptionalInstance());
      Assert.assertTrue(viewBean.readOptionalInstance() == mockClass)
   }
}

You can see that we can define a mock (with the @Mock of Mockito) as a bean within the CDI container with the registered bean. We supply the instance and the type to which this instance must be bound. Within CDI, an instance can be bound to multiple class instances like the class itself, the interface, Object.class etc …) This is also possible with BeanManagerFake as the second parameter of the registerBean method is a varargs with all the class values.

And if you run the above test, you will see they are all green, so we, in fact, get the exact instance of the CDI bean (here the mock) back as the return value of the method.

Of course, when you have very complex Cdi constructions, it is better to test them in a real CDI container. But if the focus is on the business logic, the simple CDI container for testing will do.

Code

The code of BeanManagerFake is available in the Atbash utils GitHub repository and artifacts are on Maven Central.

Conclusion

Using the programmatic interfaces of the CDI container is easier in those cases where you need to retrieve optional or multiple CDI beans. And of course in the context where the dependency injection isn’t available. And with the help of the BeanManagerFake, a simple CDI container for testing, Unit tests are possible which make is easier then to set up a full blown integration test with a container.

Have fun.

This website uses cookies. By continuing to use this site, you accept our use of cookies.  Learn more