Download Session Beans and EAR Deployments

Document related concepts
no text concepts found
Transcript
Enterprise
Java
EJB: Session Beans
v131013
EJB: Session Beans
1
Needs and JavaSE/EE Implementation
Options
v131013
EJB: Session Beans
Enterprise
Java
2
Goals
Enterprise
Java
• Be able to deploy business logic to the EJB tier
– hosted by the container
•
•
•
•
•
•
resource management
threading
security
transactions
remote interfaces
async capabilities
– accessed by other local business logic and local web tier
– accessed by remote clients
v131013
EJB: Session Beans
3
Objectives
Enterprise
Java
• Rationale
• Stateless Session Bean
– Stateless
– Stateful
– Singleton
• Enterprise Archives (EARs)
• Example Session Bean
• Interface Design Issues
– Lazy Load
– Pure POJOs
– DTO Classes
v131013
EJB: Session Beans
4
Overview
Enterprise
Java
• Entity Beans
– model business data in system
• Session Beans
– model interactions between other beans
– Taskflow
• Enterprise Archive (EAR)
– Deployment artifact with a specific structure containing
•
•
•
•
v131013
EJB component(s)
WAR component(s)
Utility jar(s)
…
EJB: Session Beans
5
Associated Design Patterns
Enterprise
Java
• Session Façade (covered in Business Logic)
• Remote Façade
• Data Transfer Objects
v131013
EJB: Session Beans
6
Remote Facade
Enterprise
Java
• Forces
– core service layer (business logic and its business
objects) contains fine grain methods and objects
– a significant number of fine-grain remote calls will not
work
• Solution
– add a Remote Facade
• a course-grain facade over a service layer
• contains no business logic; it calls it
• translates course-grain methods and objects into fine-grain
method calls and objects to/from service layer
• bulk accessors wrap fine-grain access methods
– service layer does not have a remote interface
• fine grain business objects used might not be Serializable
v131013
EJB: Session Beans
7
Enterprise
Java
Remote Facade Encapsulates Local Objects
v131013
EJB: Session Beans
8
Enterprise
Java
Remote Facade Encapsulates Local Logic
v131013
EJB: Session Beans
9
DTO Pattern
Enterprise
Java
• Context
– Business Objects represent too much information or
behavior to transfer to remote client
• Problem
–
–
–
–
Client may get information they don't need
Client may get information they can't handle
Client may get information they are not authorized to use
Client may get too much information/behavior to be
useful (e.g., entire database serialized to client)
• Forces
– Some clients are local and can share object references
with business logic
– Handling specifics of remote clients outside of core
scope of business logic
v131013
EJB: Session Beans
10
DTO/Remote Facade Solution
Enterprise
Java
• Layer a Remote Facade over Business Logic
• Remote Facade constructs Data Transfer Objects
(DTOs) from Business Objects that are appropriate for
remote client view
• Remote Facade uses DTOs to construct or locate
Business Objects to communicate with Business Logic
v131013
EJB: Session Beans
11
DTO Pattern Roles
Enterprise
Java
• Data Transfer Object
– represent a subset of the state of the application at a point
in time
– not dependent on Business Objects or server-side
technologies
• doing so would require sending Business Objects to client
• XML and Web services provide the “ultimate isolation” in
DTO implementation
• Remote Facade
– uses Business Logic to perform core business logic
– layered on to of Business Logic to translate between
Business Objects and DTOs
• Business Logic
– continues to perform core duties as described in DAO
v131013Pattern
EJB: Session Beans
12
DTO Pattern Consequences
•
•
•
•
Enterprise
Java
Clients only get what they need
Clients only get what they understand
Clients only get what they are authorized to use
Remote and Local interfaces to services are different
– makes it harder to provide location transparency
• Lightweight Business Objects can be used as DTOs
– Remote Facade must make sure they are “pruned” of
excess related items before transferring to client
– Remote Facade must make sure they are “cleaned” of
DAO persistence classes before transferring to client
v131013
EJB: Session Beans
13
Use Cases and Session Beans
Enterprise
Java
• Session Bean per Use Case too fine grain
– CreateAccountEJB
– DepositEJB
– WithdrawEJB
– TransferEJB
• Group cohesive Use Cases into a larger-grain Session
Bean
– TellerEJB
• createAccount(), deposit(), withdraw(), transfer()
v131013
EJB: Session Beans
14
Use of Session versus Entity Beans
Enterprise
Java
• Session Beans
– implementation of a task
– interaction between other beans
– direct database access
• bulk operations
– examples
• TaxDistrict.calcTax(double cost)
• Teller.transfer(long fromAccount, long toAccount,
double amount)
• Registrar.listStudents(String course)
v131013
EJB: Session Beans
15
Enterprise
Java
Use of Session versus Entity Beans (cont.)
• Entity Beans
– represent shared data in the database
– provide a type-safe, complete view of shared
information
– interacts with data generally at the individual
object/row level
– examples
• Account, Student
• Account.setOwner(String taxId), Account.getOwner()
• Account.withdraw(double amount),
Account.deposit(double amount)
v131013
EJB: Session Beans
16
Stateless Session Bean
Enterprise
Java
• maintains no conversational state
– each method is ignorant of what went before it and
what will happen after it
• maintains implementation state
– sharable between separate client invocations
• a set of procedures or batch commands that take in a
set of parameters and return a result
v131013
EJB: Session Beans
17
Stateful Session Bean
Enterprise
Java
• maintains conversational state
– object can cache values between calls
• ex. iterator
– idle timeout period or client command ends lifetime
• maintains implementation state
– not sharable between separate clients/objects
• all resources are allocated to perform the work of one
Stateful Session bean instance. That instance is tied to
the state of the client
• able to react to transaction states
– ex. Publish error message on transaction rollback
v131013
EJB: Session Beans
18
Singleton Session Bean
Enterprise
Java
• Stateful session bean with only one instance shared
across all clients
• Good for tracking transient state in-memory
v131013
EJB: Session Beans
19
Stateless/Stateful/Singleton
Enterprise
Java
• Stateless
– can contain cached implementations
•
•
•
•
JDBC DataSources
JMS Publishers
cached EAI state
all non-visible to calling client
• Stateful
– may contain all of the above and add client
conversational state
• Singleton
– May contain all of the above except client conversation
state would be shared across clients
• e.g., getNextTask()
v131013
EJB: Session Beans
20
Stateless/Stateful/Singleton
Enterprise
Java
• Stateless
– Cheapest to implement, deploy, scale
• Stateful
– should only be used within the scope of a single
HttpRequest
– should not be used at HttpSession Scope
• multiple threads would access same instance
• Singleton
– Newest bean type
– More overhead than stateless because of concurrency
management
– Extremely efficient when managing in-memory state
v131013
EJB: Session Beans
21
Stateless Session Bean Lifecycle
v131013
EJB: Session Beans
Enterprise
Java
22
Stateful Session Bean Lifecycle
v131013
EJB: Session Beans
Enterprise
Java
23
Singleton Session Bean Lifecycle
v131013
EJB: Session Beans
Enterprise
Java
24
JavaEE EARs
Enterprise
Java
• Used for compound deployments
– Multiple EJBs
– Multiple WARs
– EJB + WAR
• Optional with new JavaEE 6 “flexible deployment”
and the first and last case above
– WAR
• EJB(s)
v131013
EJB: Session Beans
25
Class Loaders
Enterprise
Java
Parent Class Loader
Child Class Loader
Child Class Loader
• Arranged in a parent/child relationship
• Requests for a class are first delegated to the parent
class loader
• May access classes/resources loaded by local and
parent class loader
• Do not have access to classes/resources loaded by
sibling class loaders
v131013
EJB: Session Beans
26
Separate EJB/WAR Deployment
Enterprise
Java
Application Server Class Loader
EJB App
Class Loader
Web App
Class Loader
Web App
Class Loader
• Classes loaded by EJB Application Class Loader not seen
by Web Application
• Shared implementations must be placed in both
applications
– WEB-INF/lib
– causes difficulty when passing object between applications
that have loaded the same class
v131013
EJB: Session Beans
27
J2EE Enterprise
Application Deployment
Enterprise
Java
Application Server Class Loader
EAR Class Loader
EJB interfaces and dependent
classes identified by EJB manifests
loaded by EAR’s classloader
EJB App Class Loader
Web App 2 Class Loader
Web App 1 Class Loader
v131013
EAR Class Loader
All EJBs are loaded by a single class loader
•may also include web dependent classes identified
through manifest entries to promote singleton loading
of classes across web applications
Servlets/JSPs and lib.jars
loaded by isolated classloaders
EJB: Session Beans
28
Enterprise
Java
Enterprise Application Archive (EAR)
EAR
•
WAR
WAR
WAR
EJB
EJB
EJB
•
•
Utility
Utility
Classes
Utility
Classes
Classes
Client
Client
App
Client
App
App
•
Resource
Resource
Adapter
Resource
Adapter
Adapter
•
WAR(s)
– directory or archive
EJB(s)
– directory or archive
Client JAR(s)
– client applications
Utility Classes(s)
– directory or archive
– supplies external source utility
classes
– referenced through MANIFESTs
Resource Adapters(s)
– custom resource drivers
META-INF/application.xml
v131013
EJB: Session Beans
29
Directory and Archive Forms
Enterprise
Java
• Exploded Directory Form
– ability to modify static files (html/jsp) without
redeploying
– separate server serves up content in exploded form
– simpler build environment
• consistent with build environment of free versions of
IDEs (Forte, JBuilder, etc.)
• Archive File Format
– easy form of distribution
v131013
EJB: Session Beans
30
Enterprise
Java
application.xml
application
icon
small-icon
display-name
description?
large-icon
web-uri
security-role*
description?
ejb|connector|java|web
v131013
module+
alt-dd
role-name
context-root
EJB: Session Beans
31
Key Element Definitions
Enterprise
Java
• Modules
– ejb – EJBs (Ex. EJB1.jar)
– web – web applications
– java - client applications
– connector – JCA resource adapters
• Web applications
– web-uri (ex. webapp1.war)
– context-root
• Name of web app’s context
• May be empty if only one webapp in the application
v131013
EJB: Session Beans
32
application.xml Example
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE application PUBLIC
"-//Sun Microsystems, Inc.//DTD J2EE Application 1.3//EN"
"http://java.sun.com/dtd/application_1_3.dtd">
<application>
<display-name>ejbsessionBankEAR</display-name>
<description>Example Session Bean Bank Application</description>
<module>
<web>
<web-uri>ejbsessionBankWAR.war</web-uri>
<context-root>/ejbsessionBankWAR</context-root>
</web>
</module>
<module>
<ejb>ejbsessionBankEJB-1.0.2007.2-SNAPSHOT.jar</ejb>
</module>
v131013
EJB: Session Beans
Enterprise
Java
33
Example: Core Implementation
Enterprise
Java
ejbsessionBankImpl/target/classes
|-- META-INF
|
`-- orm.xml
`-- ejava
`-- examples
`-- ejbsessionbank
|-- bl
|
|-- BankException.class
|
`-- Teller.class
|-- blimpl
|
`-- TellerImpl.class
|-- bo
|
|-- Account.class
|
|-- Ledger.class
|
`-- Owner.class
|-- dao
|
|-- AccountDAO.class
|
|-- DAOException.class
|
`-- OwnerDAO.class
`-- jpa
|-- JPAAccountDAO.class
`-- JPAOwnerDAO.class
* Note: we are not including a JavaSE persistence.xml in Impl
v131013
EJB: Session Beans
34
Enterprise
Java
Example Session Bean: Business Interface
package ejava.examples.ejbsessionbank.bl;
import java.util.List;
import ejava.examples.ejbsessionbank.bo.Account;
import ejava.examples.ejbsessionbank.bo.Ledger;
public interface Teller {
Account createAccount(String accNum) throws BankException;
Account getAccount(String acctNum) throws BankException;
Account closeAccount(String acctNum) throws BankException;
void updateAccount(Account account) throws BankException;
List<Account> getOverdrawnAccounts(int index, int count)
throws BankException;
List<Account> getAccounts(int index, int count)
throws BankException;
Ledger getLedger() throws BankException;
}
v131013
EJB: Session Beans
35
Example: EJB
Enterprise
Java
ejbsessionBankEJB/target/classes
|-- ejava
|
`-- examples
|
`-- ejbsessionbank
|
|-- dto
|
|
`-- OwnerDTO.class
|
`-- ejb
|
|-- Stats.class
|
|-- StatsEJB.class
|
|-- StatsLocal.class
|
|-- StatsRemote.class
|
|-- TellerEJB.class
|
|-- TellerLocal.class
|
`-- TellerRemote.class
`-- META-INF
|-- ejb-jar.xml
`-- persistence.xml
* Note: We are providing a JavaEE persistence.xml in the EJB
v131013
EJB: Session Beans
36
Enterprise
Java
Example Session Bean: Local and Remote Interfaces
package ejava.examples.ejbsessionbank.ejb;
import ejava.examples.ejbsessionbank.bl.Teller;
@javax.ejb.Local
public interface TellerLocal extends Teller {
}
package ejava.examples.ejbsessionbank.ejb;
import ejava.examples.ejbsessionbank.bl.Teller;
@javax.ejb.Remote
public interface TellerRemote extends Teller {
}
* Warning – although business interfaces can be used
for both local and remote interfaces, this only works
for simple data models – more later
v131013
EJB: Session Beans
37
Example Session Bean: Bean Class
Enterprise
Java
package ejava.examples.ejbsessionbank.ejb;
import javax.annotation.*;
import javax.ejb.*;
import javax.persistence.*;
...
@Stateless
public class TellerEJB implements TellerLocal, TellerRemote {
private static final Log log = ...
@Resource
protected SessionContext ctx;
@PersistenceContext(unitName="ejbsessionbank")
protected EntityManager em;
Stateless
@Resource(name="daoClass")
protected String daoClassName;
protected Teller teller;
v131013
EJB: Session Beans
38
Example Session Bean: Bean Class
Enterprise
Java
@PostConstruct
public void init() {
log.debug("init(), daoClass=" + daoClassName);
teller = new TellerImpl();
try {
AccountDAO dao = (AccountDAO)Thread.currentThread() //just a partial example of resolving
.getContextClassLoader() //a property supplied
.loadClass(daoClassName) //by the container
.newInstance();
((JPAAccountDAO)dao).setEntityManager(em);
((TellerImpl)teller).setAcctDAO(dao);
OwnerDAO ownerDAO = new JPAOwnerDAO();
((JPAOwnerDAO)ownerDAO).setEntityManager(em);
((TellerImpl)teller).setOwnerDAO(ownerDAO);
}
catch (Exception ex) {
log.fatal("error loading dao class:" + daoClassName, ex);
throw new EJBException("error loading dao class:" +
daoClassName + ", " + ex);
}
@PreDestroy
public void close() { ... }
v131013
EJB: Session Beans
39
Example Session Bean: Bean Class
Enterprise
Java
public Account createAccount(String accountNumber) throws BankException{
try {
return teller.createAccount(accountNumber);
}
catch (AccountDAOException ex) {
ctx.setRollbackOnly();
log.fatal("internal error creating account", ex);
throw new BankException("internal error creating account:"+ ex);
}
}
Log details of exception locally on server-side
Provide de-serializable message to client
v131013
EJB: Session Beans
40
Example Session Bean: ejb-jar.xml
Enterprise
Java
<?xml version="1.0"?>
<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_1.xsd"
version="3.1">
<enterprise-beans>
<session>
<ejb-name>TellerEJB</ejb-name>
<env-entry>
<env-entry-name>daoClass</env-entry-name>
<env-entry-type>java.lang.String</env-entry-type>
<env-entry-value>ejava.examples.ejbsessionbank.jpa.JPAAccountDAO
</env-entry-value>
</env-entry>
...
</session>
</enterprise-beans>
Watch out for <CR>!!!
</ejb-jar>
v131013
EJB: Session Beans
41
Enterprise
Java
Example Session Bean: persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
version="2.0">
<persistence-unit name="ejbsessionbank">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>java:jboss/datasources/ExampleDS</jta-data-source>
<jar-file>lib/ejbsessionBankImpl-${project.version}.jar</jar-file>
<properties>
<property name="hibernate.dialect"
value="${hibernate.dialect}"/>
</properties>
</persistence-unit>
</persistence>
v131013
EJB: Session Beans
42
Example Singleton Session Bean:
Local and Remote Interfaces
Enterprise
Java
package ejava.examples.ejbsessionbank.ejb;
public interface Stats {
void open();
void close();
int getTotal();
int getDelta();
void reset();
}
package ejava.examples.ejbsessionbank.ejb;
@javax.ejb.Local
public interface StatsLocal extends Stats {
}
package ejava.examples.ejbsessionbank.ejb;
@javax.ejb.Remote
public interface StatsRemote extends Stats {
}
v131013
EJB: Session Beans
43
Example Singleton Session Bean:
Bean
Class
Setup
package ejava.examples.ejbsessionbank.ejb;
Enterprise
Java
@javax.ejb.Singleton
@javax.ejb.Startup
@javax.ejb.ConcurrencyManagement(
javax.ejb.ConcurrencyManagementType.CONTAINER)
@javax.ejb.AccessTimeout(value=3000)
public class StatsEJB implements StatsLocal, StatsRemote {
private static final Log log = ...
private int delta;
private int total;
(Stateful)
@javax.annotation.PostConstruct
log.info("*** StatsEJB ***");
}
v131013
EJB: Session Beans
44
Example Singleton Session Bean:
Write/Read Methods
@Override
@javax.ejb.Lock(
javax.ejb.LockType.WRITE)
public void open() {
this.delta += 1;
this.total += 1;
}
@Override
@Lock(LockType.WRITE)
public void close() {
this.delta -= 1;
this.total += 1;
}
Enterprise
Java
@Override
@Lock(LockType.READ)
public int getTotal() {
return total;
}
@Override
@Lock(LockType.READ)
public int getDelta() {
return delta;
}
@Override
@Lock(LockType.WRITE)
public void reset() {
delta=0;
total=0;
}
v131013
EJB: Session Beans
45
Example: RMI Test
Enterprise
Java
ejbsessionBankTest/target/test-classes
|-- ejava
|
`-- examples
|
`-- ejbsessionbank
|
`-- ejbclient
…
…
|
|-- TellerEJBClientIT.class
|
|-- TellerRemotingIT.class
|
|-- TellerOwnerEJBClientIT.class
|
`-- TellerOwnerRemotingIT.class
|-- jboss-ejb-client.properties
|-- jndi.properties
`-- log4j.xml
JUnit Test Types
*Test = unit tests run by surefire plugin
*IT = integration tests run by failsafe plugin
v131013
EJB: Session Beans
46
•
•
•
•
•
Generic naming mechanism
Works identical with non-EJB resources
Ignorant of EJB details
Less Efficient
Being deprecated by JBoss in favor of
EJB Client
Remoting
Enterprise
Java
• JNDI Tree (Internally Accessible)
java:global/ejbsessionBankEAR/ejbsessionBankEJB/TellerEJB!ejava.examples.ejbsessionbank.ejb.TellerLocal
java:app/ejbsessionBankEJB/TellerEJB!ejava.examples.ejbsessionbank.ejb.TellerLocal
java:module/TellerEJB!ejava.examples.ejbsessionbank.ejb.TellerLocal
java:global/ejbsessionBankEAR/ejbsessionBankEJB/TellerEJB!ejava.examples.ejbsessionbank.ejb.TellerRemote
java:app/ejbsessionBankEJB/TellerEJB!ejava.examples.ejbsessionbank.ejb.TellerRemote
java:module/TellerEJB!ejava.examples.ejbsessionbank.ejb.TellerRemote
• JNDI Tree (externally Accessible)
java:jboss/exported/ejbsessionBankEAR/ejbsessionBankEJB/TellerEJB!ejava.examples.ejbsessionbank.ejb.TellerRemote
• jndi.properties
java.naming.factory.initial=org.jboss.naming.remote.client.InitialContextFactory
java.naming.factory.url.pkgs=
java.naming.provider.url=remote://127.0.0.1:4447
java.naming.security.principal=known
java.naming.security.credentials=password
jboss.naming.client.ejb.context=true
• External JNDI Name
ejbsessionBankEAR/ejbsessionBankEJB/TellerEJB!ejava.examples.ejbsessionbank.ejb.TellerRemote
v131013
EJB: Session Beans
47
JUnit Integration Test (IT)
public class TellerRemotingIT {
private static final Log log = ...
protected Teller teller;
@Before
public void setUp() throws Exception {
InitialContext jndi = new InitialContext();
teller = (TellerRemote)jndi.lookup(jndiName);
}
Enterprise
Java
JNDI Properties
being supplied through
jndi.properties file -orthrough a Properties
object
@Test
public void testCreateAccount() throws Exception {
log.info("*** testCreateAccount ***");
Account account=null;
//try with what should be a unique number
try {
account = teller.createAccount("1234");
log.debug("account created:" + account);
}
catch (Exception ex) {
log.fatal("error creating account:" + ex, ex);
fail("error creating account:" + ex);
}
v131013
EJB: Session Beans
48
•
•
•
•
•
EJB-specific naming mechanism
Does not work with non-EJB resources
Aware of EJB details
More efficient than Remoting
Non-standard
EJBClient
Enterprise
Java
• jndi.properties
java.naming.factory.initial=
java.naming.factory.url.pkgs=org.jboss.ejb.client.naming
java.naming.provider.url=
java.naming.security.principal=
java.naming.security.credentials=
• jboss-ejb-client.properties
#top level property listing the names of the connections. There will be a set
#of properties for each name listed here
remote.connections=default
#here we define the properties for the server we have called "default"
remote.connection.default.host=127.0.0.1
remote.connection.default.port=4447
remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED=false
• External JNDI Name
ejb:(ear)/(module)/(distinctName)/(ejbClass)!(remoteInterface)[?stateful]
ejb:ejbsessionBankEAR/ejbsessionBankEJB/””/TellerEJB!ejava.examples.ejbsessionbank.ejb.TellerRemote
v131013
EJB: Session Beans
49
Lazy Load Issues
Enterprise
Java
• EJB public List<Owner> getOwners(int index, int count) {
return teller.getOwners(index, count);
• RMI Test
List<Owner> owners = teller.getOwners(0, 100);
assertEquals("unexpected number of owners", 2, owners.size());
for(Owner o : owners) {
for (Account a: o.getAccounts()) { //LINE 87
...
}
}
• Error
org.hibernate.LazyInitializationException: failed to lazily initialize a
collection of role: ejava.examples.ejbsessionbank.bo.Owner.accounts, no
session or session was closed
...
org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersisten
tCollection.java:86)
at
org.hibernate.collection.PersistentBag.iterator(PersistentBag.java:249)
at
ejava.examples.ejbsessionbank.ejbclient.TellerOwnerRemoteTest.testLazy(Telle
rOwnerRemoteTest.java:87)
v131013
EJB: Session Beans
50
Lazy Load Correction
Enterprise
Java
• EJB
Remote
@Remote
public interface TellerRemote extends Teller {
List<Owner> getOwnersLoaded(int index, int count) throws BankException;
}
• EJBpublic List<Owner> getOwnersLoaded(int index, int count)
}
throws BankException {
List<Owner> owners = getOwners(index, count);
for(Owner owner : owners) {
for (Account account : owner.getAccounts()) {
account.getBalance(); //call a method to get loaded
}
}
return owners;
• RMI Test
List<Owner> owners = teller.getOwnersLoaded(0, 100);
Alt: relation fetch mode
Alt: DAO JPAQL Query
public class Owner {
@OneToMany(fetch=EAGER)
private List<Account> accounts;
v131013
SELECT o FROM Owner o
LEFT JOIN FETCH o.accounts
EJB: Session Beans
51
Non-POJO Class Issues
Enterprise
Java
• EJB public List<Owner> getOwnersLoaded(int index, int count)
}
throws BankException {
List<Owner> owners = getOwners(index, count);
for(Owner owner : owners) {
for (Account account : owner.getAccounts()) {
account.getBalance(); //call a method to get loaded
}
}
return owners;
• RMI Test
List<Owner> owners = teller.getOwnersLoaded(0, 100);
for(Owner o : owners) {
for (Account a: o.getAccounts()) {
log.info("account=" + a);
}
log.debug("addresses=" + o.getAccounts().getClass().getName());
assertTrue("unexpected collection class",
o.getAccounts().getClass().getName().contains("hibernate"));
}
• Output
-account=id=2, acctnum=111, bal=$0.0
-addresses=org.hibernate.collection.PersistentBag
v131013
EJB: Session Beans
52
Non-POJO Class Correction
• EJB
Enterprise
Java
public List<Owner> getOwnersPOJO(int index, int count) ...
List<Owner> ownersPOJO = new ArrayList<Owner>();
for(Owner owner : getOwners(index, count)) {
Owner ownerPOJO = new Owner(owner.getId());
ownerPOJO.setFirstName(owner.getFirstName());
ownerPOJO.setLastName(owner.getLastName());
ownerPOJO.setSsn(owner.getSsn());
for (Account account : owner.getAccounts()) {
Account accountPOJO = new Account(account.getId());
accountPOJO.setAccountNumber(account.getAccountNumber());
accountPOJO.deposit(account.getBalance());
ownerPOJO.getAccounts().add(accountPOJO);
}
ownersPOJO.add(ownerPOJO);
}
return ownersPOJO;
}
• RMI Test
owners = teller.getOwnersPOJO(0, 100);
...
• Output
log.debug("addresses=" + o.getAccounts().getClass().getName());
assertFalse("unexpected collection class",
o.getAccounts().getClass().getName().contains("hibernate"));
-account=id=2, acctnum=111, bal=$0.0
-addresses=java.util.ArrayList
v131013
EJB: Session Beans
53
BO Complexity Class Issues
Enterprise
Java
• Business Object
public class Owner implements Serializable {
private long id;
private String firstName;
private String lastName;
private String ssn;
private Collection<Account> accounts = new ArrayList<Account>();
...
v131013
EJB: Session Beans
54
BO Complexity Correction
Enterprise
Java
• DTO
Class
public class OwnerDTO implements Serializable {
...
private
private
private
private
private
static final long serialVersionUID = 1L;
long id;
String firstName;
String lastName;
int accounts;
• EJBpublic List<OwnerDTO> getOwnersDTO(int index, int count)
}
throws BankException {
List<OwnerDTO> ownersDTO = new ArrayList<OwnerDTO>();
for(Owner owner : getOwners(index, count)) {
OwnerDTO ownerDTO = new OwnerDTO(owner.getId());
ownerDTO.setFirstName(owner.getFirstName());
ownerDTO.setLastName(owner.getLastName());
ownerDTO.setAccounts(owner.getAccounts().size());
ownersDTO.add(ownerDTO);
}
return ownersDTO;
• RMI Test
List<OwnerDTO> owners = teller.getOwnersDTO(0, 100);
v131013
EJB: Session Beans
55
Enterprise
Java
Building EJBs
with Maven
v131013
EJB: Session Beans
56
Parent Project
|-|-|-|-`--
Enterprise
Java
ejbsessionBankBLImpl
ejbsessionBankEAR
ejbsessionBankEJB
ejbsessionBankTest
pom.xml
v131013
EJB: Session Beans
57
Parent Project
Enterprise
Java
<?xml version="1.0" encoding="UTF-8"?>
<project>
<parent>
<groupId>ejava</groupId>
<artifactId>ejava-root</artifactId>
<version>3.0.2012.2-SNAPSHOT</version>
<relativePath/>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>ejava.javaee.ejb</groupId>
<artifactId>ejbsessionBank</artifactId>
<packaging>pom</packaging>
<name>EJB Session Bean Bank</name>
<description>
This project is the root project for the core session bean example.
</description>
<modules>
<module>ejbsessionBankImpl</module>
<module>ejbsessionBankEJB</module>
<module>ejbsessionBankWAR</module>
<module>ejbsessionBankEAR</module>
<module>ejbsessionBankTest</module>
</modules>
</project>
v131013
EJB: Session Beans
58
EJB Project
Enterprise
Java
ejbsessionBankEJB/src/
`-- main
|-- java
|
`-- ejava
|
`-- examples
|
`-- ejbsessionbank
|
|-- dto
|
|
`-- OwnerDTO.java
|
`-- ejb
|
|-- StatsEJB.java
|
|-- Stats.java
|
|-- StatsLocal.java
|
|-- StatsRemote.java
|
|-- TellerEJB.java
|
|-- TellerLocal.java
|
`-- TellerRemote.java
`-- resources
`-- META-INF
|-- ejb-jar.xml
|-- persistence.xml
`-- (jboss-ejb3.xml)
v131013
EJB: Session Beans
59
Enterprise
Java
EJB Project pom.xml: ejb Packaging
<project>
<parent>
<artifactId>ejbsessionBank</artifactId>
<groupId>ejava.javaee.ejb</groupId>
<version>3.0.2012.2-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ejbsessionBankEJB</artifactId>
<packaging>ejb</packaging>
<name>Session Bank EJB</name>
<description>
This project provides an example of the core properties of a session bean.
</description>
<dependencies>
</dependencies>
<build>
</build>
<profiles>
</profiles>
</project>
v131013
EJB: Session Beans
60
EJB Project: dependencies
Enterprise
Java
<dependencies>
<!-- core dependencies -->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>ejbsessionBankImpl</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
v131013
EJB: Session Beans
61
EJB Project: plugins
Enterprise
Java
<build>
<!--tell the resource plugin to perform filtering on resources
to fill in dialect, etc. -->
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<!-- tell the EJB plugin we are using EJB3 and configure client-jar -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-ejb-plugin</artifactId>
<configuration>
<generateClient>true</generateClient>
<clientExcludes>
<clientExclude>**/ejb/*Local.class</clientExclude>
<clientExclude>**/ejb/*EJB.class</clientExclude>
</clientExcludes>
</configuration>
</plugin>
</plugins>
</build>
v131013
EJB: Session Beans
62
EJB Project: profiles
Enterprise
Java
<profiles>
<profile> <!-- H2 embedded/file-based DB -->
<id>h2db</id>
<properties>
<jdbc.driver>org.h2.Driver</jdbc.driver>
<jdbc.url>jdbc:h2:${basedir}/target/h2db/ejava</jdbc.url>
<jdbc.user>sa</jdbc.user>
<jdbc.password/>
<hibernate.dialect>
org.hibernate.dialect.H2Dialect
</hibernate.dialect>
</properties>
...
</profile>
</profiles>
v131013
EJB: Session Beans
63
EJB Project: persistence.xml
Enterprise
Java
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
version="2.0">
<persistence-unit name="ejbsessionbank">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>java:jboss/datasources/ExampleDS</jta-data-source>
<properties>
<property name="hibernate.dialect"
value="${hibernate.dialect}"/>
<property name="hibernate.show_sql" value="false"/>
</properties>
</persistence-unit>
• After filtering
<property name="hibernate.dialect"
value="org.hibernate.dialect.HSQLDialect"/>
v131013
EJB: Session Beans
64
EAR Project
Enterprise
Java
ejbsessionBankEAR/
`-- pom.xml
• pom.xml
<project>
<parent>
<artifactId>ejbsessionBank</artifactId>
<groupId>ejava.javaee.ejb</groupId>
<version>3.0.2012.2-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ejbsessionBankEAR</artifactId>
<packaging>ear</packaging>
<name>Session Bank EAR</name>
<dependencies>
</dependencies>
<build>
</build>
</project>
v131013
EJB: Session Beans
65
EAR Project (cont.): dependencies
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>ejbsessionBankEJB</artifactId>
<version>${project.version}</version>
<type>ejb</type>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>ejbsessionBankWAR</artifactId>
<version>${project.version}</version>
<type>war</type>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>ejbsessionBankImpl</artifactId>
<version>${project.version}</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
v131013 </dependency>
EJB: Session Beans
</dependencies>
Enterprise
Java
66
EAR Project (cont.): plugins
Enterprise
Java
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-ear-plugin</artifactId>
<configuration>
<description>
Example Session Bean Bank Application
</description>
<defaultLibBundleDir>lib</defaultLibBundleDir>
<!-- eliminates use of version in EAR JNDI name portion -->
<applicationName>${project.artifactId}</applicationName>
<modules>
<webModule>
<groupId>${project.groupId}</groupId>
<artifactId>ejbsessionBankWAR</artifactId>
<contextRoot>ejbsessionBank</contextRoot>
</webModule>
<!-- eliminates use of the version in the EJB JNDI name -->
<ejbModule>
<groupId>${project.groupId}</groupId>
<artifactId>ejbsessionBankEJB</artifactId>
<bundleFileName>ejbsessionBankEJB.jar</bundleFileName>
</ejbModule>
</modules>
</configuration>
</plugin>
</plugins>
</build>
v131013
EJB: Session Beans
67
EAR Project (cont.)
Enterprise
Java
• Use cargo plugin to undeploy built and deployed EARs
<profile>
<id>undeploy</id>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.cargo</groupId>
<artifactId>cargo-maven2-plugin</artifactId>
<executions>
<execution>
<id>undeploy-ear</id>
<phase>pre-clean</phase>
<goals>
<goal>undeploy</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
v131013
EJB: Session Beans
68
EAR Project (cont.)
Enterprise
Java
ejbsessionBankEAR/target/ejbsessionBankEAR-3.0.2012.2-SNAPSHOT
|-- ejbsessionBankEJB.jar
|-- ejbsessionBankWAR-3.0.2012.2-SNAPSHOT.war
|-- lib
|
|-- ejava-util-3.0.2012.2-SNAPSHOT.jar
|
`-- ejbsessionBankImpl-3.0.2012.2-SNAPSHOT.jar
`-- META-INF
`-- application.xml
v131013
EJB: Session Beans
69
RMI Test Project
Enterprise
Java
ejbsessionBankTest/
|-- pom.xml
`-- src
|-- main
`-- test
|-- java
|
`-- ejava
|
`-- examples
|
`-- ejbsessionbank
|
`-- ejbclient
|
|-- TellerOwnerRemoteTest.java
|
`-- TellerRemoteTest.java
`-- resources
|-- jndi.properties
`-- log4j.xml
• pom.xml
<project>
<parent>
<artifactId>ejbsessionBank</artifactId>
<groupId>ejava.javaee.ejb</groupId>
<version>3.0.2012.2-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ejbsessionBankTest</artifactId>
<packaging>jar</packaging>
<name>Session Bank Test</name>
v131013
EJB: Session Beans
70
RMI Test Project (cont.)
Enterprise
Java
<dependencies>
...
<!-- component to test within deployment-->
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>ejbsessionBankEJB</artifactId>
<version>${project.version}</version>
<type>ejb-client</type>
<scope>test</scope>
</dependency>
<!-- package being deployed must be a dependency -->
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>ejbsessionBankEAR</artifactId>
<version>${project.version}</version>
<type>ear</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>ejava.common</groupId>
<artifactId>jboss-rmi-client</artifactId>
<version>${project.version}</version>
<type>pom</type>
<scope>test</scope>
</dependency>
...
v131013
EJB: Session Beans
71
RMI Test Project (cont.): plugins
Enterprise
Java
<build>
<plugins>
<!-- artifacts to deploy to server -->
<plugin>
<groupId>org.codehaus.cargo</groupId>
<artifactId>cargo-maven2-plugin</artifactId>
<configuration>
<deployables>
<deployable>
<groupId>${project.groupId}</groupId>
<artifactId>ejbsessionBankEAR</artifactId>
<type>ear</type>
</deployable>
</deployables>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<configuration>
<systemPropertyVariables>
<foo>${foovar}</foo>
</systemPropertyVariables>
</configuration>
</plugin>
</plugins>
</build>
v131013
EJB: Session Beans
72
Summary
Enterprise
Java
• Integrates Bean activity (“task script”)
• Server-side code for client
– Stateless and Stateful
• Server-side cache for client
– Stateful
• POJO with minor amount of class metadata
v131013
EJB: Session Beans
73
References
Enterprise
Java
• “Enterprise JavaBeans 3.0, 5th Edition”; Burke &
Monsen-Haefel; ISBN 0-596-00978-X; O'Reilly
• “Mobile Design Patterns and Architectures”,
http://www.titu.jyu.fi/modpa/ (MODPA)
– Remote Facade
• http://www.titu.jyu.fi/modpa/Patterns/patternRemoteFacade.html
• “Patterns of Enterprise Archecture, Chapter 15: Remote
Facade”; Martin Fowler
– http://www.theserverside.com/tt/articles/content/FowlerP
atterns/Fowler_ch15.pdf
v131013
EJB: Session Beans
74
Related documents