Free Online Courses for Software Developers - MrBool
× Please, log in to give us a feedback. Click here to login
×

You must be logged to download. Click here to login

×

MrBool is totally free and you can help us to help the Developers Community around the world

Yes, I'd like to help the MrBool and the Developers Community before download

No, I'd like to download without make the donation

×

MrBool is totally free and you can help us to help the Developers Community around the world

Yes, I'd like to help the MrBool and the Developers Community before download

No, I'd like to download without make the donation

Apache DeltaSpike: Programmable CDI

See in this article the productivity in the world of CDI taken to the extreme, with an overview of DeltaSpike, allowing you to know their main features and understand why this project is so innovative

It is undeniable to say that the CDI specification definitely changed the way of developing software using Java. The concept of dependency injection, which from the beginning is disseminated as a principle (and good practice) in object orientation, has become a first class citizen. In addition to the injection facilities, the ability to provide Beans that have a well-defined life cycle, made the CDI became one of the subjects most talked about lately in blogs, articles and presentations in various technology events.

In the CDI version 1.0 (JSR 299), the Expert Group was very happy to specify as part of the functionality an important principle of object-oriented programming: The principle OCP (Open Closed Principle). This determines which objects should be open for extension and closed for modification.

In CDI this feature was named Portable Extensions. This feature allows the CDI to be extended to the point of its modified behavior, enabling new features are available through the dynamic registration of new Beans CDI, modifying the metadata (qualifiers, alternatives and interceptors) existing beans and the creation of new contexts.

Not take long for several Java communities and organizations realize that CDI could also be used as a foundation for frameworks or for integration with their existing products and technologies. With this, several initiatives in parallel spread quickly.

Projects like JBoss Seam 3, Apache MyFaces CODI and CDISource become large (in terms of quantity and quality) repositories CDI extensions. At first, this only proved that the CDI specification became a success, by providing a true ecosystem for developers.

However, in late 2011, the communities formed by Red Hat, Apache and CDISource decided to unite their efforts and create a set of CDI extensions in a standardized manner and combining the best features of each of these projects.

Soon after, in early 2012, it was announced the DeltaSpike project. This project was incubated within the Apache Foundation until May 2013, when he became a top-level project. Even before the release of the final version, the DeltaSpike was already being used by other projects, such as PicketLink, Red Hat.

The version 1.0 of DeltaSpike was launched in June this year and almost two months after it was announced at JavaOne 2014 (in September) that the project took home a statuette of Duke's Choice Award. Since then, this solution is gaining more users, contributors and contributions.

In Figure 1 you can have an overview of the history of the project.

Figure 1. Historical overview of DeltaSpike project.

Essentially, DeltaSpike is a set of extensions to the CDI, with useful features that are not available in the specification. In order to maintain a logical grouping of these extensions, the project consists of a main module and several optional modules, namely:

  • Core: It is the main module DeltaSpike, the only one that is required. It provides features such as Configuration API, Type-safe ProjectStage and i18n, the @Exclude annotation, an exception handling framework, etc .;
  • Security: Module that provides a safety mechanism using annotations;
  • JPA: It is the module that allows CDI Beans are part of a transactional context (such as EJBs) through the use of @Transactional annotation. This module also states the @TransactionScoped context that determines the life cycle of a CDI Bean boots and finalized with the transaction;
  • Date: Module that brings features such as the implementation of the Repository pattern, providing access to data declaratively and dramatically reducing the required code. This module also provides JPA entities audit functionality;
  • JSF: Module that provides new CDI scopes (WindowScoped, ViewScope, ViewAccessScoped and GroupedConversationScoped) as well as the possibility of metadata configuration (related to safety, navigation, forwarding, extension, etc.) of the JSF pages (view-config) of programmatically. In addition, it allows classes of JSF specification, as Converters and Validators, can receive the injection CDI Beans;
  • Bean-Validation: Module that allows the injection of CDI and EJB objects validators;
  • Servlet: Module that enables the injection of Servlet objects and spread the events of the Servlet life cycle for CDI;
  • Partial Bean: Module that allows you to create proxies for abstract interfaces and classes that will have the same behavior CDI beans. This feature helps in creating CDI beans without the need to implement an interface or abstract class directly;
  • Scheduler: Module that provides integration with the Quartz in order to facilitate the scheduling of Jobs and also allow the injection of CDI objects;
  • Container & Control/Test-Control: Both modules allow the startup and shutdown of ICD containers in Java SE environments, and to control the life cycle of contexts and facilitate the writing tests for CDI components.

The ratio of DeltaSpike with Java EE 7 and CDI 1.1

In addition to being this huge collection of extensions to the CDI, DeltaSpike also acts as an enabler of the development of this specification. Many features that today are already available in Java EE 7, inclusive, got their start in DeltaSpike. Here are some examples:

  • The @Transactional annotation to POJOs;
  • The @Vetoed annotation of Java EE 7 exists in DeltaSpike as @Exclude;
  • Allow the injection Beans IDUs in EntityListerners JPA specification and classes that will perform validation on the Bean Validation specification;
  • The viewing scope (@ViewScoped), where the beans are discarded when the user navigates to another page. This solution was already available in DeltaSpike before they become present in JSF 2.2 specification.

The Figure 2 shows all the modules that make up the DeltaSpike. The modules represented in blue color only contain unique features, which were not even specified in the CDI. Already the module in green contains features that are already present in CDI 1.1, but thanks to DeltaSpike can run on Java EE 6/CDI 1.0 environments.

