Generating (Maven) Projects

Introduction

The first thing we do when starting a new application is setting up our project. A lot of people use Maven for this, and you have various options how you can do this.
Since I create a lot of projects for testing out various features of the Atbash projects or for trying things out (I have around 300 projects on my computer today) I was searching for some help to do this.

Application setup

When trying things out, I need to have some minimal project setup. Not only do I need the Maven pom file with the required dependencies, I also need some files like configuration or a login file for Octopus.

I do not need to have tools to generate me the JPA entities, JSF Screens or JAX-RS endpoints. Creating a few of them is not difficult with the current IDE’s and that automatic generation is mostly too opinionated so that it is not usable in production systems either.

So what are the options to have this minimal project setup

Copy and Paste

You can always copy such a minimal project you have already created and made some modifications to

  • Change the groupId and artifactId of the pom file
  • Update the dependencies
  • Update the configuration file to match your new dependencies and use case you want to test out.
  • Change the java package with your java code
  • Add or remove code depending on the feature for this use case.

This is a valid procedure and in most cases the most efficient one. You don’t need to learn any new tool, extend it with your features (Like Octopus in my case) but of course, it is not the most fun way of doing things.

JBoss Forge

JBoss Forge https://forge.jboss.org/ is a tool specifically designed to get your application up and running fast. It not only generates the project for you but also can help you in generating those well-structured classes like JPA entities, JAX-RS endpoints, and screens with JSF or Angular(JS).

I used it in the past and it can be a valuable tool but it is not the right thing for what I want.
Although you can generate your maven project, you need a script and/or a custom add-on for the features that I want (specific dependencies within the pom.xml file and some configuration and java files)

It also has a lot of options to generate code for you, but again this is sometimes opinionated and not what you or your company wants to use.

Other tools

Since there are various other tools on the internet, the topic seems to be important for a lot of people. Similar tools which I found are generjee and factorEE.
Not all of them are maintained anymore or do focus on the wrong things (for my use case) like generating code.
I also find a CLI very important in this case since it allows you to create an application very rapidly (and recreate it based on the same configuration)

Jessie

So, due to the lack of the right tool for me, I created one of my own called Jessie (Java EE Start project as it was geared at that time towards Java EE). Last year with the release of CDI 2.0, I did a rewrite of it using the Java SE CDI container and included the usage of ThymeLeaf as templating mechanism so that it became easier to generate files which can be customized.

In the OpenSource spirit of Atbash, I placed the code on Github  and created a front end for it.
You can play with it on the OpenShift V3 instance  or can download the code that just needs a few parameters within a YAML config file and the CLI version generates your project.

The first version has support for Java EE and additional frameworks like DeltaSpike, PrimeFaces, and Octopus, the security framework.

Since I’m also involved with MicroProfile lately, a version for MicroProfile and the support for the different vendor implementation like LibertyIO, WildFly Swarm, Payara Micro etc will be created later on.

Conclusion

When setting up a new project, the most efficient solution is creating it from scratch or start from a similar existing project and make the required adaptations.
Another useful tool is JBoss Forge, mainly when you are interested in generating some code.

Jessie has been created a few years ago as a toy and now available on GitHub and it was a good learning opportunity for CDI 2.0, templating with ThymeLeaf and creating a tool which runs in multiple environments (CLI, Java FX, Web/JSF)

Maybe it is also helpful for you.

Have fun.

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.