Monday, August 31, 2009

Daemon Applications in J2EE


Prior to ejb 3.0 spec there was no such concept of container provided timer services. But now an ejb (stateless + mdb) can schedule itself. Moreover container provided timer services are reliable (can survive container crash) and serializable (we can save timer handle for later reference e.g. for cancellation).
But still we cannot right daemon ejbs! It could have been possible if timer services were not transaction aware so we could create timer in PostConstruct callback. But since timer services are transaction aware and PostConstruct callback is not, so we cannot do this. How to get away with it? Startup servlet is the solution, it will call our dameon ejb on first instance and from there we can schedule for regular intervals.
Other point that must be kept in mind while using ejb timer services is that they are not real time as per specs i.e. we cannot expect container to expire timer in millis. Programming model does not restrict it as interval unit is in millis but container does not provide any guarantees for real time. So, for this you are bound to use schedulers e.g. Quartz. I have seen two ways, to integrate quartz in j2ee
1-      Startup servlet approach as mentioned above. http://www.theserverside.com/news/thread.tss?thread_id=24896
2-       A resource adapter with Message beans as endpoints see JBoss for an implementation. This is really cool way of achieving this. http://www.jboss.org/ejb3/docs/tutorial/jca/inflow/quartz/quartz.html

Sunday, August 30, 2009

JAAS LDAP OC4J

We need a good LDAP tool; the best I found was LDAPSoft LDAP Admin Tool. It is limited trial version. It automatically connects to my network’s LDAP server if connected to LAN and gives a very good view active directory contents.
For website orion-web.xml
For ejb orion-ejb.xml
For application orion-application.xml
Orion-xxx.xml is OC4J propriety file and is not dictated by J2EE specs.
We need to create orion-application.xml using the information given by LDAPSoft.
<?xml version = '1.0' encoding = 'windows-1252'?>
<orion-application xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                   xsi:noNamespaceSchemaLocation="http://xmlns.oracle.com/oracleas/schema/orion-application-10_0.xsd">
 <!--jazn element specifies that I am using custom LDAP provider i.e. Active directory for JAAS. Other options for JAAS are db, file based, Oracle Internet Directory (oracle implementation of LDAP)-->
 <jazn provider="XML">
  <property name="custom.ldap.provider" value="true"></property>
 </jazn>
<!—Role that I will be using in the application. I gave it an app friendly name i.e. RAUser but in the end this app friendly role name must be mapped to a LDAP group whom authenticated users will be member. So, In order to define roles in the application I have to follow a three step process.
1- Define app friendly role name in web.xml under <security-role>
2- Specify authorization access of the role in web.xml under
<security-constraint>….<auth-constraint>. This step is optional.
3- Define mapping of app friendly roles names to backend (db, file based, LDAP) security provider. The first two steps are defined by J2EE specs but this step is specific is container. So, for OC4J I define it in orion-application.xml under <security-role-mapping>
   -->
 <security-role-mapping name="RAUser">
  <group name="VAS IT"></group>
 </security-role-mapping>
<!—- This section defines LDAP connectivity details. The content of this section are copied to system-jazn-data.xml after you deploy your application. All the settings under this section can be mentioned at deployment time using OracleAS Control but I took them to orion-application.xml so that I can reuse this file across projects. For this first time I deployed my application from OAS control but afterwards I copied the below section from system-jazn-data.xml-->
 <jazn-loginconfig>
  <application>
<!—application name that I will use when I deploy the application in OC4J.-->
   <name>RA-ldap</name>
   <login-modules>
    <login-module>
     <class>oracle.security.jazn.login.module.LDAPLoginModule</class>
     <control-flag>required</control-flag>
     <options>
      <option>
       <name>oracle.security.jaas.ldap.connect.pool.prefsize</name>
       <value>10</value>
      </option>
      <option>
       <name>oracle.security.jaas.ldap.connect.pool.initsize</name>
       <value>2</value>
      </option>
      <option>
       <name>oracle.security.jaas.ldap.connect.pool.timeout</name>
       <value>300000</value>
      </option>
      <option>
 <!--ObjectClass of user, for Active directory standard is user. I can verify this from LDAP tool by viewing any user properties-->      <name>oracle.security.jaas.ldap.user.object.class</name>
       <value>user</value>
      </option>
      <option>
       <name>oracle.security.jaas.ldap.provider.connect.pool</name>
       <value>true</value>
      </option>
      <option>
 <!--User credentials that I will use to connect to Active Directory server, for the time being I used my own. I can search and read Active Directory using my own credentials. But you should create credentials specifically for this app and set password expiry to never -->  <name>oracle.security.jaas.ldap.provider.credential</name>
       <value>{903}iezH/eKV6X1BkCbc/j+aKS+K</value>
      </option>
      <option>
       <name>oracle.security.jaas.ldap.provider.type</name>
       <value>Active Directory</value>
      </option>
      <option>
       <name>oracle.security.jaas.ldap.connect.pool.maxsize</name>
       <value>25</value>
      </option>
      <option>