The orange color indicates the modules that have already present features in CDI 1.1 and also other novel features. By having features already implemented in Java EE 7, some people may be led to wonder why use DeltaSpike.

At this point it is worth remembering that in corporate environments the use of supported and approved Java EE 7 servers may take a few years and, in these cases, using the DeltaSpike, some of the features of Java EE 7 as well as numerous other features, will be available in your Java EE 6 server, allowing your code is up to date and facilitate a future upgrade, and, of course, the other possibilities and facilities that DeltaSpike available.

Figure 2. DeltaSpike modules and its relations with the CDI 1.1.

Installing DeltaSpike in your project

The installation of DeltaSpike can be done manually by downloading (see the address in the Links section) of the package and copy the JAR files to the application CLASSPATH. The DeltaSpike modules are always available in two files: a JAR containing the APIs and other JAR containing implementations. If your project is a WAR, copy both the module files you want to use for the WEB-INF/lib folder.

However, the recommended way to install is to use Maven, where DeltaSpike dependencies can be declared in the pom.xml.

A good practice is to declare the version of DeltaSpike as a property, thereby facilitating project update (see Listing 1). Then, as shown in Listing 2, you must compulsorily declare the core module and optionally the other modules you want to use. In all cases, the corresponding device API must be within the scope of "compile" and the corresponding device for implementation, the scope of "runtime", since the implementation is not required for compilation but is necessary for execution.

Listing 1. Statement version of DeltaSpike.

  1 <properties>
  2     <!-- other properties of the project -->
  3
  4     <!-- DeltaSpike Version -->
  5     <deltaspike.version>1.0.3</deltaspike.version>
  6 </properties>

Listing 2. Declaration of the core module.

  1  <!-- DeltaSpike Core -->
  2  <dependency>
  3     <groupId>org.apache.deltaspike.core</groupId>
  4       <artifactId>deltaspike-core-api</artifactId>
  5       <version>${deltaspike.version}</version>
  6       <scope>compile</scope>
  7  </dependency>
  8 
  9  <dependency>
  10       <groupId>org.apache.deltaspike.core</groupId>
  11       <artifactId>deltaspike-core-impl</artifactId>
  12       <version>${deltaspike.version}</version>
  13       <scope>runtime</scope>
  14 </dependency>

The Core Module

As the name says, this is the central module of DeltaSpike. It is the only required module. Its aim is to serve as a basis not only for the other modules, but also to provide features in common for the application being developed.

In this module you can find mechanisms for configuration and design verification stage, internationalization, resource injection, exception handling, beans exclusion, as well as a number of utility classes. The following are these mechanisms and sample code demonstrating its actual application in projects.

Type-safe ProjectStage

During the software development cycle, applications need to behave differently depending on the current stage of the project, for example, do not carry out certain checks that should be present in the testing phases and production or to provide a Bean CDI which produces sample data only during the testing phase.

For such situations, the DeltaSpike provides a Bean which, when injected, identifies what stage the project is. By default, DeltaSpike provides some stages, defined by convenience. Are they:

  • UnitTest - used for unit testing;
  • Development - used during the development life cycle;
  • IntegrationTest - Used integration tests;
  • SystemTest - Used integration tests related to the environment (operating system and hardware);
  • Staging - used in pre-production with end users;
  • Production - Represents the production phase itself.

To know at what stage the project is just inject ProjectStage any Bean as in Listing 3. You can also use this information in JSF pages to display or hide parts of a page. See an example in Listing 4.

The design stage of the setting is made by org.apache.deltaspike.ProjectStage property, by an existing configuration mechanisms. The DeltaSpike configuration API is presented below.

Listing 3. Example of use of ProjectStage.

  1  @Named(“myConfig”)
  2  public class ApplicationConfig {
  3
  4     @Inject
  5     private ProjectStage projectStage;
  6
  7     // Demonstrates how to return the current Project Stage
  8     public ProjectStage getProjectStage() {
  9        return projectStage;
  10    }
  11    
  12    // Demonstrates how to check if the current ProjectStage is the development
  13    public boolean isDevelopment(){
  14        return ProjectStage.Development.equals(this.projectStage);
  15     }
  16 }

Listing 4. Example of use of ProjectStage in JSF pages.

  1  <h:panelGroup rendered="#{config.projectStage == 'Development'}"> 
  n      . . .
  10 </h:panelGroup>

DeltaSpike Configuration

The purpose of this feature is to provide a mechanism for applications (and also for the very DeltaSpike) which enables providing properties (key and value) fully flexible. To understand how to use this API in your favor, it is interesting to learn first as the DeltaSpike can be configured.

The DeltaSpike can get these properties of various configuration sources. Each source has a value, the higher the number, the more important it is, then overwriting the previously reported values. By default, the following configuration sources (in order of importance) are used by DeltaSpike:

  • System Properties: Represents amounts reported in the implementation of the JVM with the -D parameter. For example: -Dorg.apache.deltaspike.ProjectStage=Development;
  • Environment variables: Represents amounts reported as environment variables in the operating system. On Linux, it usually is configured using the command line: export org.apache.deltaspike.ProjectStage="Development";
  • JNDI values: Represents the values available via JNDI. These values are in the JNDI directory "java:comp/env/deltaspike/";
  • Properties File: Represents the values available within a properties file. By default, DeltaSpike uses the META-INF/apache-deltaspike.properties file.

In addition to these standard options, you can also write your own configuration source. This is useful if you, for example, allow your application or use DeltaSpike coming values of a database and /or files in XML, JSON, YAML, etc.

