DTU 
 

 

02162: Course on Software Engineering 2 (e14)

In this tutorial, you will learn how to store the data collected and manipulated via web services in a database, so that they are stored permanently. To this end, we will use the database Java DB (Derby), which is part of the JDK, and the default database technology of GlassFish.

 

In addition, we will use the Java Persistence API (JPA) with EclipseLink, which works smoothly together with the technologies that we are using for web services (see tutorials 1, 2, and 4).

 

Behind the scenes, there will be a mapping of the entities to a database, which is called an Object Relational Mapping (ORM). But, this does not need to concern us too much, because the mappings are automatially derived from the respective Java classes, supported by some JPA and EJB annotations. The details are explained below, while going through the different steps of the task.

 

Basically, you will implement the same web services of assignment 2 again, only that now the events reported by the addevent service are stored permanently. Since over the time the database will store extermely many events, you will need to add one other service, which returns the events of an sensor which are not older than a specified time period (in milliseconds).

 

Tasks

Below, the steps for the tasks of the firth assignment are explained:
  1. In order not to mix up the projects of this assignment with projects of earlier assignments, create another Dynamic Web Project (see tutorials 1, 2). You can reuse some code from the earlier tutorials though. When creating the Dynamic Web Project, don't forget to check the box for creating the web.xml file. After creating the Dynamic Web Project, set it up as a Jersey project (see assignment 2).

     

    In addition to that, you need to convert this project to a JPA project. You do this by right-clicking on the project and selecting "Configure->Convert to JPA Project...". In the "Project Facets" dialog, you do not need to change anything (make sure that the JPA facet is checked), and click "Next".

     

    In the "Configure JPA settings" dialog, choose EclipseLink as Platform and the GlassFish System Library as implementation. You can leave the "Connection" settings open, since we will add them later. Click on "Finish" to finish the conversion to a JPA project. After that step, your project should show a JPA folder with a persistence.xml file in it. This is the confiuration of the JPA project, but it is almost empty at this point.

     

    Next, set up the JPA configuration. To this end, you could basically copy the complete contents from the following persistence.xml file. The defined persistence-unit defines a name of a persistence unit, which we need to refer to later in the code. This can be freely chosen. The other elements, could remain unchanged — at least in the start. The property eclipselink.ddl-generation with value create-or-extend-tables says that upon starting the GlassFish server, the tables in the database for storing the entities of your application are created or extended according to the entity classes (and their annotations) of your project. You could also choose value drop-and-create-tables: this will delete existing tables (and you would not want that once your system is running with production data). The element jta-data-source indicates which database connection of the GlassFish server should be used for this persistence unit. By default, GlassFish is configured with a connection jdbc/__default, which we use for our project. The element exclude-unlisted-classes with value false says that JPA will look through all Java classes for definitions of entities (which are the classes which are persisted to the database).

     

  2. Before you can start this project, we need to create a service and data classes, which you can re-use from assignment 4, if you want (you will need to make some changes, though). The data classes will be uses as so-called data transfer objects (DTOs) now. Create separate packages for the service class and for the dto classes now.

     

    In addition to that, also create classes for the entities. In our case, there would be an entity for the Sensor and for the Event. In order not to confuse the DTO class with the entity class, call the entity EventEntity. As Java classes, DTO and entity classes will look very similar. Anyway it is a good idea to keep them separate, in order to keep the two different aspect persistence and data transfer to the clients completely independent of each other (you would also run into technical problems if you did not do that). Create these entity classes in a separate package.

     

    The most important part of these classes are the JPA annotations: first of all, these annotations indicate that these are entities, but also define how these classes are mapped to a relational database schema. You can find two examples here: Sensor.java, EventEntity.java. The concept of object relational mappings and the meaning of the annotations will be explained in the tutorial on Friday, October 3. You can also look them up at http://wiki.eclipse.org/Introduction_to_EclipseLink_JPA_(ELUG).

     

    Note that, by default, entities will be cashed, which might result in strange effects (data that you added to the database, is not shown); therefore, you can switch caching off for some entities with the @Cacheable(false) annotation. In the examples above, this is necessary for the Sensor.java, which will be explained in the tutorial session. Whenever in doubt, switch caching off (which might of course have a negative effect on the performance).

     

    At last, you also need to create a so-called data access object (DAO) or entity access object (EAO) that allows you to obtain the entity objects from the database at a defined point. For now, one such class would be enough. Create a new package and a entity access class in that package. Here are some snippets of how such a class typically looks like: SensorDataEAO.java.

     

    This examples shows two ways of accessing data. One by using the injected EntityManager without any SQL queries, which would be the standard way of accessing objects. Note that, even though there are no commands for transactions and for committing changes to the database, these modifications are handled in a transactional way. For more information on using the EntityManager, see http://wiki.eclipse.org/EclipseLink/Examples/JPA/EMAPI.

     

    The other uses SQL queries (with some JPA extensions) for more specific selections of entities. In the example below, this is a query for obtaining only the latest events for some sensor (for a given time period). Of course, we could obtain them by accessing the sensor, getting its list of all events, and then removing the outdated ones. This would, however, be terribly inefficient, getting the right events from the database with an appropriate SQL query is much faster and also uses much less memory.

     

    Anyway, you should also implement a method that returns all events registered for a sensor (as we had it in assignment 2). This should be implemented in the same style as the addEvent() method.

     

  3. Now that you have all the parts in place, you can re-implement the web services from assignment 2, plus one only returning the latest events for a sensor in a given period of time.

     

    This is done in the same way as in assignment 2. In order to use the methods of the SensorDataEAO, you need to add some additional annotations to it: The class of the web service implementation must have the annotations @LocalBean and @Stateless. In order to access the SensorDataEAO, you need to define an attribute declaration with an annotation as shown below:

      @EJB
      SensorDataEAO eao;
    Note that even tough you never initialize this attribute, it will be properly initiallized by the technology and you can use this attribute in all methods, to access the require entities.

     

    Since the SensorDataEAO implements most of the needed functionality already, implementing the web services should be easy now. But, you still need to convert the entities into data transfer objects. To this end, you need to implement some converters in a classical way. You can use these converters in a classical programming style. But, there are also means to inject these converters so that it is easier to replace the DTOs and this way decouple entities from the interfaces.

     

    You will find some more information on the DTOs and how to inject a converter here.

     

  4. Next, test your new web application by deploying it to your localhost (you will be able to debug it). Since you are using the database, you need to start this database first. To this end, go to the folder to which you installed GlassFish. In the toplevel folder of that installation, which is called glassfish4, go to folder bin and issue the command

     

      asadmin start-database

     

    Update (Oct. 10): Note that depending on your platform and the Java version you are using, you might need to set a permission so that the database can be opend on port 1527. You need to add a

     

      grant { permission java.net.SocketPermission "localhost:1527", "listen"; };

     

    to the respective java.policy file, which is located in the ...\lib\security folder of your Java installation (remember, that you might have different Java versions installed; find out which you are actually using with java -version and where java on the Windows platform). See here for more details.

     

    Then, start the GlassFish server as you know it from assignment 1. Test your web application by invoking the services with URLs from your browser.In particular, make sure that events are properly added and that the service for obtaining only the most recent events is working properly. The debugger might be a great help. If the data are not properly updated, you might have forgotten to prevent caching for some entities.

     

    In the end, you can stop the glassfish databaseby issuing the command

     

      asadmin start-database

     

    in the same folder of the glassfish installation as discussed above.

     

  5. You can also deploy your web application to the GlassFish server of your group (as discussed here). But, note that there is not database running on that server. So, you will need to configure the GlassFish server so that it uses the so-called Embedded Database (note that the data will be gone when the GlassFish sever for any reason should go down). In order to use GlassFish with the Embedded Database, open the administrator view of your GlassFish sever; in the "Common Tasks" list on the left, open the "Resources", "JDBC", and "JDBC Connection Pools". Then select "DerbyPool" and, in the open "Edit JDBC Connection Pool" on the right, change the "Datasource Classname" from "org.apache.derby.jdbc.ClientDataSource" to "org.apache.derby.jdbc.EmbeddedDataSource".

     

    Note again: The data in this database will be lost when the GlassFish server stops (crashes or whichever other reason).

     

    Update (Oct. 10): Each group has another GlassFish server available now on which a database is running already. These servers have the same passwords as the servers made available to your group earlier:

     

Useful links

Here are some links that might be helpful:

 

 

Ekkart Kindler (), October 2, 2014 (last updated October 10, 2014)