<!--Active directory server info -->
       <name>oracle.security.jaas.ldap.provider.url</name>
       <value>ldap://172.18.70.33:389</value>
      </option>
      <option>
<!--Whether to search for role (IT) directly under oracle.security.jaas.ldap.role.searchbase or in the whole subtree that lies under it which is obviously expensive-->
       <name>oracle.security.jaas.ldap.role.searchscope</name>
       <value>onelevel</value>
      </option>
      <option>
<!--Whether to search for user directly under oracle.security.jaas.ldap.user.searchbase or search whole subtree-->
       <name>oracle.security.jaas.ldap.user.searchscope</name>
       <value>onelevel</value>
      </option>
      <option>
<!-- Search base for role (IT)-->
       <name>oracle.security.jaas.ldap.role.searchbase</name>
       <value>OU=Groups,OU=RASoft,DC=WT,DC=WI,DC=Pri</value>
      </option>
      <option>
<!-- Search base for user-->
       <name>oracle.security.jaas.ldap.user.searchbase</name>
       <value>OU=Executives,OU=IT,OU=Central,OU=RASoft,DC=WT,DC=WI,DC=Pri</value>
      </option>
      <option>
<!—Which LDAP attribute contains group name? It is cn by default for active diretcory-->       <name>oracle.security.jaas.ldap.role.name.attribute</name>
       <value>cn</value>
      </option>
      <option>
<!--ObjectClass of group/role which is group by default for Active Directory-->       <name>oracle.security.jaas.ldap.role.object.class</name>
       <value>group</value>
      </option>
      <option>
<!--Which LDAP attribute contains user name? It is sAMAccountName by default for active diretcory--> <name>oracle.security.jaas.ldap.user.name.attribute</name>
       <value>sAMAccountName</value>
      </option>
      <option>
<!—User credentials for connecting to active directory server-->
       <name>oracle.security.jaas.ldap.provider.user</name>
       <value>wt\struser</value>
      </option>
      <option>
<!--Whether user are direct member of role/group (IT)-->       <name>oracle.security.jaas.ldap.membership.searchscope</name>
       <value>direct</value>
      </option>
      <option>
<!--Which group/role attribute specifies membership? For Active Directory it is by default member-->      
       <name>oracle.security.jaas.ldap.member.attribute</name>
       <value>member</value>
      </option>
      <option>
       <name>oracle.security.jaas.ldap.lm.cache_enabled</name>
       <value>true</value>
      </option>
     </options>
    </login-module>
   </login-modules>
  </application>
 </jazn-loginconfig>
</orion-application>
Now I need to focus on web.xml where I will set appropriate configs to trigger form based authentication. Below is the related excerpt from web.xml.
<!--
    ISSUE:
    If welcom-file-list is enabled partial requests
    enter into redirect loop. e.g.
    http://localhost:8888/RA-ldap/
    or
    http://localhost:8888/RA-ldap/faces
    results in redirect to
    http://localhost:8888/RA-ldap/
    and continues forever.
    -->
<!--Note no slash(/) in start as is the case with other paths specified in web.xml because this is not a path but file name instead-->
    <!--
    <welcome-file-list>         
        <welcome-file>faces/verifyNic.jsp</welcome-file>
    </welcome-file-list>-->
    <security-constraint>
        <display-name>SecurityConstraint</display-name>
        <web-resource-collection>
            <web-resource-name>SecurePages</web-resource-name>
            <description></description>
            <url-pattern>/faces/verifyNic.jsp</url-pattern>
            <http-method>GET</http-method>
            <http-method>POST</http-method>
            <http-method>HEAD</http-method>
            <http-method>PUT</http-method>
            <http-method>OPTIONS</http-method>
            <http-method>TRACE</http-method>
            <http-method>DELETE</http-method>
        </web-resource-collection>
        <auth-constraint>
            <description></description>
            <role-name>RAUser</role-name>
        </auth-constraint>
    </security-constraint>
    <login-config>
        <auth-method>FORM</auth-method>
        <form-login-config>
            <form-login-page>/faces/login.jsp</form-login-page>
            <form-error-page>/faces/login.jsp?login=Incorrect user name / password</form-error-page>
        </form-login-config>
    </login-config>
    <security-role>
     <role-name>RAUser</role-name>
    </security-role>