As an example, say your application needs information from the JMS queue (name and user). So instead of putting this information "hardcoded" in the code, we can use one of the sources mentioned configuration to provide these values outside source.

In Listing 5, these values were placed in /META-INF/apache.deltaspike.properties file. Note that the property jms.queue.name has a suffix Development (in line 1) and Production (line 2).

This is an optional form of integration with type-safe ProjectStage, thereby allowing different configuration values for each stage of the project. If the value is the same, regardless of the stage where the project is, you can only inform the property without using any suffix, as shown by the line 3.

Listing 5. File containing DeltaSpike settings.

  1 jms.queue.name.Production=queue/queueProduction
  2 jms.queue.name.Development=queue/queueDevelopment
  3 jms.queue.username=userFile

In Listing 6 we see how the properties can be accessed via injection, with the qualifier @ConfigProperty or programmatically using the ConfigResolver class (line 12).

Listing 6. Example of how to get settings.

  1 @Named
  2 public class ApplicationConfig {
  3 
  4    // Injects configuration
  5    @Inject
  6    @ConfigProperty(name = "jms.queue.username")
  7    private String userJMS;
  8
  9     // Demonstrates how to read settings easily and according to ProjectStage
  10    // Uses programmatically
  11    public String getFilaJMS() {
  12        return ConfigResolver.getProjectStageAwarePropertyValue("jms.queue.name");
  13    }
  14
  15    // Demonstrates how to read settings easily and according to ProjectStage
  16    // Use via injection CDI
  17    public String getUsuarioJMS() {
  18       return usuarioJMS;
  19    }
  20 }

The @Exclude annotation

In version 1.0 of the CDI, by default, all classes of a CDI project are available for injection. For this reason, there have been several complaints from users who wanted a way to prevent certain classes were available.

The feature "vetoes" a class to become a Bean is present in CDI 1.1 specification, which from the @Vetoed annotation the annotated classes are now ignored.

However, even there the @Vetoed annotation to CDI 1.1, the @Exclude annotation, provided by DeltaSpike, has some advantages, such as the possibility of longer ignore beans CDI CDI 1.0 and still ignore them based on the stage of the project (ProjectStage) or based on expressions. This feature opens the door to possibilities like having beans that are activated only under specific circumstances.

In Listing 7 we can see some examples of CDI beans using @Exclude annotation. In line 1, the WillNeverInjected class is not enabled as Bean CDI for injection. In line 6, the MyBean class will always be available as a CDI bean, except when the stage of the project is "Development".

In the line 11, in the opposite way, the MyBeanDevelopment class is enabled only when the stage of the project is "Development". Finally, on line 16, the MyBeanConfigurable class can only be injected into other beans if the expression informed within the onExpression parameter returns true.

Listing 7. Examples of use of @Exclude annotation.

  1  @Exclude
  2  public class WillNeverInjected {
  3   // This bean is always ignored by the CDI
  4  }
  5 
  6  @Exclude(ifProjectStage = ProjectStage.Development.class)
  7  public class MyBean {
  8   // This bean will not be available during the development stage
  9  }
  10 
  11 @Exclude(exceptIfProjectStage = ProjectStage.Development.class)
  12 public class MyBeanDevelopment {
  13  //This bean is only available during the development stage
  14 }
  15 
  16 @Exclude(onExpression = "someConfiguration == someValue")
  17 public class MyBeanConfigurable {
  19  // This bean is only available during the development stage
  20 }

Exception handling

Often based on the type of exception that happens in the system, we have the need to take some actions such as log message, notify the error to an administrative console, count the number of access attempts and block a user.

Anyway, there are several possibilities that we want to do with one exception, and in these cases it is common to see the use of aspect-oriented programming to solve this kind of situation

In order to allow exceptions are handled in uncoupled form the class that threw the exception, DeltaSpike provides a mechanism from which the exception thrown as a CDI event can be treated in other classes.

On line 13 of Listing 8 we see that the exception PersistenceException was encapsulated within the CDI ExceptionToCatchEvent event. From this moment, annotated classes with @ExceptionHandler will be used to handle these exceptions.

Listing 8. Placing the exception in CDI event bar.

  1  public class PessoaDao {
  2
  3     @PersistenceContext private EntityManager em;
  4  
  5     @Inject private Event<ExceptionToCatchEvent> catchEvent;
  6  
  7     public Pessoa searchByName(String name) {
  8          try {
  9              Query q = em.createQuery("SELECT p FROM Person p WHERE p.name = :name");
  10             q.setParameter("name", name);
  11             return q.getSingleResult();
  12         } catch (PersistenceException and) {
  13             catchEvent.fire(new ExceptionToCatchEvent(e));
  14         }
  15     }
  16 }

Once the exception is CDI event bus, the developer must implement methods that treat. These methods should contain the first parameter with the @Handles annotation and type of the parameter must be ExceptionEvent. This ExceptionEvent class, in addition to providing information about the exception, also provides methods that control the exception processing, such as aborting the treatment in all handlers or mark the exception as already treated.

In addition, you can still use Qualifiers CDI to differentiate equal exceptions, but they had different origins (batch processing, JSF form, REST endpoint). Listing 9 shows examples of exception handlers.

