OpenSource Geek

أسألك أن تدعو الله لي دعوه بظهر الغيب

25 November 2009

Loading properties files using Classloader

One problem I was facing last week while playing with a small client/server application was that I cannot refer to the relative path of properties files using eclipse.

Let me discuss the situation; I have a class called Constants that load a properties file that contains the server host and port:

public class Constants {

private static Logger logger = Logger.getLogger(Constants.class);

public static String HOST_NAME;
public static int PORT_NUMBER;

static {
try {
Properties jposAppProps = new Properties();
jposAppProps.load(new FileInputStream(new File("JposApp.properties")));
String host = jposAppProps.getProperty("server.host");
String port = jposAppProps.getProperty("server.port");

if (host == null || port == null)
throw new Exception("Invalid configuration");

HOST_NAME = host;
PORT_NUMBER = Integer.parseInt(port);

}catch(NumberFormatException ex) {
logger.fatal("Invalid configuration", ex);
System.exit(-1);
}
catch (IOException ex) {
logger.fatal(ex.getMessage(), ex);
System.exit(-1);
}catch(Exception ex) {
logger.fatal(ex.getMessage(), ex);
System.exit(-1);
}
}
}

The problem appears in the line :
jposAppProps.load(new FileInputStream(new File("JposApp.properties")));

I have the JposApp.properties in the "src" directory, so when running this class from outside eclipse, everything goes well.
But from inside eclipse, eclipse needs me to provide an absolute path !! (may be there's a work-around way, but I don't know it)

But I recognized that, Web frameworks like JSF and JSPX-BAY, uses classloaders to load properties files, So, I choose that way.

So, I have replaced the line above by this one:
jposAppProps.load(Constants.class.getClassLoader().getResourceAsStream("JposApp.properties"));

Really I have not much experience with class loaders, so this line may be abuse, but it really works.

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:

@Stateless
public 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
}
@PostConstruct
public 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 point
bean.doSomeAction();
}
}

And here's the output from one run for the client:

13:56:19,998 INFO [TestSessionBeansBoolingBean] Creating a new Stateless Session Bean instance
13:56:20,023 INFO [TestSessionBeansBoolingBean] >> Doing the business
13:56:25,062 INFO [TestSessionBeansBoolingBean] Creating a new Stateless Session Bean instance
13:56:25,062 INFO [TestSessionBeansBoolingBean] >> Doing the business
13: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

<?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;
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;
}

}
You are done.
Resources : http://www.jboss.org/community/wiki/setUpAOracleDataSource

10 October 2009

Layerd architectures (1)

Most enterprise applications contain a large number of components. Enterprise applications are designed to solve a unique type of customer problem, but they share many common characteristics. For example see more ...

01 October 2009

Jakarta Commons Net

Actually, Apache foundation is a big source for open source libraries in Java.

On of their projects that very interesting is Jakarta Commons Net I found it while navigation through trying to answer on a thread in Arab Team 2000 forums.

Library home page : http://commons.apache.org/net
Java docs : http://commons.apache.org/net/api
Interesting class for FTP : http://commons.apache.org/net/api/org/apache/commons/net/ftp/FTPClient.html

Thanks.

19 September 2009

Enable Arabic in JSPX:

Enable arabic entring arabic letters in JSPX forms goes as if any other framework that hides servlets details.
you will need to add a Filter as the following :
public class InitFilter implements Filter {

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
// pass the request along the filter chain
chain.doFilter(request, response);
}
}
and then configure this filter in your web.xml :

<filter>
<display-name>InitFilter</display-name>
<filter-name>InitFilter</filter-name>
<filter-class>com.goodtreeit.storefront.web.InitFilter</filter-class>
</filter> <filter-mapping> <filter-name>InitFilter</filter-name> <servlet-name>JspxHandler</servlet-name> <dispatcher>REQUEST</dispatcher> <dispatcher>FORWARD</dispatcher> <dispatcher>INCLUDE</dispatcher> <dispatcher>ERROR</dispatcher> </filter-mapping>

09 September 2009

Introduction to JSPX ListTable component

So far we have introduced JSPX and Talked about the combo boxes and how to deal
with in the JSPX.
Today we are to talking about ListTable compoenent, it is actally a Data Table or
a Grid. The reason the framework creators don't name it DataTable because there is
already a DataTable component. Both components are responsible for displaying Grid
of data on the form, but DataTable is to deal with the underlying RDMBS directly,
but the ListTable, deals with components such as DAOs, EJBs, Webservices.
The following snippet is from JSPX formal documentations :
“ Formally we introduced DataTable as a readymade solution from jspx to interact
with DB and provide a widely common task that is to search DB and apply filters on
the search results. Some might say that interacting with DB directly is not
preferred way specially from the presentation

Read more ...