FORM BASED AUTHENTICATION
In form based auth the login page as specified by <form-login-page> should post two params j_username, j_password to j_security_check servlet. This is what J2EE specs define. The sequence of steps is:
1-    Users requests a protected resource such as in this case verifyNic.jsp
2-    AS determines whether user is already logged in by checking if its session exists on server.
3-    If not logged in AS redirects to <form-login-page>
4-    Login page gets user name and password and post it to j_security_check which authenticates and authorize user and redirects user to url requested in step 1.
To make redirection in step 4 work in OC4J I need to start the server with following java option:
-Doc4j.redirect=true
For stand alone I do it by starting sever like this
>java -Doc4j.redirect=true -jar
$ORACLE_STANDALONE_HOME\j2ee\home\oc4j.jar
And for OAS I need to put this parameter in server properties which can be accessed from OAS control or opmn.xml.
In OAS control click on instance then Administration and then server properties and add it under java options section.
But what if user comes direct to login page or user logs out and tries to login again? To which page will AS redirect user? OC4J sends user to no where and keeps j_security_check in url which displays resource not found (404) error in browser. Some app servers allow another parameter j_url or j_uri to j_security_check so that server can redirect, after user is authenticated, to the given url but this is not the case with OC4J. I was unable to use welcome-file-list feature of web.xml as it enters into redirect loop (for details see above web.xml excerpt).
Another issue with JSF is that I cannot define the form’s action target because it follows a post-back model. And if I use a simple JSP page for login, I am deprived of all JSF input validations and then I have to do it all myself.
So the solution to above two problems is login proxy page. Below is JSF navigation diagram of the project.

The action of login.jsp is
        FacesContext context = FacesContext.getCurrentInstance();
        Map request = context.getExternalContext().getRequestMap();
        request.put("username", txtUser.getValue());
        request.put("password", txtPassword.getValue());
        return "proxy";
The jsp source of proxy.jsp is
<body onload="document.forms[0].submit();document.forms[1].submit();">
 
  <form action="verifyNic.jsp" method="POST"></form>
  <form action="j_security_check" method="POST">
      <input type="hidden" name="j_username" value="${requestScope.username}"/>
      <input type="hidden" name="j_password" value="${requestScope.password}"/>
  </form>
Explanation of proxy.jsp:
First html form tells OC4J that after authentication succeeds redirect me to verifyNic.jsp.
Second form submits user supplied credentials on previous page to j_security_check.
The order of form submits is important.
Logout
        FacesContext context = FacesContext.getCurrentInstance();
        HttpSession session = (HttpSession)context.getExternalContext().getSession(false);
        session.invalidate();
Get logged in user name in EJB
    @Resource
    private SessionContext ctx;
……
ctx.getCallerPrincipal().getName()
Login error
<h:outputLabel value="#{param.login}" …
Displays whatever is in query string parameter login. E.g. for login.jsp?login=incorrect it will display incorrect.
Value attribute uses JSF Unified Expression Language (EL) and implicit object param.



Must use tools and libs for web applications
1- Firefox, Firebug (No need to debug with alerts, can also track http requests/response). FirePhp for php users provides additional logging features for server side script.
1- jquery (script your apps with it, its really powerful)
2- jquery ui (change ui themes in minutes, even provide theme change feature to website users)
3- jqgrid (a javascript + ajax grid library, very powerful, search, filter, paging etc)

Saturday, August 29, 2009

Advanced XML RPC Library

Apache xml rpc is good as it relieves programmer from using xml constructs, and exposes xml rpc request/response in object oriented form. See apache project site on mappings of xml rpc constructs to different types for more details. But still a better way would be to expose xml rpc as domain objects. Similar to what JAXB does in case of domain objects based on XSDs. Since XML RPC has its own schema so a domain classe code generation tool would have to rely on xml documents or annotations instead of schema.

An example for .net is http://www.xml-rpc.net/

And for java is: http://xmlrpc.sourceforge.net/

Marquïee XML-RPC Library

Commons Apache Http Client (Disable connection pooling)