Listing 9. Handlers examples.

  @ExceptionHandler
  public class MyHandlers {
   
    void logExceptions(@BeforeHandles ExceptionEvent<Throwable> evt, Logger log){
      log.warn("exception: " + evt.getException().getMessage());
    }
   
    void handleException(@Handles @RestRequest ExceptionEvent<Throwable> evt, 
                         ResponseBuilder builder) {
      builder.status(500).entity("Http Response Code 500: " 
        + evt.getException().getMessage()).type(MediaType.TEXT_PLAIN_TYPE);
      evt.handledAndContinue();
    }
   
     void showFacesMessage(@Handles @FacesRequest ExceptionEvent<Throwable> evt, 
                          FacesContext facesContext) {
      facesContext.addMessage(null, new FacesMessage(evt.getException().getMessage()));
      evt.handledAndContinue();
    }
  }

Type-safe I18N

Working with internationalization, often we deal only with strings. To solve this problem the DeltaSpike brings the concept of internationalization type-safe through proxies CDI.

In this way, the Java interfaces are used to represent system messages by simply receiving both the @MessageBundle annotation. In a properties file, the key property must have the name of the method of the annotated interface @MessageBundle.

If there is a need to set a different key name, just use the @MessageTemplate annotation about the method name.

Because it is a proxy CDI, this interface can also receive the @Named annotation, so that messages are also available in JSF forms. The Listing 10 interface and file properties in Listing 11 to provide an example of how we can use these interfaces to represent messages that are automatically translated according to the definition of the system or web-browser locale.

Another interesting feature is that the translated messages can receive parameters passed in the methods. For example, invoking the method defined in line 15 of Listing 10 as Welcome ("Fabrício"), the displayed value will be the String "Welcome, Fabrício." To understand this behavior, note the line 3 of Listing 11.

Listing 10. Examples of use of I18N DeltaSpike functionality.

   1 package mypackage.i18n;
   2
   3 @Named("label")
   4 @MessageBundle
   5 public interface Messages {
   6
   7   // use the value 'User' of the properties file
   8   public String user();
   9
   10   // use the value 'password' the properties file
   11   @MessageTemplate("{password}")
   12   public String password();
   13
   14   // pass the value of the method as a parameter to the value 'followingUser'
   15   public String Welcome (String username);
   16}

Listing 11. Examples of file properties.

  one file for each translation
  mypackage/i18n/Messages_en.properties
  mypackage /i18n/Messages_fr.properties
  mypackage i18n/Messages_de.properties 
 
  file containing the default translation:: mypackage/i18n/Messages.properties:
  1 user=User
  2 password=Password
  3 welcome=Welcome, %s!

This Messages interface (defined in Listing 10) can be injected into other beans to provide messages (Listing 12) or be used in JSF forms as the example in Listing 13.

Listing 12. Use of type-safe I18N in Beans CDI.

   1 @Model
   2 public class MyBean {
   3
   4    @Inject
   5    private FacesContext facesContext;
   6
   7    @Inject
   8    private Messages msg;
   9
   10   public void myAction (User user) {
   11       // business logic
   12       facesContext.addMessage (null,
   13       new FacesMessage(msg.followingUser(user.getUsername())));
   14   }
   15
   16}

Listing 13. Use of type-safe I18N JSF forms.

  1 #{label.user()}:
  2 <br />
  3 #{label.password()}:

Injecting resources

During development, we often need to read a file that is on the hard drive or in a JAR. Thinking about it, the DeltaSpike brings simple functionality, but extremely useful for reading files.

By using the @InjectableResource annotation on an InputStream as line 5 of Listing 14, the target file will be searched in the file system or in the classpath. Despite this feature, you can also implement your own mechanism to search for files, such as HTTP.

Listing 14. Injecting InputStream for reading files.

  1 @Named
  2 public class InformationSystem {
  3
  4    @Inject
  5    @InjectableResource(location = "/version.txt")
  6    private InputStream is;
  7
  8    // The InputStream was injected
  9    public String getVersion() throws IOException {
  10        try (BufferedReader br = new BufferedReader(new InputStreamReader(is))) {
  11            return br.readLine();
  12        }
  13   }
  14 }

The JSF module

In order to provide a number of features to JSF, this module is installed as the core module, through the declaration of Maven dependencies in the pom.xml file. This is one of the largest modules DeltaSpike in functionality and see the key below them.

Scopes

The JSF module provides a number of new scopes and also gives scopes defined in javax.faces.bean package, JSF 2.0, the same treatment given to the scope of CDI. The new scopes are:

  • @WindowScoped: It is a scope that much resembles a session window or tab, so that the data between the windows or tabs are not shared;
  • @GroupedConversationScoped: Through @ConversationGroup annotation, this scope allows multiple conversations exist in parallel and in isolation;
  • @ViewAccessScoped: This scope remains active beans while they are referenced by page. These same beans remain active if they are referenced again on the next page;
  • @ViewScoped - Unlike what happens with @ViewAccessScoped, with this the scope beans are destroyed so that navigation is made to any other page.

This scope is not part of CDI, but the JSF 2. However, like other scopes JSF 2.0 (javax.faces.bean.ApplicationScoped, javax.faces.bean.SessionScoped and javax.faces.bean.RequestScoped ), is promoted automatically by DeltaSpike to receive the same treatment given to the scope of the CDI (javax.enterprise.context. ApplicationScoped, javax.enterprise.context.SessionScoped and javax.enterprise.context.RequestScoped).

The Java EE 6 brought the @RequestScoped annotations, duplicate @SessionScoped and @ApplicationScoped in javax.faces.bean packages and javax.enterprise.context by a divergence between the Expert Groups of the specifications CDI 1.0 and JSF 2.0. However, the JSF 2.2 specification says the javax.faces.bean package annotations will be "deprecated" in future versions and so developers are strongly recommended to avoid these annotations and use the options provided by the CDI.

Type-safe view-config

