Salam,
http://www.eclipse.org/webtools/dali/
a very existing tool exist in Eclipse ( I think >= 3.5)
to open it, Window>Show Views> JPA Details
Showing posts with label EJB. Show all posts
Showing posts with label EJB. Show all posts
05 June 2011
18 January 2010
Calling session beans on JSF Managed bean's start up
One situation may occurs is that you need to call some session bean method on some JSF page's start up.
If you try to put the code that calls the injected EJB session bean's method in your JSF request-scoped Managed bean constructor, you will get a NullPointerException as the Injection occurred after making an instance of the managed bean.
The solution is that to provide a @PostConsruct method and put your EJB calling code in.
@PostConsruct is supported in JSF1.2 and if you running your JSF Application in an Application Server (example JBoss)
So, Here's the sequence the managed bean instance is created in:
Calling manged bean constructor => Injecting Session bean (if any) => calling PostConstruct method(s) (if any)
Here's an example:
And here's the output :
If you try to put the code that calls the injected EJB session bean's method in your JSF request-scoped Managed bean constructor, you will get a NullPointerException as the Injection occurred after making an instance of the managed bean.
The solution is that to provide a @PostConsruct method and put your EJB calling code in.
@PostConsruct is supported in JSF1.2 and if you running your JSF Application in an Application Server (example JBoss)
So, Here's the sequence the managed bean instance is created in:
Calling manged bean constructor => Injecting Session bean (if any) => calling PostConstruct method(s) (if any)
Here's an example:
public class ShowArticleBean {
@EJB(name="SimpleWiki/ArticleManagementBean/local")
private ArticleManagement articleMgmt;
public ShowArticleBean() {
System.out.println("In Constructor : " + articleMgmt);
}
@PostConstruct
public void construct() {
System.out.println("In PostConsruct : " + articleMgmt);
}
And here's the output :
04:51:29,546 INFO [STDOUT] In Constructor : null
04:51:29,547 INFO [STDOUT] In PostConsruct : ArticleManagementBean
12 January 2010
Avoid throwing RuntimeException from you Session beans
Working with session beans usually requires you to throw some type of exceptions to the calling layer (usually the presentation layer), So beware, don't try to throw RuntimeExceptions or RemoteException because the Container will encapsulate these exceptions in EJBException and then destroys the bean instance from the bean bool.
If you need to throws Runtime/Remote Exceptions, then add @ApplicationException(rollback=true) as a class level annotation to your Exception class, and this applicable only on your own custom exceptions.
In all cases (RuntimeException or Application Exceptions) the container will rollback the transactino.
From EJB in Action :
“In EJB , an application exception is an exception that the client is expected to handle. When thrown, such exceptions are passed directly to the method invoker. By default, all checked exceptions except for
java.rmi.RemoteException are assumed to be application exceptions.
On the other hand, all exceptions that inherit from either java.rmi. RemoteExceptions or java.lang.RuntimeException are assumed to be system exceptions (as you might already know, all exceptions that inherit
from java.lang.RuntimeException are unchecked). In EJB , it is not assumed that system exceptions are expected by the client. When encountered, such exceptions are not passed to the client as is but are wrapped in a javax.ejb.EJBException instead.”
Here's an example session bean that throws IllegalArguemntException ( a well-known runtime exception):
And here's a test client :
And here's the output of the EJB Container :
As you can see from the output of the session bean, When a RuntimeException thrown, the EJB Container destroys the bean instance from the bean bool !
If you need to throws Runtime/Remote Exceptions, then add @ApplicationException(rollback=true) as a class level annotation to your Exception class, and this applicable only on your own custom exceptions.
In all cases (RuntimeException or Application Exceptions) the container will rollback the transactino.
From EJB in Action :
“In EJB , an application exception is an exception that the client is expected to handle. When thrown, such exceptions are passed directly to the method invoker. By default, all checked exceptions except for
java.rmi.RemoteException are assumed to be application exceptions.
On the other hand, all exceptions that inherit from either java.rmi. RemoteExceptions or java.lang.RuntimeException are assumed to be system exceptions (as you might already know, all exceptions that inherit
from java.lang.RuntimeException are unchecked). In EJB , it is not assumed that system exceptions are expected by the client. When encountered, such exceptions are not passed to the client as is but are wrapped in a javax.ejb.EJBException instead.”
Here's an example session bean that throws IllegalArguemntException ( a well-known runtime exception):
@Stateless
@Remote(AccountManagement.class)
@Local(AccountManagement.class)
public class AccountManagementBean extends DBBaseBean implements AccountManagement {
public void registerUser(User user) throws IllegalArgumentException {
if (user == null || StringUtil.isNullSpacesOrEmpty(user.getUsername()) || user.getPassword() == null)
throw new IllegalArgumentException("Uncomplete user registeration data");
em.persist(user);
logger.info("User created :" + user.getUsername());
}
@PostConstruct
public void init() {
System.out.println("INIT");
}
@PreDestroy
public void destroy() {
System.out.println("DESTROY");
}
}
And here's a test client :
public class Main {
public static void main(String[] args) throws Exception{
AccountManagement test = InitialContext.doLookup("SimpleWiki/AccountManagementBean/remote");
try {
test.registerUser(null);
}catch (Exception ex) {
if (ex.getCause() instanceof IllegalArgumentException) {
System.out.println("IllegalArgumentException : " + ex.getCause().getMessage());
}else {
ex.printStackTrace();
}
}
}
}
And here's the output of the EJB Container :
21:33:12,504 INFO [STDOUT] INIT
21:33:28,595 INFO [STDOUT] DESTROY
As you can see from the output of the session bean, When a RuntimeException thrown, the EJB Container destroys the bean instance from the bean bool !
13 October 2009
An example on pooling in Stateless Session Beans
Stateless Session Beans are pooled and reused by the container, also one important thing to note when you JNDI a statless bean to get a reference to the bean, subsequent calls to methods on this reference doesn't grantee to be for the same instance created for you from JNDI.
As the container can create new instances and handle them to you when necessary.
Here's the example that illustrate what I am saying:
The Stateless Bean implementation:
@Statelesspublic class TestSessionBeansBoolingBean implements TestSessionBeansBooling {Logger logger = Logger.getLogger(TestSessionBeansBoolingBean.class);public void doSomeAction() {// this action will take a long time:try {logger.info(">> Doing the business ");Thread.sleep(5000);}catch (Exception ex) {ex.printStackTrace();}// Then I'll call this bean more than once, and I'll notice that more than once instances will be created}@PostConstructpublic void construct() {logger.info("Creating a new Stateless Session Bean instance");}}
And Here's the Client, It is a standalone client :
public class TestSessionBeansBoolingClient {public static void main(String[] args) {TestSessionBeansBooling bean = (TestSessionBeansBooling) InitialContextHelper.lookup("ejbinaction_part2/" + TestSessionBeansBoolingBean.class.getSimpleName() + "/remote");bean.doSomeAction();bean.doSomeAction(); // new bean instance will be created at this pointbean.doSomeAction();}}
And here's the output from one run for the client:
13:56:19,998 INFO [TestSessionBeansBoolingBean] Creating a new Stateless Session Bean instance13:56:20,023 INFO [TestSessionBeansBoolingBean] >> Doing the business13:56:25,062 INFO [TestSessionBeansBoolingBean] Creating a new Stateless Session Bean instance13:56:25,062 INFO [TestSessionBeansBoolingBean] >> Doing the business13:56:30,072 INFO [TestSessionBeansBoolingBean] >> Doing the business
How to use JDBC with Oracle Database in JBoss
This article is a quick and dirty yet complete article about how to setup Oracle as a DataSource for using in JDBC-based application with session beans in JBoss 4.2 .
First you need to add this file to : $JBOSS_HOME/server/default/deploy
File: oracle-ds.xml
The rest of work is in your session bean code, suppose we have a bean that is called BidManagerBean, here's the code:
Resources : http://www.jboss.org/community/wiki/setUpAOracleDataSource
First you need to add this file to : $JBOSS_HOME/server/default/deploy
File: oracle-ds.xml
<?xml version="1.0" encoding="UTF-8"?>
<datasources>
<local-tx-datasource>
<!-- The jndi name of the DataSource, it is prefixed with java:/ -->
<!-- Datasources are not available outside the virtual machine -->
<jndi-name>OracleDS</jndi-name>
<!-- I am using oracle 10g, change the url to suite you, try and tell me as the only version of oracle I tired was 10g -->
<connection-url>jdbc:oracle:thin:@localhost:1521:XE</connection-url>
<driver-class>oracle.jdbc.driver.OracleDriver</driver-class>
<user-name>ejb</user-name>
<password>system</password>
<!-- The minimum connections in a pool/sub-pool. Pools are lazily constructed on first use -->
<min-pool-size>5</min-pool-size>
<!-- The maximum connections in a pool/sub-pool -->
<max-pool-size>100</max-pool-size>
<prepared-statement-cache-size>32</prepared-statement-cache-size>
<valid-connection-checker-class-name>org.jboss.resource.adapter.jdbc.vendor.OracleValidConnectionChecker</valid-connection-checker-class-name>
<exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.OracleExceptionSorter</exception-sorter-class-name>
<metadata><type-mapping>Oracle9i</type-mapping></metadata>
</local-tx-datasource>
</datasources>
The rest of work is in your session bean code, suppose we have a bean that is called BidManagerBean, here's the code:
import org.jboss.resource.adapter.jdbc.WrappedConnection;You are done.
import oracle.jdbc.OracleConnection;
// import other staff ...
@Local(ItemManager.class)
@Stateless
public class ItemManagerBean {
// mapped name is the name in jndi-name tag in oracle-ds.xml
@Resource(name="ds/AnyNameSuchAsYourAppName", mappedName="java:/OracleDS")
private DataSource datasource;
private OracleConnection oraConnection;
private Logger logger = Logger.getLogger(ItemManagerBean.class);
// this method is the post construct method (i.e. called before any other method is being callded, after the bean inited and DI injected)
@PostConstruct
public void init() {
try {
logger.info("start post consturct method");
Connection inconnection = datasource.getConnection();
WrappedConnection wConn = (WrappedConnection) inconnection;
Connection underlyingConn = wConn.getUnderlyingConnection();
oraConnection = (OracleConnection) underlyingConn;
}catch(SQLException ex) {
ex.printStackTrace();
}
}
@PreDestroy
public void destroy() {
try {
logger.info("start pre destroy method");
oraConnection.close();
oraConnection = null;
}catch (SQLException ex) {
ex.printStackTrace();
}
}
// testing the connection by submiting a simple query
public List<Item> getAllItems() throws ItemsNotFoundException{
List<Item> itemList = null;
Statement stmt = null;
ResultSet rs = null;
try {
String sql = "SELECT ID, NAME, PRICE FROM ITEMS";
stmt = oraConnection.createStatement();
rs = stmt.executeQuery(sql);
itemList = constructItemList(rs);
rs.close();
}catch (SQLException ex) {
throw new ItemsNotFoundException(ex);
}finally {
try {
}catch (Throwable ignore) {}
}
return itemList;
}
}
Resources : http://www.jboss.org/community/wiki/setUpAOracleDataSource
Subscribe to:
Posts (Atom)