Documentation

EJB 3.0

Deployment

Configuration

Commands

Feeds

 

Overview

In this example we use the @Resource annotation to inject a javax.sql.DataSource into our bean. The trickiest thing about injecting a DataSource is not declaring the annotation, but actually configuring the data source.

In OpenEJB the rules are quite simple. An declaration like the following in code:

@Resource DataSource customerDataSource;

Matches a data source declared as follows in the openejb.xml file:

<Resource type="DataSource" id="customerDataSource">
 ....
</Resource>

As seen in this example, the data source can also be declared via properties as follows:

customerDataSource = new://Resource?type=DataSource

This style of properties creation can be used in the InitialContext properties, set into the System properties, or passed in on the command line as vm properties.

The source for this example is in the "injection-of-datasource" directory located in the openejb-examples.zip available on the download page.

The Code

package org.superbiz.injection;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.ejb.Stateful;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.List;
import java.util.ArrayList;

@Stateful(name = "Movies")
public class MoviesImpl implements Movies {

    /**
     * The field name "movieDatabase" matches the DataSource we
     * configure in the TestCase via :
     * p.put("movieDatabase", "new://Resource?type=DataSource");
     *
     * This would also match an equivalent delcaration in an openejb.xml:
     * <Resource id="movieDatabase" type="DataSource"/>
     *
     * If you'd like the freedom to change the field name without
     * impact on your configuration you can set the "name" attribute
     * of the @Resource annotation to "movieDatabase" instead.
     */
    @Resource
    private DataSource movieDatabase;

    @PostConstruct
    private void construct() throws Exception {
        Connection connection = movieDatabase.getConnection();
        try {
            PreparedStatement stmt = connection.prepareStatement("CREATE TABLE movie ( director VARCHAR(255), title VARCHAR(255), year integer)");
            stmt.execute();
        } finally {
            connection.close();
        }
    }

    public void addMovie(Movie movie) throws Exception {
        Connection conn = movieDatabase.getConnection();
        try {
            PreparedStatement sql = conn.prepareStatement("INSERT into movie (director, title, year) values (?, ?, ?)");
            sql.setString(1, movie.getDirector());
            sql.setString(2, movie.getTitle());
            sql.setInt(3, movie.getYear());
            sql.execute();
        } finally {
            conn.close();
        }
    }

    public void deleteMovie(Movie movie) throws Exception {
        Connection conn = movieDatabase.getConnection();
        try {
            PreparedStatement sql = conn.prepareStatement("DELETE from movie where director = ? AND title = ? AND year = ?");
            sql.setString(1, movie.getDirector());
            sql.setString(2, movie.getTitle());
            sql.setInt(3, movie.getYear());
            sql.execute();
        } finally {
            conn.close();
        }
    }

    public List<Movie> getMovies() throws Exception {
        ArrayList<Movie> movies = new ArrayList<Movie>();
        Connection conn = movieDatabase.getConnection();
        try {
            PreparedStatement sql = conn.prepareStatement("SELECT director, title, year from movie");
            ResultSet set = sql.executeQuery();
            while ( set.next() ) {
                Movie movie = new Movie();
                movie.setDirector(set.getString("director"));
                movie.setTitle(set.getString("title"));
                movie.setYear(set.getInt("year"));
                movies.add( movie );
            }

        } finally {
            conn.close();
        }
        return movies;
    }

}

Writing a unit test for the example

public class MoviesTest extends TestCase {