Commons Apache Http Client (Disable connection pooling)

In some cases we want to disable default connection pooling of http client e.g. in case when your application is using ThreadContextClassLoader so statically managed http connection pool will not help instead it will take the pool some time to remove its single connection because its hoping that someone else will try to reuse it. Turn-off the pool, otherwise your http Server will have more unused sockets opened than required for more duration.

Note that close() method does not close underlying http connection instead it’s responsibility of connection manager to close or reuse in releaseConnection().

Use org.apache.commons.httpclient.SimpleHttpConnectionManager which physically closes http connection on close().

HttpClient client = new HttpClient(new SimpleHttpConnectionManager(true));

Apache XML RPC

XML RPC
In one of my projects I used Apache commons xml rpc library. I faced some issues that I would like to discuss and provide solutions that can be helpful to others.

1- Date format which is ISO 8601 as mandated by Xml RPC Specification. But since ISO 8601 does not specify one concrete format so there are confusions in implementations by clients/servers reference http://www.cookcomputing.com/blog/archives/000009.html.

In my case xml rpc server was using yyyyMMdd'T'HH:mm:ssZ, so needed to create a CustomFormat class like:

class CustomTypeFactory extends TypeFactoryImpl {
public CustomTypeFactory(XmlRpcController pController) {
super(pController);
}

private static final String ISO_FORMAT = "yyyyMMdd'T'HH:mm:ssZ";

public TypeSerializer getSerializer(XmlRpcStreamConfig pConfig,
Object pObject) throws SAXException {
if (pObject instanceof Date) {
return new DateSerializer(new SimpleDateFormat(ISO_FORMAT));
} else {
return super.getSerializer(pConfig, pObject);
}
}
}

And on org.apache.xmlrpc.client.XmlRpcClient:
client.setTypeFactory(new CustomTypeFactory(client));

2- Various transport factories (LiteHttp, SunTransport,CommonsTransport) provided with apache xml rpc library have trade-offs. Lets read my misery story step by step:
2.1. I first used SunTransport which is the default but every other day or so I found application hanged while communicating over with xml rpc server (Ctrl+Break was not much helpful).
2.2. I then moved to LiteHttp but the same behavior continued.
2.3. I then tried CommonsTransport which used apache commons http client behind the scene. But un-understandably commons client tried reaching internet to download the xml rpc schema which was mentioned in rpc server’s response. Since server’s response was not under my control and commons client did not provide any way to disable schema validation. I had to quit.
2.4- I then went on to studying XmlRpcClient code and JDK’s default http implementation. Notably I found that in JDK 1.5 reply time out can be set on URLConnection and this feature was not present in JDK 1.4. This feature was added to avoid application hanging, while reading from sockets blocked in deadlock, which is very common in distributed environment with firewalls and network glitches etc. You would observe the same in case of JDBC API which provides similar bounded blocking I/O. XmlRpcClient was not utilizing this feature instead it had same implementation of sendRequest() in base class XmlRpcSunHttpTransport for both JDK 1.5 and 1.4. So, here you go

Override sendRequest() in org.apache.xmlrpc.client. XmlRpcSun15HttpTransportFactory and enable bounded blocking read.

public Object sendRequest(XmlRpcRequest pRequest) throws XmlRpcException {
httpConfig = (XmlRpcHttpClientConfig)pRequest.getConfig();
try {
final URLConnection c =
conn = newURLConnection(httpConfig.getServerURL());
c.setUseCaches(false);
c.setDoInput(true);
c.setDoOutput(true);
//Must be used with JDK 1.5
c.setReadTimeout(httpConfig.getReplyTimeout());
c.setConnectTimeout(httpConfig.getConnectionTimeout());
} catch (IOException e) {
throw new XmlRpcException("Failed to create URLConnection: " +
e.getMessage(), e);
}
return super.sendRequest(pRequest);
}

For new ones here is the code to use apache xml rpc as a client.

private XmlRpcClient client = new XmlRpcClient();
private XmlRpcClientConfigImpl config = new XmlRpcClientConfigImpl();
config.setConnectionTimeout(CONNECTION_TIMEOUT);
config.setReplyTimeout(REPLY_TIMEOUT);
config.setBasicEncoding(null); //UTF-8
config.setBasicUserName(getUser());
config.setBasicPassword(getPassword());
config.setAuthScopeRealm(getRealm());
config.setUserAgent(getUserAgent());
client.setConfig(config);
client.setTypeFactory(new CustomTypeFactory(client));