In JSF, the views are represented through the pages, whether or JSPs XHTMLs. These pages have metadata such as name, extension type (JSP or XHTML), navigation (forward or redirect), HTTP parameters that can be reported in the request, if the page is public or restricted, etc.

In DeltaSpike, these metadata are represented as Java interfaces, which allow multiple inheritance, which allows one or more pre-defined metadata are applied to more than one view SFJ. This feature will be better understood through the example of Listing 15, explained below.

As this list shows, we can see that two interfaces have been declared: the MinhaAplicacao interface, which in addition to extending the ViewConfig DeltaSpike interface, is also annotated with @View, setting the navigation metadata through a redirect; and SecurityPage interface that receives @Secured annotation, allowing apply security to folders and pages.

As the SecurityPage interface extends the MyAplication interface, it also automatically receives, via inheritance, the definition of navigation. Thus, all secure pages do not need to set this information again.

Also in Listing 15, we find two classes: Index and PaginaSeguraImpl. Both are identified by DeltaSpike during the application deploy as implement, even indirectly, the ViewConfig interface. Thus, the DeltaSpike expect to find the /index.xhtml pages and /postMessage.xhtml, otherwise an exception is thrown.

Look again in Listing 15, the class name matches the page name, unless the @View annotation (line 16) is used to change the name, or even the extension. Also note that the Index class implements the interface MyAplication (line 5).

This navigation of the Index page will be through redirection. Already SecurityPagempl class implements the interface SecurityPage (line 17), so that in addition to the navigation also be via redirection, this page will make the security check because it was set to @Secured annotation (on line 8).

Listing 15. Example ViewConfig.

  1  @Folder(name = "/")
  2  public class Pages {
  3
  4     @View(navigation = NavigationMode.REDIRECT)
  5     public interface MyAplication extends ViewConfig {
  6     }
  7 
  8     @Secured(Decididor.class)
  9     public interface SecurityPage extends MyAplication {
  10    }
  11
  12    // without @View annotation, use the class name
  13    public class Index implements MyAplication {
  14    };
  15 
  16    @View(name = "postMessage")
  17    public class SecurityPagempl implements PageSecurity {
  18    };
  19 }

Once the JSF views were configured using @View annotation, you can perform navigation in two ways, as presented in Listing 16. The myAction1() method, the implementation returns the class (line 8) defined on line 13 of Listing 15. In the myAction2() method, the ViewNavigationHandler class was used to define the navigation at the end of the implementation of this method (line 12).

Listing 16. Example of using ViewConfig for navigation.

  1  @Model
  2  public class MyBean implements Serializable {
  3
  4      @Inject
  5      private ViewNavigationHandler vnh;
  6    
  7      public Class<Index> myAction1() {
  8         return Index.class;
  9      }
  10
  11     public void myAction2() {
  12         vnh.navigateTo(SecurityPagempl .class);
  13     }
  14 }

Listening events JSF via CDI @Observes

The concept of events in JSF is something that exists since its first specification.

Today, even in the JSF 2.2 specification, you must reference the class that will hear the event at the faces-config.xml file or tag . The DeltaSpike allows events like BeforeJsfRequest, AfterJsfRequest, BeforePhase, AfterPhase, PostConstructApplicationEvent, PreDestroyApplicationEvent and ExceptionQueuedEvent be observed by the CDI.

In this way, code as shown in Listing 17 can be written without the need to implement the interface PhaseListener JSF and register it in the faces-config.xml.

Listing 17. Events JSF being observed by the CDI.

  1 @ApplicationScoped
  2 public class MyListeners {
  3    public void watch (@Observes PostConstructApplicationEvent event){
  4        //....
  5    }
  6 }

Avoiding double submitting form

Generally we want HTML forms are not submitted in duplicate when you accidentally double-click the button.

To prevent a double (or more) click (s) in a commandButton cause the form to be processed multiple times, DeltaSpike provides the . To use it, simply declare the http://deltaspike.apache.org/jsf namespace in the JSF page and then declare it within the , as shown in Listing 18 code.

Listing 18. Preventing double form submission.

  1 <html xmlns="http://www.w3.org/1999/xhtml"
  2      xmlns:h="http://java.sun.com/jsf/html"
  3      xmlns:ds="http://deltaspike.apache.org/jsf">
  4   . . .
  5        <h:form>
  6            . . .
  7            <ds:preventDoubleSubmit/>
  8        </h:form>
  9   . . . 
  10 </html>

Injection Converters and Validators JSF

One of the most anticipated features of JSF 2.2 is the injection of beans IDUs in Converters and Validators JSF. However, this feature did not enter the 2.2 version of the specification, so that the dependency injection in Converters and Validators is not yet available.

With DeltaSpike, on the other hand, the injection of both Converters CDI beans as for Validators it is possible and automatic, that is, no code or additional configuration is not required.

The Security Module

As the name implies, this module is responsible for providing functionality to DeltaSpike related to security. The installation is made by adding Maven dependencies in the pom.xml (as exposed to the previous modules) and SecurityInterceptor return within the beans.xml (see Listing 19).

Listing 19. Declaration of SecurityInterceptor in beans.xml file.

  1 <beans>
  2    <interceptors>
  3        <class>org.apache.deltaspike.security.impl.extension.SecurityInterceptor</class>
  4    </interceptors>
  5 </beans>

Applying security in method invocations

This functionality DeltaSpike lets you create annotations that will be used to intercept method invocations and then verify that the implementation is allowed.

