1 the jndi enc and injection every ejb container that is deployed in an application server has its...

32
1 The JNDI ENC and Injection The JNDI ENC and Injection Every EJB container that is deployed in an application server has its own personal internal registry called the Enterprise Naming Context (ENC). This ENC is implemented by JNDI and is a sandbox where the EJB container can hold specific references to its environment. Think of it as the EJB container's personal address book, where it writes down addresses to various Java EE services that it wants to look up and use within its business logic.

Upload: deborah-johnson

Post on 11-Jan-2016

215 views

Category:

Documents


2 download

TRANSCRIPT

Page 1: 1 The JNDI ENC and Injection Every EJB container that is deployed in an application server has its own personal internal registry called the Enterprise

11

The JNDI ENC and InjectionThe JNDI ENC and Injection

Every EJB container that is deployed in an application server has its own personal internal registry called the Enterprise Naming Context (ENC).

This ENC is implemented by JNDI and is a sandbox where the EJB container can hold specific references to its environment.

Think of it as the EJB container's personal address book, where it writes down addresses to various Java EE services that it wants to look up and use within its business logic.

Page 2: 1 The JNDI ENC and Injection Every EJB container that is deployed in an application server has its own personal internal registry called the Enterprise

22

The JNDI ENCThe JNDI ENC The ENC has been around in the EJB specification since

the early 1.0 days. It began as a local JNDI namespace that was specific to an EJB container. Developers could define aliases to resources, EJBs, and environment entries in the JNDI ENC through EJB XML deployment descriptors.

These aliases could then be looked up directly in JNDI within business logic. In EJB 3.0, this mechanism was enhanced so that JNDI ENC references could be injected directly into the fields of a bean class.

Annotations are the primary mechanism for doing this, but XML deployment descriptor support is available for those who wish to use that abstraction.

Page 3: 1 The JNDI ENC and Injection Every EJB container that is deployed in an application server has its own personal internal registry called the Enterprise

33

What Can Be Registered in the JNDI ENC?What Can Be Registered in the JNDI ENC?

Many different items can be bound to the ENC: references to any EJB interface, a JMS queue or topic destination, JMS connection factories, data sources, any JCA resource, and even primitive values.

Java EE services such as javax.transaction.UserTransaction, javax.ejb.TimerService, and org.omg.CORBA.ORB are also available in the ENC.

Page 4: 1 The JNDI ENC and Injection Every EJB container that is deployed in an application server has its own personal internal registry called the Enterprise

44

How Is the JNDI ENC Populated?How Is the JNDI ENC Populated?

The ENC's JNDI namespace is populated in two separate ways: via XML or via annotations.

Any reference that you declare in XML to a service or resource automatically populates the JNDI ENC with the reference's name.

Any environment annotation that you use in your bean class also causes the ENC to be populated. Once an item is bound to the JNDI ENC of the EJB container, it can be referenced by a JNDI lookup.

Page 5: 1 The JNDI ENC and Injection Every EJB container that is deployed in an application server has its own personal internal registry called the Enterprise

55

XML PopulationXML Population To illustrate how XML population works, let's define a

reference to the stateless session bean we wrote in Lecture 11. Here we define a local interface reference to the ProcessPayment EJB for the TravelAgent EJB:<ejb-jar> <enterprise-beans> <session> <ejb-name>TravelAgentBean</ejb-name> <ejb-local-ref> <ejb-ref-name>ejb/ProcessPayment

</ejb-ref-name> <ejb-ref-type>Session</ejb-ref-type>

<local>com.titan.processpayment.ProcessPaymentLocal</local> <ejb-link>ProcessPaymentBean</ejb-link> </ejb-local-ref> </enterprise-beans></ejb-jar>

Page 6: 1 The JNDI ENC and Injection Every EJB container that is deployed in an application server has its own personal internal registry called the Enterprise

66

XML PopulationXML Population The <ejb-local-ref> element tells the EJB container that the

TravelAgentBean wants a reference to the ProcessPayment EJB.

A reference to this bean is registered in the TravelAgentBean's JNDI ENC under the name ejb/ProcessPayment.

This is defined by the <ejb-ref-name> element. Other referenceable things, like resources and JMS destinations, have similar XML elements such as <ejb-local-ref> to specify how and where the reference will be bound into their JNDI ENCs.

