EJB 3.0 Dependency Injection

Aus SDQ-Wiki

Einleitung

Eine schöne Diskussion von Brian Repko zum Vergleich von EJB3 Dependency Injection und JNDI Lookup findet sich hier.

HowTo

Der folgende Beispiel-Code funktioniert mit JBoss 4.0.4GA [1] und nutzt die Dependency Injection unter EJB 3.0. Die Abhängigkeiten werden dabei per XML-Datei (ejb-jar.xml) gesteuert.

Übersicht

In diesem Kurz-Tutorial werden zwei Fälle behandelt:

  • Injection einer EJB (Session Bean) in eine andere
  • Injection von primitiven Datentypen in eine EJB

Voraussetzungen

Mithilfe der Dependency Injection können ausschließlich über JNDI gemanagte Ressourcen eingeimpft werden. Außerdem funktioniert die Dependency Injection nur in vom Container gemanagten Objekten, also z.B. in Session Beans, in Message Driven Beans oder Entities aber auch Servlets oder JSF Managed Beans. Einfache POJOs werden vom Container nicht gemanagt, deshalb funktioniert dort die Dependency Injection nicht. POJOs müssen die benötigten Ressourcen über den InitialContext und die Methode lookup() einbinden. Hier ist ein Beispiel wie das mit Glassfish und anderen von ihm abgeleiteten Application Servern funktioniert.

Injection einer EJB (Session Bean)

Szenario: BusinessLogicProxy möchte auf BusinessLogicCoordinator zugreifen. Die Abhängigkeiten soll jedoch nicht fest codiert werden.

Interface IBusinessLogic (Remote und Local Interface):

package de.uka.ipd.sdq.docSys.businessLogic;

import javax.ejb.Local;
import javax.ejb.Remote;
import de.uka.ipd.sdq.docSys.classInterfaces.IError;

@Remote // @Local und @Remote dürfen nicht zusammen verwendet werden!
public interface IBusinessLogic extends IBusinessLogicCoordinator {
	//TODO: define methods
}

Klasse BusinessLogicProxy (Stateless Session Bean):

package de.uka.ipd.sdq.docSys.businessLogic.impl;

import javax.annotation.EJB;
import javax.ejb.Stateless;

@Stateless
public class BusinessLogicProxy implements IBusinessLogic
{
	private IBusinessLogicCoordinator businessLogicCoordinator;
	
	/**
	 * Setter injection for the IBusinessLogicCoordinator object.
	 * The dependency is injected at this point.
	 * @param IBusinessLogicCoordinator Delegate
	 */
	@EJB(name="ejb/BusinessLogicCoordinator")
	public void setBusinessLogicCoordinator(IBusinessLogicCoordinator businessLogicCoordinator)
	{
		this.businessLogicCoordinator = businessLogicCoordinator;
	}

	//TODO: implement methods

	// Example; businessLogicCoordinator can be called:
	public void myMethod() {
		this.businessLogicCoordinator.doSomething();
	}
}

Interface IBusinessLogicCoordinator(Remote und Local Interface):

package de.uka.ipd.sdq.docSys.businessLogic;

import javax.ejb.Local;
import javax.ejb.Remote;

import de.uka.ipd.sdq.docSys.userManagement.IUserManagement;

@Remote // @Local und @Remote dürfen nicht zusammen verwendet werden!
public interface IBusinessLogicCoordinator extends ISearch, IDocumentManagement, IUserManagement {
	//TODO: define methods

	// Example:
	public void doSomething();
}

Klasse BusinessLogicCoordinator (Stateless Session Bean):

package de.uka.ipd.sdq.docSys.businessLogic.impl;

import java.util.Hashtable;

import javax.annotation.EJB;
import javax.ejb.Stateless;

import de.uka.ipd.sdq.docSys.businessLogic.IBusinessLogicCoordinator;

/**
 * TODO: Most method calls should be delegated. 
 *
 */
@Stateless
public class BusinessLogicCoordinator implements IBusinessLogicCoordinator {
	//TODO: implement methods

	// Example:
	public void doSomething() {
		//TODO: Method code
	}
}

Der XML-Code der /META-INF/ejb-jar.xml sieht daraufhin wie folgt aus:

<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar xmlns="http://java.sun.com/xml/ns/javaee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
	http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd" version="3.0">

	<enterprise-beans>
	<session>
		<ejb-name>BusinessLogicProxy</ejb-name>
		<ejb-ref>
			<!-- Injection target point: -->
			<ejb-ref-name>ejb/BusinessLogicCoordinator</ejb-ref-name>
			<!-- Type of target bean: entity oder session: -->
			<ejb-ref-type>Session</ejb-ref-type>
			<-- The remote interface: -->
			<remote>de.uka.ipd.sdq.docSys.businessLogic.IBusinessLogicCoordinator</remote>
			<!-- JNDI-Name of the bean to inject into the target: -->
			<ejb-link>BusinessLogicCoordinator</ejb-link>			
			<injection-target>
				<!-- The target class (where to inject): -->
				<injection-target-class>
					de.uka.ipd.sdq.docSys.businessLogic.impl.BusinessLogicProxy
				</injection-target-class>
				<!-- The target name in the target class (where to inject): -->
				<injection-target-name>businessLogicCoordinator</injection-target-name>
			</injection-target>
		</ejb-ref>
	</session>	
	</enterprise-beans>
</ejb-jar>

Injection von primitiven Datentypen

Eine Klasse, in die ein primitiver Daten-Typ (hier ein String) injected werden soll:

package com.full.namespace;

import javax.annotation.Resource;
import javax.ejb.Stateful;

@Stateful
public SomeClass {
	
	/**
	 * Injection target for primitive data type (String here).
	 * Identified by the default JNDI-Name ("classesArray").
	 */
	@Resource
	private String classesArray;

	[..]
}

Dazu notwendiger Code in der ejb-jar.xml:

<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar xmlns="http://java.sun.com/xml/ns/javaee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
	http://java.sun.com/xml/ns/javaee/ejb-jar_3_0.xsd" version="3.0">

	<enterprise-beans>
		<session>
			<ejb-name>SomeClass</ejb-name>
			<ejb-class>com.full.namespace.SomeClass</ejb-class>
			<env-entry>
				<env-entry-name>classesArray</env-entry-name>
				<env-entry-type>java.lang.String</env-entry-type>
				<env-entry-value>This is the string value to inject.</env-entry-value>
				<injection-target>
					<injection-target-class>
						com.full.namespace.SomeClass
					</injection-target-class>
					<injection-target-name>classesArray</injection-target-name>
				</injection-target>
			</env-entry>
		</session>
	</enterprise-beans>
</ejb-jar>

Siehe auch

Referenzierung von EJBs aus POJOS