As noted in the Injection of env-entry Example , the EJB 3.0 supported env-entry types are fairly limited. Also the use of several tags in an ejb-jar.xml can get a bit verbose.

OpenEJB does not restrict you to just these data types or require you to use an ejb-jar.xml to declare them.

See Built-in Type Converters for a full list of supported env-entry types.

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

The Code

Bean Class

public class Stratocaster {

    @Resource(name = "pickups")
    private List<Pickup> pickups;

    @Resource(name = "style")
    private Style style;

    @Resource(name = "dateCreated")
    private Date dateCreated;

    @Resource(name = "guitarStringGuages")
    private Map<String, Float> guitarStringGuages;

    @Resource(name = "certificateOfAuthenticity")
    private File certificateOfAuthenticity;

    public Date getDateCreated() {
        return dateCreated;

     * Gets the guage of the electric guitar strings
     * used in this guitar.
     * @param string
     * @return
    public float getStringGuage(String string) {
        return guitarStringGuages.get(string);

    public List<Pickup> getPickups() {
        return pickups;

    public Style getStyle() {
        return style;

    public File getCertificateOfAuthenticity() {
        return certificateOfAuthenticity;

The META-INF/env-entries.properties file


The Custom Type and Editor

Support for java.lang.Enum types is already built-in, but we've decided we'd like to allow abbreviated versions of the enum constants to be usable. We do this by creating a custom PropertyEditor for our Pickup enum like so:

public class PickupEditor extends java.beans.PropertyEditorSupport {
    public void setAsText(String text) throws IllegalArgumentException {
        text = text.trim();

        if (text.equalsIgnoreCase("H")) setValue(Pickup.HUMBUCKER);
        else if (text.equalsIgnoreCase("S")) setValue(Pickup.SINGLE_COIL);
        else throw new IllegalStateException("H and S are the only supported Pickup aliases");

We cleverly install this PropertyEditor in a static block in the Pickup class that will be executed should someone actually reference the Pickup type.

public enum Pickup {


    // Here's the little magic where we register the PickupEditor
    // which knows how to create this object from a string.
    // You can add any of your own Property Editors in the same way.
    static {
        PropertyEditorManager.registerEditor(Pickup.class, PickupEditor.class);

Test Case

public class StratocasterTest extends TestCase {

    private Stratocaster strat;

    public void test() throws Exception {
        EJBContainer.createEJBContainer().getContext().bind("inject", this);

        Date date = DateFormat.getDateInstance(DateFormat.MEDIUM, Locale.US).parse("Mar 1, 1962");
        assertEquals("Strat.getDateCreated()", date, strat.getDateCreated());

        List<Pickup> pickups = asList(Pickup.SINGLE_COIL, Pickup.SINGLE_COIL, Pickup.SINGLE_COIL);
        assertEquals("Strat.getPickups()", pickups, strat.getPickups());

        assertEquals("Strat.getStyle()", Style.VINTAGE, strat.getStyle());

        assertEquals("Strat.getStringGuage(\"E1\")", 0.052F, strat.getStringGuage("E1"));
        assertEquals("Strat.getStringGuage(\"A\")", 0.042F, strat.getStringGuage("A"));
        assertEquals("Strat.getStringGuage(\"D\")", 0.030F, strat.getStringGuage("D"));
        assertEquals("Strat.getStringGuage(\"G\")", 0.017F, strat.getStringGuage("G"));
        assertEquals("Strat.getStringGuage(\"B\")", 0.013F, strat.getStringGuage("B"));
        assertEquals("Strat.getStringGuage(\"E\")", 0.010F, strat.getStringGuage("E"));

        File file = new File("/tmp/strat-certificate.txt");
        assertEquals("Strat.getCertificateOfAuthenticity()", file,strat.getCertificateOfAuthenticity());


Running it

Running the example is fairly simple. In the "custom-injection" 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.enventries.StratocasterTest
Apache OpenEJB 3.1-SNAPSHOT    build: 20080409-12:05
INFO - openejb.home = /Users/dblevins/work/openejb3/examples/custom-injection
INFO - openejb.base = /Users/dblevins/work/openejb3/examples/custom-injection
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=Default JDK 1.3 ProxyFactory, type=ProxyFactory, provider-id=Default JDK 1.3 ProxyFactory)
INFO - Found EjbModule in classpath: /Users/dblevins/work/openejb3/examples/custom-injection/target/classes
INFO - Configuring app: /Users/dblevins/work/openejb3/examples/custom-injection/target/classes
INFO - Configuring Service(id=Default Stateless Container, type=Container, provider-id=Default Stateless Container)
INFO - Auto-creating a container for bean StratocasterImpl: Container(type=STATELESS, id=Default Stateless Container)
INFO - Loaded Module: /Users/dblevins/work/openejb3/examples/custom-injection/target/classes
INFO - Assembling app: /Users/dblevins/work/openejb3/examples/custom-injection/target/classes
INFO - Jndi(name=StratocasterImplLocal) --> Ejb(deployment-id=StratocasterImpl)
INFO - Created Ejb(deployment-id=StratocasterImpl, ejb-name=StratocasterImpl, container=Default Stateless Container)
INFO - Deployed Application(path=/Users/dblevins/work/openejb3/examples/custom-injection/target/classes)
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.705 sec

Results :

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