As an example, let's create the @ApenasAdmin annotation - along the lines 1-5 of Listing 20 - which, as the name implies, allow only users who are in the Admin group can execute the methods. To tell DeltaSpike this annotation adds security (via interceptor) methods, it must have the @SecurityBindingType annotation (line 4).

Then you only need to declare a method (in any class) that contains the InvocationContext type as a parameter and returns a Boolean value (lines 10-15). If the returned value is false, the method execution is denied and an exception of AccessDeniedException type will be launched.

This method that performs the logic should also receive the @Secures annotation (line 10) and the annotation you just created (line 11). Note that you can use other Beans CDI as a parameter of this method. An example of this can be seen in Authorizing class in Listing 20, where the Bean CDI LoggedUser (line 13) is passed to the method.

Once created the annotation, set the method and access logic, just write down the methods of application with the newly created annotation, as startAdministrativeTask () method (lines 21 to 25) of AdminBean class also declared in Listing 20.

Listing 20. Using the Security-Binding.

  1  @Retention(value = RetentionPolicy.RUNTIME)
  2  @Target({ ElementType.TYPE, ElementType.METHOD })
  3  @Documented
  4  @SecurityBindingType
  5  public @interface OnlyAdmin {}
  6
  7  @ApplicationScoped
  8  public class  Authorizer{
  9
  10     @Secures
  11     @AdminOnly
  12     public boolean checks(InvocationContext invocationContext, 
  13                                             LoggedUser usr) throws Exception {
  14         return usr.getGrupo().equalsIgnoreCase("Admin");
  15     }
  16 }
  17 
  18 @Model
  19 public class AdminBean {
  20
  21     @OnlyAdmin
  22     public void startAdministrativeTask () {
  23         // The Authorizer#  method checks will be invoked before
  24         // to decide whether this method can be performed
  25     }
  26 }

The @Secured annotation is a simplification of @SecurityBindingType note that we have seen, it allows you to write directly the methods in which to apply security and specify both the class that contains the logic.

This annotation is usually used to make security JSF views as shown in the topic on type-safe view-config JSF module, and also to enable integration with other security frameworks such as JBoss PicketLink.

Listing 21 shows the modified AdminBean class to use @Secured annotation. Note that @Secured specifies the AdminDecisionVoter.class value. This class implements the AbstractAccessDecisionVoter abstract class, provided by DeltaSpike, so simply implement the checkPermission() method to check whether or not security breaches according to your need.

Listing 21. Using the annotation @Secured

  1  @Model
  2  public class AdminBean {
  3
  4      @Secured(AdminDecisionVoter.class)
  5      public void iniciarTarefaAdministrativa() {
  6          // The class is used AdminDecisionVoter.class
  7          // to decide whether this method can be performed
  8      }
  9  }
  10 
  11 public class AdminDecisionVoter extends AbstractAccessDecisionVoter {
  12
  13   @Override
  14    protected void checkPermission(AccessDecisionVoterContext ctx, 
  15                                         Set<SecurityViolation> violations){
  16         // checks for violations
  17         violations.add(newSecurityViolation("Access not allowed"));
  18     }
  19 }

The Data Module

Data module focuses on the persistence layer, bringing the user a more productive experience with the JPA. This is possible through the implementation of the Repository pattern, which as well as the DAO pattern, centralizes access logic, as well as queries related to specific entities. In addition, this module provides the ability to perform the audit of JPA entities. Because the Data module works directly with the JPA, it is mandatory that the EntityManager is available as a Bean CDI. For this, we need to expose it to the application via a CDI @Produces. Listing 22 shows an example of code that complements your installation. Listing 22. Exposing the EntityManager via @Produces.
  1  public class EntityManagerProducer{
  2
  3      @PersistenceUnit
  4      private EntityManagerFactory emf;
  5 
  6      @Produces 
  7      public EntityManager create(){
  8          return emf.createEntityManager();
  9      }
  10
  11     public void close(@Disposes EntityManager em){
  12         if (em.isOpen()){
  13             em.close();
  14        }
  15     }
  16 }

Repositories

The default repository project is defined as a mediator between the application and data repository (DAO, EntityManager, etc.).

Its main role is to act as a research translator, but there are no restrictions to the repository also perform operations such as insertion and removal of data. The Links section contains the address of an excellent article on this standard.

By adopting the DeltaSpike the default repository can be implemented easily, because we only need to create an interface that extends the generic interface EntityRepository inform the type of entity and the type of the primary key (line 2) as a generic type, and annotate this interface @Repository (see Listing 23). Then, at runtime, the DeltaSpike inject a proxy created by him to perform the operations.

In addition to the query operations, the EntityRepository interface defines a number of common operations like save, delete, search by primary key, etc.

These operations are always available so that the code used for creating repositories impressed by the low number of lines. Listing 24 shows the most important methods of EntityRepository interface.

Listing 23. Example repository.

  1  @Repository
  2  public interface RepositoryUsers extends EntityRepository<Usuario, Long> {
  3
  4      @Query("SELECT u FROM User AS u WHERE u.name='?1' ")
  5      public List<User> findByName(String name);
  6
  7      // The very method name creates SQL
  8      public User findByNameAndPassword(String name, char[] password);
  9    
  10 }

Listing 24. Methods of EntityRepository interface.

1  public interface EntityRepository<E, PK extends Serializable> {
  2 
  3      E save(E entity);
  4      void remove(E entity);
  5      void refresh(E entity);
  6      void flush();
  7      E findBy(PK primaryKey);
  8      List<E> findAll();
  9      List<E> findBy(E example, SingularAttribute<E, ?>... attributes);
  10     List<E> findByLike(E example, SingularAttribute<E, ?>... attributes);
  11     Long count();
  12     Long count(E example, SingularAttribute<E, ?>... attributes);
  13     Long countLike(E example, SingularAttribute<E, ?>... attributes);
  14 }