Each service type in Java EE has its own reference syntax.

Page 7: 1 The JNDI ENC and Injection Every EJB container that is deployed in an application server has its own personal internal registry called the Enterprise

77

Annotation PopulationAnnotation Population Each referenceable type also has a corresponding

annotation that can be used as an alternative to XML. If you specify these annotations on the bean class, they

will cause the JNDI ENC to be populated with the information defined in the annotation:import javax.annotation.EJB;

@Stateful

@EJB(name="ejb/ProcessPayment",

beanInterface=ProcessPaymentLocal.class,

beanName="ProcessPaymentBean")

public class TravelAgentBean implements TravelAgentRemote {

...

}

Page 8: 1 The JNDI ENC and Injection Every EJB container that is deployed in an application server has its own personal internal registry called the Enterprise

88

Annotation PopulationAnnotation Population

In this example, we are registering a reference to the ProcessPayment EJB under the ejb/ProcessPayment name.

Business logic running inside the TravelAgentBean is able to do JNDI lookups to find this reference.

Each environment annotation, such as @javax.annotation.EJB , has a name( ) attribute that specifies the JNDI ENC name to which you want the service reference to be bound.

Page 9: 1 The JNDI ENC and Injection Every EJB container that is deployed in an application server has its own personal internal registry called the Enterprise

99

How Are Things Referenced from the ENC?How Are Things Referenced from the ENC?

Anything registered in the JNDI ENC can be looked up by name under the java:comp/env context. The comp part of this name corresponds to component.

The JNDI name resolves to a different context depending on where you invoke the lookup. For example, if you invoke jndi.lookup("java:comp/env") within the TravelAgentBean, you will get that EJB container's ENC.

If you do the same within ProcessPaymentBean, you will get a different ENC registry specific to that bean. The application server knows what ENC is active when you perform the lookup.

@Stateful@EJB(name="ejb/ProcessPayment", beanInterface=ProcessPaymentLocal.class, beanName="ProcessPaymentBean")

Page 10: 1 The JNDI ENC and Injection Every EJB container that is deployed in an application server has its own personal internal registry called the Enterprise

1010

How Are Things Referenced from the ENC?How Are Things Referenced from the ENC?

