4 Storing the Data Transactionally

In this chapter, we will run the iteration for the first time and store the entities transactionally in the database. To enable us to do this, we must first configure the data source. After running the iteration, we’ll then encounter a couple more “unexpected” minor issues. As with the configuration of the data source, we’ll tackle these in a step-by-step manner.

We can use the project from the last chapter. If you have already closed it, you can start another temporary session by clicking the following link. Don’t forget that the whole work is volatile unless you sign up to Codenvy and persist the project in your own workspace.

Start Cloud IDE

My-Campaign after embedding EntityManager in Services

4.1 Configuring the Data Source

JPA requires its own XML configuration file. The data source to be used and the parameters for accessing it are set in this file. The configuration file for our sample application can be found in Listing 4-1. Please save it in the folder src\main\resources\META-INF under the name persistence.xml. If the META-INF folder does not exist, create it (case-sensitive!).

<?xml version="1.0" encoding="UTF-8"?>
<persistence 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"
        version="2.1">
    <persistence-unit name="primary">
        <jta-data-source>java:jboss/datasources/MyCampaignDS</jta-data-source>
        <properties>
            <property name="hibernate.hbm2ddl.auto" value="update"/>
            <property name="hibernate.show_sql" value="false"/>
        </properties>
    </persistence-unit>
</persistence>

Listing 4-1 Configuration file persistence.xml

As well as setting the usual XML header (including XML schema referencing), we’ll set the following configuration parameters within the file:

  • The JNDI name of the datasource, in our case java:jboss/datasources/MyCampaignDS
  • Setting of the Hibernate paramater show_sql to false – this causes the SQL generated by Hibernate not to be output on the console. For debugging purposes, the parameter can be set to true.
  • Setting of the Hibernate parameter hbm2ddl.auto to update

The last parameter in the list requires a more detailed explanation. The setting update causes the schema of our database to be updated automatically after deployment, enabling our entities to be persisted without errors. This is ideal for our test purposes, since it removes the need for SQL commands to build the database schema (e.g. CREATE TABLE….). It is a given that in a production environment, we will not want to execute database scripts automatically after deployment. It only makes sense to build an initial functioning database schema once the deployment of the first version is complete.

In later versions, we only have to set the hibernate.hbm2ddl.auto parameter to validate. In this case, Hibernate merely validates whether the database schema is suitable for storing entities. Any change in the entities requires the manual creation of an SQL script that modifies the database schema in such a way that the entities can be processed without errors. For example, a new column must be added to the table corresponding to the entity when the entity is modified with an attribute.

In contrast to the rest of the file, the Hibernate parameters defined with the <properties> tag do not belong to the JPA standard. In light of this, if we use another JPA implementation, the parameters will either not exist or will exist under a different name. Though JPA 2.1 does offer a parameter for generating a database schema (in the form of javax.persistence.schema-generation-action), it is not supported by the Hibernate version we are using, thus requiring us to use a Hibernate-specific parameter instead.

We have now reference the name of the data source (MyCampaignDS) in the configuration file, though we still need to actually create it. To accomplish this, we will first save the file from Listing 4-2 with the name mycampaign-ds.xml in the folder src\main\webapp\WEB-INF. As we do so, we must ensure that the folder does not contain any other configuration files with the suffix -ds.

<?xml version="1.0" encoding="UTF-8"?>
<datasources xmlns="http://www.jboss.org/ironjacamar/schema"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.jboss.org/ironjacamar/schema
            http://docs.jboss.org/ironjacamar/schema/datasources_1_0.xsd">

    <datasource jndi-name="java:jboss/datasources/MyCampaignDS"
            pool-name="mycampaign" enabled="true"
            use-java-context="true">
        <connection-url>jdbc:h2:file:~/data/mycampaign</connection-url>
        <driver>h2</driver>
        <security>
            <user-name>sa</user-name>
            <password>sa</password>
        </security>
    </datasource>
</datasources>

Listing 4-2 Configuration file mycampaign-ds.xml