In line 4 of Listing 23 we see that the @query annotation was used to inform what the JPQL that will run the EntityManager when findByName() method is invoked. In the line 8 this annotation was not used because, by default, DeltaSpike uses the method signature to mount the JPQL clause.

These methods that automatically create the JPQL based on their names must return an entity or a list of entities and have their name starting with findBy followed by the name of the entity's property that is managed by the repository.

It is also possible to use operators such as "AND" and "OR", and comparators as "Equal", "Like", "IsNull" the method name. In the case of findByNameAndPassword() method (line 8 of Listing 23), the JPQL created will be: "SELECT u FROM User u WHERE u.name = ': name' AND u.password = ':password'".

Audit entities

Many applications implement in different ways mechanisms of audit entities. DeltaSpike, in turn, allows a simple entity auditing is enabled to register when the entity was created, the date it was last modified and who modified. (The audit of DeltaSpike does not have the functionality to store a history of changes made to the entity. For this type of functionality Hibernate Envers is recommended.)

To enable auditing, simply inform the listener DeltaSpike (org.apache.deltaspike.data.impl.audit.AuditEntityListener) in @EntityListeners annotation (line 2 of Listing 25).

Once this is done, your organization must have properties to store the date/time of creation, modification and who changed it, with their @CreatedOn annotations, @ModifiedOn and @ModifiedBy.

For the DeltaSpike identifies the user who made the modification, it is necessary for the application there is a method annotated with the qualifier @CurrentUser and @Produces and return the user ID in the form of string, as the line 26 of Listing 25.

Listing 25. Auditing an entity.

  1  @Entity
  2  @EntityListeners(AuditEntityListener.class)
  3  public class EntityExample {
  4  
  5      // other entity properties
  6  
  7      @Temporal(TemporalType.TIMESTAMP)
  8      @CreatedOn
  9      private Date created;
  10
  11     @Temporal(TemporalType.TIMESTAMP)
  12     @ModifiedOn
  13     private Date modified;
  14
  15     @ModifiedBy
  16     private String whoModified;
  17
  18     // getters e setters
  19 }
  20 
  21 public class UserProvider {
  22
  23    @Inject
  24    private User user;
  25
  26    @Produces @CurrentUser
  27    public String currentUser() {
  28        return user.getUsername();
  29    }
  30
  31 }

JPA module

The installation of the JPA module is made by adding the Maven dependencies in the pom.xml file and TransactionalInterceptor statement in beans.xml file (according to Listing 26). As the Data module, this module also works directly with the JPA. Therefore, it is mandatory that the EntityManager is exposed to the application through a CDI producer, as already shown in Listing 22.

Listing 26. Declaring TransactionalInterceptor in beans.xml file.

  1 <beans>
  2     <interceptors>
  3        <class>org.apache.deltaspike.jpa.impl.transaction.TransactionalInterceptor</class>
  4    </interceptors>
  5 </beans>

To allow CDI beans have a transactional context as EJBs, this module provides the @Transactional annotation, allowing the use of transactional contexts CDI beans that are not EJBs.

Although the specification Java EE 7 also bring the annotation @javax.transaction.Transactional the DeltaSpike through annotation

@org.apache.deltaspike.jpa.api.transaction.Transactional, enables the same behavior in Java EE 6 environments, as well as Java EE environment 7, but with the advantage of being integrated with a new scope defined by this module the @TransactionScoped.

The @TransactionScoped scope of the context is automatically started at the same time the transaction is initiated by @Transactional annotation DeltaSpike and finalized at the time the transaction is completed (through commit, rollback or timeout).

The Scheduler module

One of the projects most used for Java job scheduling is the Quartz. However, quartz is not integrated with CDI, so that jobs can not receive the injection beans dependencies through @Inject annotation.

Thinking about it, the DeltaSpike provides integration between CDI and Quartz that enables any Bean become a job, behaving these jobs receive dependency injection via @Inject annotation. In addition, these jobs are easily booked through @Scheduled annotation.

The @Scheduled annotation (see line 1 of Listing 27) lets you set the schedule using a CRON expression (see BOX 1) and further define the Job is automatically scheduled in application deployment through OnStartup parameter.

BOX 1. CRON Expressions

CRON expressions are common in Linux environments and is used to define administrative routines with the application 'cron'. This application has this name because it is derived from the word chronos. The CRON expressions are formed by six or seven fields that indicate respectively: seconds (0-59), minutes (0-59), hours (0-23), day of the month (1-31), month (1-12), day (1-7) and year (optional).

In addition to numeric values, the following wildcards can be used:

'*' - Means all the values;

'-' - Used to specify ranges. Example: 10-12 in the time field means that the job will run at 10, 11 and 12 hours;

',' - Specifies additional values. Example: 2,4,6 on the day of the week field means that the job will run Mondays, Tuesdays and Wednesdays;

'/' - It is used to set increments. Example: 0/15 in the 2nd field means that the job will run at 0, 15, 30 and 45 seconds;

'?' - It means that there is a specific value.

Thus, the expression "0 0/1 * * * ?" Means that the Job will run to zero seconds of one minute, at all hours, days, months, and no matter what day of the week.

