Hi David,
Mohammad and myself have been combing the spec and
discussing the testing that we should do for the Field Injection
tests.As per your advice we are attaching the points we got from the
spec in this mail. Mohammad please correct if I have missed anything
or am wrong somewhere. We plan to create test cases for the different
resources listed below. David can you check it for errors.
----------------------------------------------------------------------------------------------------------------------------------
Dependency Injection
Every possible type of JNDI entry can be injected via fields/annotations.
Fields that need to have values injected should not be static or final.
If a session bean makes use of dependency injection, the container
injects these references after the bean instance is created, and
before any business methods are invoked on the bean instance. If
dependency injection fails, the bean instance is discarded. The
Deployer can mark fields for Dependency injection by using deployment
descriptor elements as well as annotations. Always deployment
descriptor elements override the annotations.Container must throw
NameNotFoundException if any reference is not found. But what if we
try
to inject? We are assuming that no value will be injected and no
exception will be thrown.
Field Injection
In the case of variables
@Resource(name="myDB") //type is inferred from variable
public DataSource customerDB;
If the variable name is myDB then the variable is
@Resource //type and name are inferred from variable
public DataSource myDB;
@EJB //reference name and type inferred from variable
public AddressHome addressHome;
Setter Injection
@Resource(name="customerDB")
public void setDataSource(DataSource myDB) {
this.ds = myDB;
}
@Resource // reference name is inferred from the property name and
resource type //by parameter type
public void setCustomerDB(DataSource myDB) {
this.customerDB = myDB;
}
@Resource
public void setSessionContext(SessionContext ctx) {
this.ctx = ctx;
}
Types of references in JNDI
1) Simple environment entries.
For injecting simple environment entries use the annotation
@Resource int maxExemptions;
env-entry elements in the deployment descriptor.
The environment entry values may be one of the following Java
types: String, Character,Integer, Boolean, Double, Byte, Short, Long,
and Float.
Environment entries are scoped to a particular bean.
Page 412 of the core spec shows how to specify injection of
environment entries using the deployment descriptor. If
<env-entry-value> tag is not specified then the named resource is not
initialized in the naming context, and explicit lookups of the named
resource will fail.The container must only inject a value for the
environment entry if the application assembler or deployer has
specified a value to override the default value.
2) EJB References
a) EJB business interface
A client can obtain a session bean's business interface through
dependency injection or lookup in the JNDI namespace.For example, the
business interface Cart for the CartBean session bean may be obtained
using dependency injection as follows: @EJB Cart cart;
@EJB(
name="ejb/shopping-cart",
beanInterface=ShoppingCart.class,
beanName="cart1",
description="The shopping cart for this application"
)
private ShoppingCart myCart;
b) Home interface for EJB 2.1 Beans
For example, an EJB 3.0 client, com.acme.example.MySessionBean, might
obtain a reference to a bean's home interface as follows:
@EJB CartHome cartHome;
@EJB(
name="ejb/shopping-cart",
beanInterface=ShoppingCartHome.class,
beanName="cart1",
description="The shopping cart for this application"
)
private ShoppingCartHome myCartHome;
This home interface could be looked up in JNDI using the EJBContext
lookup method as shown in the following code segment:
@Resource SessionContext ctx;
...
CartHome cartHome =
(CartHome)ctx.lookup("com.acme.example.MySessionBean/cartHome");
If all the information is not given then it becomes the
deployer's responsibility to map the bean
3) Web Service References
WebService-Ref is the annotation,
a) JAX-RPC Web Service Clients
Dependency injection is not supported for these web
services.(Not sure abt this)
b) JAX-WS Web Service
WebService-Ref is the annotation and it can be used to declare a
service or a service endpoint
@WebServiceRef(name="java:comp/env/service/AddressBookService")
AddressBookService abf;
@WebServiceRef(name="java:comp/env/service/AddressBookService",
AddressBookService.class)
AddressBookPort port;
service-ref is deployment descriptor element
4) Resource Manager Connection Factory References
Can be declared using annotations and container will inject.
@Resource javax.sql.DataSource employeeAppDB;
4 types of connection factories need to be tested
a) JDBC
b) JMS
c) Mail
d) URL
Note that resource manager connection factory references
declared via annotations will not, by default, appear in any subcontext.
Resource injection into classes should also be tested.
@Resource(name="jdbc/EmployeeAppDB", type=javax.sql.DataSource)
@Stateless public class EmployeeServiceBean
implements EmployeeService {
@Resource SessionContext ctx;
public void changePhoneNumber(...) {
...
// use context lookup to obtain resource manager
// connection factory
javax.sql.DataSource ds = (javax.sql.DataSource)
ctx.lookup("jdbc/EmployeeAppDB");
// Invoke factory to obtain a connection. The security
// principal is not given, and therefore
// it will be configured by the Deployer.
java.sql.Connection con = ds.getConnection();
...
}
}
5) Resource Environment References
A field or a method of a bean may be annotated with the
Resource annotation to request injection of a resource environment
reference.
6) Message Destination References
Injection of a Message Destination Reference
@Resource javax.jms.Queue stockQueue;
The following example illustrates how an enterprise bean uses a
message destination reference to locate a JMS Destination.
@Resource(name="jms/StockQueue", type=javax.jms.Queue)
@Stateless public class StockServiceBean implements StockService {
@Resource SessionContext ctx;
public void processStockInfo(...) {
...
// Look up the JMS StockQueue in the environment.
Object result = ctx.lookup("jms/StockQueue");
// Convert the result to the proper type.
javax.jms.Queue queue = (javax.jms.Queue)result;
}
}
7) Persistence Unit References
The field or method should be annotated with a PersistenceUnit
Annotation.The name element specifies the name under which the entity
manager factory for the referenced persistence unit may be located in
the JNDI naming context. The optional unitName element specifies the
name of the persistence unit as declared in the persistence.xml file
that defines the persistence unit.
@PersistenceUnit
EntityManagerFactory emf;
@PersistenceUnit(unitName="InventoryManagement")
EntityManagerFactory inventoryEMF;
java:comp/env/persistence subcontext to be used
Obtaining entity manager for a persistence context
@PersistenceContext(name="persistence/InventoryAppMgr")
@Stateless
public class InventoryManagerBean implements InventoryManager {
@Resource SessionContext ctx;
public void updateInventory(...) {
...
// use context lookup to obtain container-managed entity
manager
EntityManager em =(EntityManager)
ctx.lookup("persistence/InventoryAppMgr");
...
}
}
persistence-context-ref used to declare the persistence context
references in the deployment descriptor.
8) UserTransaction Interface
Only Session and Message Driven beans with BMT can access the
UserTransaction interface available at java:comp/UserTransaction.
@Resource UserTransaction tx;
...
public void updateData(...)
...
// Start a transaction.
tx.begin();
...
// Perform transactional operations on data
...
// Commit the transaction.
tx.commit();
...
}
9) ORB References
java:comp/ORB
@Resource ORB orb;
public void method(...) {
...
// Get the POA to use when creating object references.
POA rootPOA = (POA)orb.resolve_initial_references("RootPOA");
...
}
An ORB reference may also be declared in a deployment
descriptor in the same way as a resource manager connection factory
reference. Such a deployment descriptor entry may be used to specify
injection of an ORB object.The application may set the shareable element
of the Resource annotation to false, or may set the res-sharing-scope
element in the deployment descriptor to Unshareable, to request a
non-shared ORB instance.
10) TimerService References
The Timer Service is accessed via dependency injection(Resource
annotation), through the getTimerService method of the EJBContext
interface, or through lookup in the JNDI
namespace(java:comp/TimerService).
11) EJBContext References
Are made available through dependency injection(using the
Resource Annotaton) or in JNDI (under the name
java:comp/EJBContext).An EJBContext object reference may also be
declared in a deployment descriptor in the same way as a resource
environment reference.Such a deployment descriptor entry may be used
to specify injection of an EJBContext object.EJBContext objects accessed
through the naming environment are only valid within the bean
instance that
performed the lookup. Lookup should give SessionContext for session
beans and MessageDrivenContext for MDBs
EJBContext.getEnvironment Method need not be supported and is
deprecated. Runtime exception or subclass of it should be thrown
@Resource SessionContext ctx;
...
Cart cart = (Cart)ctx.lookup(cart);
This should be irrespective of whether the interface is local or remote.
Can be in another EJB or in a standalone clientIf a dependency on the
SessionContext is declared, or if the bean class implements the
optional SessionBean interface (see Section 4.3.5), the SessionContext
is also injected at this time. In the case of the SessionContext being
acquired through dependency injection,the Resource annotation (or
resource-env-ref deployment descriptor element) is used to denote the
bean's dependency on the SessionContext. The SessionContext should be
injected first before anything else.
Notes
1) In the JNDI namespace,every lookup should return a new object other
than for shared objects like ORB,singletons or immutable objects
2) Fields that need to have values injected should not be static or final
3) JNDI name format -->
java:comp/env/com.acme.example.MySessionBean/myDatabase. -->
java:comp/env/package.Class/Field. The @Resource annotation also allows the
JNDI name to be specified explicitly.
4) Setter Injection for properties
setMyDatabase -> java:comp/env/com.example.MySessionBean/myDatabase.
5) When Deployment descriptor is used specify both JNDI name and property name
You can specify non default names to inject.
6) Each resource can be injected into a single field or method only
either the field or method can request the injection of a non default
named resource.By explicitly specifying the JNDI name of a resource, a
single resource may be injected into multiple fields or methods of
multiple classes.
7) Not visible/Hidden fields in the superclass (eg private fields) may
request injection as well. Also overridden methods will follow
whatever is given in that method.
8) The container needs to prompt the Deployer of any unresolved EJB
references, and allow him or her to resolve an EJB reference by
binding it to a specified compatible target bean.
We need to create test cases for each type of resource with both
annotations and dd based injection as well as overrides.
----------------------------------------------------------------------------------------------------------------------------------
P.S. In all the test cases we test injection of only public fields but
the spec only says that we cannot inject into static and final fields.
David can you clarify why only public fields can be injected.
Thanks
Manu
On 11/16/06, Manu George <[EMAIL PROTECTED]> wrote:
Hi David and Mohammad,
I will be happy to take this up and collaborate
with Mohammad and anyone else interested. I will take up the public
field injection tests first
[OPENEJB-161] iTest: StatelessBeanPublicFieldInjectionTests
[OPENEJB-187] iTest: StatefulBeanPublicFieldInjectionTests
Will start combing through the spec :-) for related info
Thanks
Manu
On 11/16/06, Mohammad Nour El-Din <[EMAIL PROTECTED]> wrote:
> Hi David...
>
> The mail is not directed to me :), but I really want to join into these
> tests specially the ones which their container code is not implemented yet
> so I can write the test case and go through its related container code too
> :), so I would like to have these ones:
>
> [OPENEJB-160] iTest: StatelessBeanSetterInjectionTests
> [OPENEJB-186] iTest: StatefulBeanSetterInjectionTests
>
> On 11/15/06, David Blevins <[EMAIL PROTECTED]> wrote:
>
> > On Nov 9, 2006, at 6:10 AM, Manu George wrote:
> >
> > > Hi David,
> > > That explains it. The Pojo name in some of the test
> > > cases. I was wondering what it was. I have attached the patches for
> > > 152 and 156.
> >
> > Ok, I've got 152 and 156 applied and checked in. Thank you very much
> > for those!
> >
> > > Please assign some others to me namely 154 and 155.
> >
> > I see you already have these completed and patches in for those --
> > you work fast. I'll get those in for you today too.
> >
> > Thanks Manu! You're really cruising these tests. Any interest in
> > working on one of these?
> >
> > [OPENEJB-160] iTest: StatelessBeanSetterInjectionTests
> > [OPENEJB-161] iTest: StatelessBeanPublicFieldInjectionTests
> > [OPENEJB-162] iTest: StatelessBeanCallbackTests
> > [OPENEJB-186] iTest: StatefulBeanSetterInjectionTests
> > [OPENEJB-187] iTest: StatefulBeanPublicFieldInjectionTests
> > [OPENEJB-188] iTest: StatefulBeanCallbackTests
> >
> > Not as easy as the other ones as there's no pre-existing test to copy/
> > paste from. But I get the feeling you may be up to the challenge.
> > The corresponding setter injection code in the container has not been
> > written, so these tests will not pass but they will be a very big
> > help in completing that functionality.
> >
> > Thoughts?
> >
> > -David
> >
> >
>
>
> --
> Thanks
> - Mohammad Nour
>
>