This is a WildFly-specific file that does not belong to the Java EE standard and offers no opportunity to create a standardized definition for a data source; thus, the configuration of the data source will differ depending on which application server is used. As above, only a small section of the file is actually of interest. As well as noting the JNDI name of the data source, java:jboss/datasources/MyCampaignDS, which we set in the tag <datasource>, we should pay particular attention to the URL of our JDBC connection, which is defined in the tag <connection-url>. Let’s look a little closer at this URL: jdbc:h2:file:~/data/mycampaign We include the value h2 to specify that we are using the H2 database (http://www.h2database.com). This is a small embedded database that persists its data in a single file according to the data source and is therefore particularly well-suited for development purposes. We will specify ~/data/mycampaign as the file in our connection URL. Since H2 adds .h2.db as a suffix for the file name, the file will store the database in our home directory (whose synonym is the tilde, ~) in the file mycampaign.h2.db in the folder data. The database driver, username and password are also specified within the file mycampaign-ds.xml, in the tags <driver>, <user-name> and <password> respectively. Since we are using a H2 database the corresponding driver – in this case, h2 – is configured. We will set sa as a username and password.

4.2 Expanding Services with Transactions

Now we’ve finished configuring the database, we can finally run our iteration. After starting the application and adding a campaign, however, we get a strange exception: javax.persistence.TransactionRequiredException. This means that no transaction is available. Make sure that it is exactly this exception you are seeing. If a different exception appears, it is probable that you have made a typo at some point during the process. Likely places for this to have occurred would be the JPQL commands or the configuration files, neither of which are checked by the compiler. The exception appears for a good reason. To implement changes to a database in Java EE, we require a transaction. In a transaction, multiple database operations are encapsulated in one logical operation. This logical operation is either executed completely, or not at all. If, during a transaction, an operation cannot be carried out – perhaps because another database user has changed the same data set – then all changes carried out within our transaction will be rolled back. On the other hand, if everything functions correctly, then changes to the database will be committed. This concept often turns out to be indispensable. In our application, for example, it is important to know whether a Donation object is created properly when the use case Donate money is invoked. Data is only committed (and a message sent to the user informing them of their successful donation) if no errors appear. If errors do appear, all database changes belonging to the transaction are rolled back, an exception is raised and the user is informed. There are various methods for creating a transaction, which we’ll look at in more detail in the following chapter. In our application, we’ll opt for the most simple approach: converting our CDI bean into an EJB (Enterprise JavaBean) – or, more precisely, into an SSB (Stateless Session Bean). The SSB is very similar to a CDI bean with RequestScope in that it does not save any data within a user session. Unlike the CDI bean, however, the methods of an SSB are configured by default such that a new transaction is invoked when they are started and ended when they are ended. The operations associated with a transaction are therefore determined by the method scope. This transactional behaviour is highly useful to us, since it results in one transaction per service operation. Previously, when we did not have detailed knowledge of the term “transaction”, this would have corresponded to our intuitive understanding of a service. Though this explanation has been somewhat lengthy, the implementation is actually very simple. The annotation @RequestScoped in the bean CampaignServiceBean must be replaced by the annotation @Stateless from the package javax.ejb:

@Stateless
public class CampaignServiceBean implements CampaignService {
…

Rerun the application. You should now find that the issue of the missing transaction has been solved, and the application can now be used. But be aware that we have just implemented the persistence of campaigns. All use cases of the application that involve donations will still lead to errors. This will change after the next chapter.

By making this small change, we have changed a few things in the background: the lifecycle of the servce beans is now no longer managed by CDI, but by the EJB container. In the upcoming Cloud Tutorial EJB in a Day (available in march 2016), we’ll learn about other options – aside from transactions – that are opened up for services as a result of conversion to EJBs.

If you have other problems with your project, please compare it with the project behind the following link:

Start Cloud IDE

My-Campaign Persist Campaigns

Discussion

Use the message board below to give the authors your feedback or to discuss this page’s topic with other readers (in English please!). Please don’t expect the authors to answer directly, but they might update the content of this site according to your feedback.