Listing 27. Example of CDI bean that is also a Job Quartz.

  1 @Scheduled(cronExpression = "0 0/1 * * * ?", onStartup = false)
  2 public class MyJob implements org.quartz.Job {
  3
  4     // The Job allows injection CDI
  5     @Inject
  6     private AdminService service;
  7    
  8     @Override
  9     public void execute(JobExecutionContext context) throws JobExecutionException {
  10        service.executeAdministrativeRoutines();
  11    }
  12 }

If the OnStartup parameter is false, you must register the Job manually (see line 8 of Listing 28), just to inject this class Scheduler . This class also provides pause, resume, stop and consult Jobs.

Listing 28. Manually Registering the Job.

  1 @Model
  2 public class AdminBean {
  3
  4    @Inject
  5    private Scheduler<Job> jobScheduler;
  6
  7    public void startAdministrativeTask() {
  8        jobScheduler.registerNewJob(CdiAwareQuartzJob.class);
  9    }
  10
  11 }

The Bean Validation module

To the Bean Validation specification 1.0 Java EE 6 was not possible to beans injection CDI or EJBs within the classes that perform the validation.

How's functionality is already possible in the Bean Validation 1.1 of Java EE 7, the purpose of this module is to enable this feature in Java EE 6 environments, since the possibility of dependency injection in classes that perform the validation is very useful, allowing for example, reuse business rules already in service classes or EJBs.

To install this module, the only requirement needed, and configure the dependencies in pom.xml file, you have within the META-INF/validation.xml the definition of ConstraintValidatorFactory the DeltaSpike, as shown in Listing 29.

Listing 29. META-INF/validation.xml file - enabling the bean-validation module in Java EE 6.

 
  1 <validation-config xmlns="http://jboss.org/xml/ns/javax/validation/configuration"
  2   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3   xsi:schemaLocation="http://jboss.org/xml/ns/javax/validation/configuration">
  4     <constraint-validator-factory>
  5         org.apache.deltaspike.beanvalidation.impl.CDIAwareConstraintValidatorFactory
  6     </constraint-validator-factory>
  7 </validation-config>

The Servlet modules, Partial-Bean, Container Control and Test Control

Some DeltaSpike modules bring smaller features and no less important. For example, with the Servlet module, you can have access to HttpSession objects, HttpServletRequest and HttpServletResponse within CDI beans and also listen to events of the life cycle through the CDI @Observes.

But the Partial-Bean module allows you to create proxy classes that replace interfaces (or abstract classes). In turn, the Container Control module enables independent implementation that is used (Weld, OpenWebBeans, etc.), CDI containers and servlet containers like JBoss Undertow, Apache Tomcat and Jetty are initialized and finalized.

Finally, we can mention the Test Control module, which integrates with JUnit allowing injection CDI beans in test classes and also setting the stage of the project (ProjectStage) and controlling IDUs contexts assets.

Thus, the tests in beans CDI integrated to DeltaSpike can be tested easily and with little configuration. Listing 30 shows a JUnit test example by @TestControl annotation, determines which settings will be initialized and what will be the stage used project.

Listing 30. Test Example Test using the Control.

  1  @RunWith(CdiTestRunner.class)
  2  @TestControl(startScopes = SessionScoped.class)
  3  public class MyTestt{
  4     
  5     @Inject
  6      private MyBean myBean;
  7
  8      @Test
  9      @TestControl(projectStage = ProjectStage.Development.class)
  10     public void developmentTest(){
  11          // test implementation 
  12     }
  13
  14 }

As we have seen, the DeltaSpike is not a framework, but rather a set of CDI extensions that bring many features that are not available in the specification. Obviously these features should be used according to need and demand. And for this, one must have knowledge of what this project can offer.

In addition, it is known that some companies should take some time to migrate your servers to Java EE 7. DeltaSpike enables some features of Java EE 7, among many others, to run in the Java EE 6 servers so that a future upgrade is performed gradually.

We can not fail to mention that the DeltaSpike is, in itself, highly extensible, so that the features presented in this article can be customized to meet a specific need. Because it is an open source project, the reader is encouraged to contribute ideas and new extensions implementations, as well as patches and documentation.

On the website of the project you can find all the detailed documentation of these features, instructions to subscribe to the mailing lists and how to get the sources and carry out the project build.

Links

DeltaSpike Apache project.

http://deltaspike.apache.org/

Download DeltaSpike binaries.

http://deltaspike.apache.org/download.html

Specification of JSR 299 (CDI 1.0).

https://jcp.org/en/jsr/detail?id=299

Winners of the Duke's Choice Award in 2014.

https://blogs.oracle.com/java/entry/2014_duke_s_choice_award

Repository Design Pattern.

http://www.javabuilding.com/academy/patterns/repository.html

Quartz project site.

http://quartz-scheduler.org/

JBoss Undertow –

http://undertow.io/



Fabrí­cio Galdino is a software expert and has worked with IT analysis and business development for more than five years. It has extensive experience with testing, back and front-end technologies.

What did you think of this post?
Services
[Close]
To have full access to this post (or download the associated files) you must have MrBool Credits.

  See the prices for this post in Mr.Bool Credits System below:

Individually – in this case the price for this post is US$ 0,00 (Buy it now)
in this case you will buy only this video by paying the full price with no discount.

Package of 10 credits - in this case the price for this post is US$ 0,00
This subscription is ideal if you want to download few videos. In this plan you will receive a discount of 50% in each video. Subscribe for this package!

Package of 50 credits – in this case the price for this post is US$ 0,00
This subscription is ideal if you want to download several videos. In this plan you will receive a discount of 83% in each video. Subscribe for this package!


> More info about MrBool Credits
[Close]
You must be logged to download.

Click here to login