public class TravelAgentBean implements TravelAgentRemote {

public TicketDO bookPassage(CreditCardDO card, double amount) {

ProcessPaymentLocal payment = null;

try {

javax.naming.InitialContext ctx = new InitialContext( );

payment = (ProcessPaymentLocal)

ctx.lookup("java:comp/env/ejb/ProcessPayment");

} catch (javax.naming.NamingException ne) {

throw new EJBException(ne);

}

payment.process(card, customer, amount);

...

}

Page 11: 1 The JNDI ENC and Injection Every EJB container that is deployed in an application server has its own personal internal registry called the Enterprise

1111

How Are Things Referenced from the ENC?How Are Things Referenced from the ENC?

In this example, the bookPassage( ) method from our TravelAgent EJB needs a reference to the ProcessPayment EJB so that it can bill the customer for the reservation.

A reference to the ProcessPayment EJB was created in the TravelAgent's ENC by annotating the bean class with the @EJB annotation.

The preceding code does a JNDI lookup to find this reference. While the ProcessPayment.process( ) method is invoked, the java:comp/env/ejb/ProcessPayment reference is no longer available because the ProcessPayment's ENC is active instead of the TravelAgent's ENC.

Page 12: 1 The JNDI ENC and Injection Every EJB container that is deployed in an application server has its own personal internal registry called the Enterprise

1212

Annotation injectionAnnotation injection Instead of an ENC lookup, the ProcessPayment EJB

reference can be injected directly into a member variable of the TravelAgent EJB. This injection can be done through environment annotations or an XML deployment descriptor fragment:@Statefulpublic class TravelAgentBean implements TravelAgentRemote { @EJB private ProcessPaymentLocal payment;

...}

By using the @javax.ejb.EJB annotation on the payment field of the TravelAgentBean class, the EJB container will automatically inject a reference to the ProcessPayment EJB directly into the payment field when the TravelAgent bean instance is created.

Page 13: 1 The JNDI ENC and Injection Every EJB container that is deployed in an application server has its own personal internal registry called the Enterprise

1313

Annotation injectionAnnotation injection Alternatively, if you do not like this form of injection, the

specification also supports injecting via a bean setter method:

@Stateful

public class TravelAgentBean implements TravelAgentRemote {

private ProcessPaymentLocal payment;

@EJB public void setProcessPayment(ProcessPaymentLocal payment) {

this.payment = payment;

}

Unlike the previous example, when the TravelAgentBean instance is allocated, the EJB container will instead invoke the setProcessPayment( ) method, passing in the EJB reference as a parameter.

Page 14: 1 The JNDI ENC and Injection Every EJB container that is deployed in an application server has its own personal internal registry called the Enterprise

1414

XML injectionXML injection

If you prefer not to use annotations to initialize the fields of your bean class, then the <injection-target> element is available to you in your ejb-jar.xml deployment descriptor:<ejb-jar> <enterprise-beans> <session> <ejb-name>TravelAgentBean</ejb-name> <ejb-local-ref> <ejb-ref-name>ProcessPayment</ejb-ref-name> <ejb-ref-type>Session</ejb-ref-type> <local>com.titan.processpayment.ProcessPaymentLocal</local> <ejb-link>ProcessPaymentBean</ejb-link> <injection-target> <injection-target-class> com.titan.travelagent.TravelAgentBean </injection-target-class> <injection-target-name>payment</injection-target-name> </injection-target> </ejb-ref> </enterprise-beans></ejb-jar>

Page 15: 1 The JNDI ENC and Injection Every EJB container that is deployed in an application server has its own personal internal registry called the Enterprise

1515

XML injectionXML injection

Each XML environment element such as <ejb-local-ref> can use <injection-target> to populate a field or call a setter method with the referenced item.

The <injection-target-class> element is the class where your field or method is declared.

This may seem unnecessarily verbose, but this becomes important when there are inheritance hierarchies.

Page 16: 1 The JNDI ENC and Injection Every EJB container that is deployed in an application server has its own personal internal registry called the Enterprise

1616

Injection and inheritanceInjection and inheritance It is possible for a bean class to be part of a class hierarchy.

If any fields or methods have injection annotations on them, they will still be populated, but certain injection rules are followed:public class BaseClass {

@Resource DataSource data;

@EJB(beanName="ProcessPaymentBean") public void setProcessPayment(ProcessPaymentLocal pp) { ... }}@Statelesspublic class MySessionBean extends BaseClass implements MySessionRemote {...}

Page 17: 1 The JNDI ENC and Injection Every EJB container that is deployed in an application server has its own personal internal registry called the Enterprise

1717

Injection and inheritanceInjection and inheritance

In this example, we have a stateless session bean class that inherits from a base class. All instances of MySessionBean would have the appropriate resource injected into the base class's data field as well as the setProcessPayment( ) method.

It is possible to change what is injected into the setProcessPayment( ) method by reimplementing and overriding it in the subclass:@Statelesspublic class MySessionBean extends BaseClass implements

MySessionRemote { @EJB(beanName="AcmeProcessPayment")

public void setProcessPayment(ProcessPaymentLocal pp) { ... }...}

Page 18: 1 The JNDI ENC and Injection Every EJB container that is deployed in an application server has its own personal internal registry called the Enterprise

1818

Injection and inheritanceInjection and inheritance The ProcessPaymentBean would no longer be injected into

the setProcessPayment( ) method. Instead, the new overridden reference, AcmeProcessPayment, would be injected. There is one exception to this rule.

If the setProcessPayment( ) method in the BaseClass was a private method rather than a protected or public method, then the base class would still be injected with the old reference:public class BaseClass {

@Resource DataSource data;

@EJB(beanName="ProcessPaymentBean") private void setProcessPayment(ProcessPaymentLocal pp) { ... }}

Page 19: 1 The JNDI ENC and Injection Every EJB container that is deployed in an application server has its own personal internal registry called the Enterprise

1919

Injection and inheritanceInjection and inheritance@Statelesspublic class MySessionBean extends BaseClass implements

MySessionRemote { @EJB(beanName="AcmeProcessPayment") public void setProcessPayment(ProcessPaymentLocal pp) { ... }...}

So, in the previous example, both setProcessPayment( ) methods would be invoked and set with a different ProcessPaymentLocal reference.

The BaseClass 's setProcessPayment( ) method would get a reference to the ProcessPaymentBean , and the setProcessPayment( ) method of MySessionBean would get AcmeProcessPayment.

Page 20: 1 The JNDI ENC and Injection Every EJB container that is deployed in an application server has its own personal internal registry called the Enterprise

2020

@[email protected]

The @javax.ejb.EJB annotation can be used on your bean class's setter methods, on member fields, or directly on the class itself:

package javax.ejb;

@Target({TYPE, METHOD, FIELD}) @Retention(RUNTIME)

public @interface EJB {

String name( ) default "";

Class beanInterface( ) default Object.class;

String beanName( ) default "";

String mappedName( ) default "";

}

Page 21: 1 The JNDI ENC and Injection Every EJB container that is deployed in an application server has its own personal internal registry called the Enterprise

2121

XML-based remote EJB referencesXML-based remote EJB references The <ejb-ref> element defines a reference to remote EJBs. It

contains the subelements <description> (optional), <ejb-ref-name> (required), <ejb-ref-type> (required), <remote> (required), <home> (optional), <ejb-link> (optional), and <mapped-name> (optional), as well as the element <injection-target> (optional) described in the first part of this chapter.

Here is a remote reference to the ProcessPayment EJB:<ejb-jar> <enterprise-beans> <session> <ejb-name>TravelAgentBean</ejb-name> <ejb-ref> <ejb-ref-name>ejb/ProcessPaymentRemote </ejb-ref-name> <ejb-ref-type>Session</ejb-ref-type>

<remote>com.titan.processpayment.ProcessPaymentRemote</remote> </ejb-ref> </enterprise-beans></ejb-jar>

Page 22: 1 The JNDI ENC and Injection Every EJB container that is deployed in an application server has its own personal internal registry called the Enterprise

2222

XML-based local EJB referencesXML-based local EJB references The <ejb-local-ref> element defines a reference to remote EJBs.

It contains the subelements <description> (optional), <ejb-ref-name> (required), <ejb-ref-type> (required), <local> (required), <local-home> (optional), <ejb-link> (optional), and <mapped-name> (optional), as well as the element <injection-target> (optional) described in the first part of this chapter. Here is a local reference to the ProcessPayment EJB:

<ejb-jar> <enterprise-beans> <session> <ejb-name>TravelAgentBean</ejb-name> <ejb-local-ref> <ejb-ref-name>ejb/ProcessPaymentRemote </ejb-ref-name> <ejb-ref-type>Session</ejb-ref-type>

<local>com.titan.processpayment.ProcessPaymentLocal</local> </ejb-local-ref> </enterprise-beans></ejb-jar>

Page 23: 1 The JNDI ENC and Injection Every EJB container that is deployed in an application server has its own personal internal registry called the Enterprise

2323

@javax.persistence.PersistenceUnit@javax.persistence.PersistenceUnit

The @javax.persistence.PersistenceUnit annotation can be used on your bean class's setter methods or member fields, or directly on the class itself:

package javax.persistence;

@Target({TYPE, METHOD, FIELD}) @Retention(RUNTIME)

public @interface PersistenceUnit {

String name( ) default "";

String unitName( ) default "";

}

Page 24: 1 The JNDI ENC and Injection Every EJB container that is deployed in an application server has its own personal internal registry called the Enterprise

2424

@javax.persistence.PersistenceContext@javax.persistence.PersistenceContext

The @javax.persistence.PersistenceContext annotation can be used on your bean class's setter methods or member fields, or directly on the class itself:

package javax.persistence;

public enum PersistenceContextType {

TRANSACTION,

EXTENDED

}

Page 25: 1 The JNDI ENC and Injection Every EJB container that is deployed in an application server has its own personal internal registry called the Enterprise

2525

@javax.persistence.PersistenceContext@javax.persistence.PersistenceContext

@Target({}) @Retention(RUNTIME)

public @interface PersistenceProperty {

String name( );

String value( );

}

@Target({TYPE, METHOD, FIELD}) @Retention(RUNTIME)

public @interface PersistenceContext {

String name( ) default "";

String unitName( ) default "";

PersistenceContextType type( ) default TRANSACTION;

PersistenceProperty[] properties( ) default {};

}

Page 26: 1 The JNDI ENC and Injection Every EJB container that is deployed in an application server has its own personal internal registry called the Enterprise

2626

@[email protected] The @javax.annotation.Resource annotation is used to

reference an external resource. It can be applied to your bean class's setter methods or member fields, or directly on the class itself.

This annotation is highly overloaded and overused in the Java EE specification in that in addition to external resources, it is also used to reference JMS message destinations, environment entries, EJBContext s, and Java EE core services.

For now, we'll focus solely on using this annotation to access external resources:

Page 27: 1 The JNDI ENC and Injection Every EJB container that is deployed in an application server has its own personal internal registry called the Enterprise

2727

@[email protected] javax.annotation;

@Target({TYPE, METHOD, FIELD}) @Retention(RUNTIME)

public @interface Resource {

public enum AuthenticationType {

CONTAINER,

APPLICATION

}

String name( ) default "";

Class type( ) default Object.class;

AuthenticationType authenticationType( ) default v

AuthenticationType.CONTAINER;

boolean shareable( ) default true;

String description( ) default "";

String mappedName( ) default "";

}

Page 28: 1 The JNDI ENC and Injection Every EJB container that is deployed in an application server has its own personal internal registry called the Enterprise

2828

Shareable resourcesShareable resources

When several enterprise beans in a transaction use the same resource, you will want to configure your EJB server to share that resource.

Sharing a resource means that each EJB will use the same connection to access the resource (e.g., database or JMS provider), a strategy that is more efficient than using separate resource connections.

In terms of a database, EJBs that are referencing the same database will probably want to use the same database connection during a transaction so that all CRUD operations return consistent results.

Page 29: 1 The JNDI ENC and Injection Every EJB container that is deployed in an application server has its own personal internal registry called the Enterprise

2929

Shareable resourcesShareable resources EJB containers share resources by default, but

resource sharing can be turned on or off explicitly with the shareable( ) attribute of the @Resource annotation.

Occasionally, advanced developers may run into situations where resource sharing is not desirable, and having the option to turn off resource sharing is beneficial.

Unless you have a good reason for turning off resource sharing, we recommend that you set the shareable( ) attribute to true.

Page 30: 1 The JNDI ENC and Injection Every EJB container that is deployed in an application server has its own personal internal registry called the Enterprise

3030

XML-based resource referencesXML-based resource references The <resource-ref> element defines a reference to a given

resource. It contains the subelements <description> (optional), <res-ref-name> (required), <res-type> (required), <res-auth> (required), <res-sharing-scope> (optional), and <mapped-name> (optional), as well as the element <injection-target> (optional) described in the first section of this chapter. Here is an example of a reference to a data source of TitanDB:<ejb-jar> <enterprise-beans> <session> <ejb-name>TravelAgentBean</ejb-name> <resource-ref> <res-ref-name>jdbc/OracleDB</res-ref-name> <res-type>javax.sql.DataSource</res-type> <res-auth>Container</res-auth> <mapped-name>java:/DefaultDS</mapped-name> </resource-ref> </enterprise-beans></ejb-jar>

Page 31: 1 The JNDI ENC and Injection Every EJB container that is deployed in an application server has its own personal internal registry called the Enterprise

3131

Environment EntriesEnvironment Entries In Lecture 11, the ProcessPayment EJB had a configurable

property for minimum check number. These types of configurable properties are called environment entries . The bean can use environment entries to customize its behavior.

Although they can be defined using annotations, environment entries are almost always configured via XML, as they really are configuration values and not metadata.

The <env-entry> element is used to define them. This element contains the subelements <description> (optional), <env-entry-name> (required), <env-entry-type> (required), and <env-entry-value> (optional), as well as the element <injection-target> (optional). Here is a typical <env-entry> declaration:

Page 32: 1 The JNDI ENC and Injection Every EJB container that is deployed in an application server has its own personal internal registry called the Enterprise

3232

Environment EntriesEnvironment Entries

<ejb-jar>

<enterprise-beans>

<session>

<ejb-name>ProcessPaymentBean</ejb-name>

<env-entry>

<env-entry-name>minCheckNumber

</env-entry-name>

<env-entry-type>java.lang.Integer</env-entry-type>

<env-entry-value>2000</env-entry-value>

</env-entry>

</enterprise-beans>

</ejb-jar>