Defaults in Java EE 7 (Tech Tip #37) - No Fluff Just Stuff

Defaults in Java EE 7 (Tech Tip #37)

Posted by: Arun Gupta on July 10, 2014

Java EE 7 platform added a few new specifications to the platform:

  • Java API for WebSocket 1.0
  • Batch Applications for Java 1.0
  • Java API for JSON Processing 1.0
  • Concurrency Utilities for Java EE 1.0

This is highlighted in the pancake diagram shown below:

javaee7-pancake

Several of the existing specifications were updated to fill the gaps and provide a more cohesive platform. Some small, but rather significant additions, were made to the platform to provide defaults for different features. These defaults would lower the bar for application developers to build Java EE applications.

Lets take a look at them.

  • Default CDI: Java EE 6 required “beans.xml” in an archive to enable CDI. This was mostly a marker file. So you could bundle a completely empty “beans.xml” in the archive and that would enable injection. Of course, you could specify a lot of other elements in this file such as interceptors, decorators, alternative but the basic dependency injection was enabled by just the mere inclusion of this file.This was one of the biggest source of confusion of why beans were not getting injected in a Java EE 7 archive, and was asked on several forums and other channels.

    Java EE 7 made that “beans.xml” optional and provided a default behavior. Now if this file is not bundled, all CDI-scoped beans are available for injection. So any bean with an explicitly specified scope is available for injection. Scopes defined by the CDI specification are listed at docs.oracle.com/javaee/7/api/javax/enterprise/context/package-summary.html. Specifically, here are the scopes defined by CDI:

    • @ApplicationScoped
    • @ConversationScoped
    • @Dependent
    • @NormalScope
    • @RequestScoped
    • @SessionScoped

    In addition, two new scopes are introduced in Java EE 7:

    • @FlowScoped
    • @TransactionScoped

    So, any bean with these scopes will be available for injection, in other beans only, without the presence of “beans.xml”.

    Check it out in action at github.com/javaee-samples/javaee7-samples/tree/master/cdi/nobeans-xml.

  • Default data source: A Java EE runtime, a.k.a application server, requires to package a database with it. If you are building a Java EE application, you likely will need some sort of data store or RBDMS to store the data. So this makes perfect sense.For example, WildFly bundles in-memory H2 database.Now, you can certainly use another JDBC-compliant database but bundling a database makes it convenient to start with. However, in order to get started, Java EE 6 still required to create JDBC resources in an application server-specific way. This would mean understanding app server-specific tools.

    Java EE 7 simplified it by providing a default data source with a pre-defined JNDI name.This mean you can inject a data source as:

    @Resource
    DataSource ds;

    Also, your persistence.xml can look like:

    <?xml version="1.0" encoding="UTF-8"?>
    <persistence
      version="2.1"
      xmlns="http://xmlns.jcp.org/xml/ns/persistence"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence 
       http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
     <persistence-unit name="myPU" transaction-type="JTA"/>
    </persistence>

    Note, no <jta-data-source>.

    In both of these circumstances, a default data source with JNDI name java:comp/DefaultDataSource is bound to your application-server specific JDBC resource.

    The exact data source in WildFly can be verified using jboss-cli script as:

    wildfly-8.1.0.Final> ./bin/jboss-cli.sh --connect --command="/subsystem=datasources:read-resource"
    {
        "outcome" => "success",
        "result" => {
            "data-source" => {"ExampleDS" => undefined},
            "jdbc-driver" => {"h2" => undefined},
            "xa-data-source" => undefined
        }
    }

    Check it out in action at github.com/javaee-samples/javaee7-samples/tree/master/jpa/default-datasource.

  • Create JMS connection factory, queues, and topics: An application using JMS topics and queues in Java EE 6 would require a deployment script to create Connection Factory and Queues/Topics. These would again be done in an application server-specific way.Java EE 7 provide annotations @JMSConnectionFactoryDefinition and @JMSConnectionFactoryDefinitions that are read by the Java EE 7 runtime and ensures that the ConnectionFactory specified by these annotations is provisioned in the operational environment.

    Similarly, @JMSDestinationDefinition and @JMSDestinationDefinitions can be used to create Topics/Queues as part of application deployment.So no more deployment scripts, just include annotation in your code ?

    Check it out in action at github.com/javaee-samples/javaee7-samples/tree/master/jms/send-receive.

  • Default JMS connection factory: Just like default data source, a default JMS resource allows you to avoid creating a JMSConnectionFactory in an appserver-specific way to deploy the application using JMS resources.Injection of a JMS Producer or Consumer in Java EE 6 required to get an instance of application-managed or container-managed JMSConnectionFactory. This factory had to be manually created in an application-server specific way.Providing a default JMSConnectionFactory simplifies this step further.

    JMS 2.0 also introduced JMSContext as entry point to the simplified API, and it can be injected simply as:

    @Inject
    JMSContext context;

    Not specifying a ConnectionFactory means the default one will be used. And it has the JNDI name of jms/DefaultJMSConnectionFactory.

    The JNDI name may be mapped to the appserver-specific JMS provider. For example, in case of WildFly it is defined as:

    ./bin/jboss-cli.sh -c --command="/subsystem=messaging/hornetq-server=default/pooled-connection-factory=hornetq-ra:read-resource"
    {
        "outcome" => "success",
        "result" => {
            "auto-group" => false,
            "block-on-acknowledge" => false,
            "block-on-durable-send" => true,
            "block-on-non-durable-send" => false,
            "cache-large-message-client" => false,
            "call-failover-timeout" => -1L,
            "call-timeout" => 30000L,
            "client-failure-check-period" => 30000L,
            "client-id" => undefined,
            "compress-large-messages" => false,
            "confirmation-window-size" => -1,
            "connection-load-balancing-policy-class-name" => "org.hornetq.api.core.client.loadbalance.RoundRobinConnectionLoadBalancingPolicy",
            "connection-ttl" => 60000L,
            "connector" => {"in-vm" => undefined},
            "consumer-max-rate" => -1,
            "consumer-window-size" => 1048576,
            "discovery-group-name" => undefined,
            "discovery-initial-wait-timeout" => undefined,
            "dups-ok-batch-size" => 1048576,
            "entries" => [
                "java:/JmsXA",
                "java:jboss/DefaultJMSConnectionFactory"
            ],
            "failover-on-initial-connection" => false,
            "failover-on-server-shutdown" => undefined,
            "group-id" => undefined,
            "ha" => false,
            "initial-connect-attempts" => 1,
            "initial-message-packet-size" => 1500,
            "jndi-params" => undefined,
            "max-pool-size" => -1,
            "max-retry-interval" => 2000L,
            "min-large-message-size" => 102400,
            "min-pool-size" => -1,
            "password" => undefined,
            "pre-acknowledge" => false,
            "producer-max-rate" => -1,
            "producer-window-size" => 65536,
            "reconnect-attempts" => -1,
            "retry-interval" => 2000L,
            "retry-interval-multiplier" => 1.0,
            "scheduled-thread-pool-max-size" => 5,
            "setup-attempts" => undefined,
            "setup-interval" => undefined,
            "thread-pool-max-size" => 30,
            "transaction" => "xa",
            "transaction-batch-size" => 1048576,
            "use-auto-recovery" => true,
            "use-global-pools" => true,
            "use-jndi" => undefined,
            "use-local-tx" => undefined,
            "user" => undefined
        }
    }

    Check it out in action at github.com/javaee-samples/javaee7-samples/tree/master/jms/send-receive.

  • Default executors: Concurrency Utilities for Java EE introduced four different managed objects:
    • ManagedExecutorService
    • ScheduledManagedExecutorService
    • ContextService
    • ManagedThreadFactory

    These objects allow user to create application threads that are managed by the Java EE server runtime. Once again, a default and pre-configured managed object, with a well-defined JNDI name, is made available for each one of them.

    This allows a user to inject a ManagedExecutorService as:

    @Resource
    ManagedExecutorService myExecutor;

    instead of:

    @Resource(lookup="myExecutorJNDI")
    ManagedExecutorService myExecutor;

    Default ManagedExecutorService in WildFly can be found as:

    ./bin/jboss-cli.sh -c --command="/subsystem=ee/managed-executor-service=default:read-resource"
    {
        "outcome" => "success",
        "result" => {
            "context-service" => "default",
            "core-threads" => 5,
            "hung-task-threshold" => 60000L,
            "jndi-name" => "java:jboss/ee/concurrency/executor/default",
            "keepalive-time" => 5000L,
            "long-running-tasks" => false,
            "max-threads" => 25,
            "queue-length" => 0,
            "reject-policy" => "ABORT",
            "thread-factory" => undefined
        }
    }

    Similarly other default managed objects can be found.

    Check out different executors in action at github.com/javaee-samples/javaee7-samples/tree/master/concurrency.

With so many simplifications, why would you not like to use Java EE 7 platform ?

And WildFly is a fantastic application server too :-)

Download WildFly now, and get started!

Arun Gupta

About Arun Gupta

Arun Gupta is Director of Developer Advocacy at Red Hat and focuses on JBoss Middleware. As a founding member of the Java EE team at Sun Microsystems, he spread the love for technology all around the world. At Oracle, he led a cross-functional team to drive the global launch of the Java EE 7 platform through strategy, planning, and execution of content, marketing campaigns, and program. He is a prolific blogger since 2005 and have authored 1500+ blogs on technology. Arun has extensive speaking experience in ~40 countries on myriad topics and is a JavaOne Rockstar. He also founded the Devoxx4Kids chapter in the USA and continues to promoting technology education amongst kids. An author of a best-selling book, an avid runner, a globe trotter, a Java Champion, JUG leader, he is easily accessible at @arungupta.

Why Attend the NFJS Tour?

  • » Cutting-Edge Technologies
  • » Agile Practices
  • » Peer Exchange

Current Topics:

  • Languages on the JVM: Scala, Groovy, Clojure
  • Enterprise Java
  • Core Java, Java 8
  • Agility
  • Testing: Geb, Spock, Easyb
  • REST
  • NoSQL: MongoDB, Cassandra
  • Hadoop
  • Spring 4
  • Cloud
  • Automation Tools: Gradle, Git, Jenkins, Sonar
  • HTML5, CSS3, AngularJS, jQuery, Usability
  • Mobile Apps - iPhone and Android
  • More...
Learn More »