    public void test() throws Exception {
        Properties p = new Properties();
        p.put(Context.INITIAL_CONTEXT_FACTORY, "org.apache.openejb.client.LocalInitialContextFactory");
        p.put("movieDatabase", "new://Resource?type=DataSource");
        p.put("movieDatabase.JdbcDriver", "org.hsqldb.jdbcDriver");
        p.put("movieDatabase.JdbcUrl", "jdbc:hsqldb:mem:moviedb");

        Context context = new InitialContext(p);

        Movies movies = (Movies) context.lookup("MoviesLocal");

        movies.addMovie(new Movie("Quentin Tarantino", "Reservoir Dogs", 1992));
        movies.addMovie(new Movie("Joel Coen", "Fargo", 1996));
        movies.addMovie(new Movie("Joel Coen", "The Big Lebowski", 1998));

        List<Movie> list = movies.getMovies();
        assertEquals("List.size()", 3, list.size());

        for (Movie movie : list) {
            movies.deleteMovie(movie);
        }

        assertEquals("Movies.getMovies()", 0, movies.getMovies().size());
    }
}

Note in the above test code the following lines:

p.put("movieDatabase", "new://Resource?type=DataSource");
p.put("movieDatabase.JdbcDriver", "org.hsqldb.jdbcDriver");
p.put("movieDatabase.JdbcUrl", "jdbc:hsqldb:mem:moviedb");

As mentioned these actually create and configure the data source. When OpenEJB boots up, these properties will get read and executed allowing you to keep all the configuration required to run your tests right in the test case itself. No need to keep dozens of openejb.xml config files in your projects or try and create one big configuration that might end up loading a lot of unneeded containers and resources.

In your production system you can place the properties into the OPENEJB_HOME/conf/system.properties file or add them to your OPENEJB_HOME/conf/openejb.xml with a declaration like so:

<Resource type="DataSource" id="movieDatabase">
 JdbcDriver = org.hsqldb.jdbcDriver
 JdbcUrl = jdbc:hsqldb:mem:moviedb
</Resource>

Running

Running the example is fairly simple. In the "injection-of-datasource" directory of the examples zip, just run:

$ mvn clean install

Which should create output like the following.

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running org.superbiz.injection.MoviesTest
Apache OpenEJB 3.0    build: 20080408-04:13
http://openejb.apache.org/
INFO - openejb.home = /Users/dblevins/work/openejb-3.0/examples/injection-of-datasource
INFO - openejb.base = /Users/dblevins/work/openejb-3.0/examples/injection-of-datasource
INFO - Configuring Service(id=Default Security Service, type=SecurityService, provider-id=Default Security Service)
INFO - Configuring Service(id=Default Transaction Manager, type=TransactionManager, provider-id=Default Transaction Manager)
INFO - Configuring Service(id=movieDatabase, type=Resource, provider-id=Default JDBC Database)
INFO - Configuring Service(id=Default JDK 1.3 ProxyFactory, type=ProxyFactory, provider-id=Default JDK 1.3 ProxyFactory)
INFO - Found EjbModule in classpath: /Users/dblevins/work/openejb-3.0/examples/injection-of-datasource/target/classes
INFO - Configuring app: /Users/dblevins/work/openejb-3.0/examples/injection-of-datasource/target/classes
INFO - Configuring Service(id=Default Stateful Container, type=Container, provider-id=Default Stateful Container)
INFO - Auto-creating a container for bean Movies: Container(type=STATEFUL, id=Default Stateful Container)
INFO - Auto-linking resource-ref 'org.superbiz.injection.MoviesImpl/movieDatabase' in bean Movies to Resource(id=movieDatabase)
INFO - Loaded Module: /Users/dblevins/work/openejb-3.0/examples/injection-of-datasource/target/classes
INFO - Assembling app: /Users/dblevins/work/openejb-3.0/examples/injection-of-datasource/target/classes
INFO - Jndi(name=MoviesLocal) --> Ejb(deployment-id=Movies)
INFO - Created Ejb(deployment-id=Movies, ejb-name=Movies, container=Default Stateful Container)
INFO - Deployed Application(path=/Users/dblevins/work/openejb-3.0/examples/injection-of-datasource/target/classes)
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.911 sec

Results :

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

   

Apache OpenEJB is an project of The Apache Software Foundation (ASF)
Site Powered by Atlassian Confluence .
[ edit ]