Tuesday, December 22, 2009

WebLogic Server : Flush the Application Cache

" On our system, what I normally do is to stop the server with the cache that needs to be flushed, then delete the tmp and cache directories of the server "

- Java Ranch Forum Post

Weblogic server maintains certain "caches" in tmp and cache folders. The caches can sometimes prove to be nuisance - especially, the tmp folder.

You can usually find the tmp folder for your application under :-

$DOMAIN_HOME/tmp/_WL_user/myApplication/
I recently ran into this issue and it gave me a couple of sleepless nights.

I had deployed my Application and started it. I then hit the URL in my browser and promptly received an error, which indicated that my cocktail of JAR files were sour and some libraries did not like the other ones.

During the next iteration of development, decided to use newer versions of a particular library. I deleted all the old libraries, provided a "gold" set of libraries ( that were certified on the vendor's website ) and then re-deployed my application.

However, I still noticed that same error. I was baffled as I was *certain* that I had removed all the old libraries.

First, I decided to investigate which JAR file was contributing the class. I retorted to good ol' Java Reflection for this - I just put this neat little piece of code in my Servlet :-

.class.getProtectionDomain().getCodeSource().getLocation();


I printed this using a simple statement and ensured that the output gets imprinted in the Server's Domain Log.

Alright, I now redeployed my application and when I invoked the Servlet, I saw this in my log file :-

$DOMAIN_HOME/servers/tmp/_WL_user/myApplication/ub48zr/war/WEB-INF/lib/myOldJARFile .jar

Bingo ! I promptly cleared the "cache" and redeployed the application. I re-invoked my Servlet and it works fine !!

I have modified my build.xml to include this minor operation - to clear the contents of the _WL_user folder and then undeploy / redeploy.



Weblogic Server : Quick EAR Deployment using WLST

" The WebLogic Scripting Tool (WLST) is a command-line scripting environment that you can use to create, manage, and monitor WebLogic Server domains. "


You can use WLST to quickly deploy an Application EAR File in a Weblogic Server.

What do you need ?
  • the EAR file ( uploaded to a directory in the target WebLogic Server )
  • A simple WLST script
  • Credentials for the Weblogic Server ( preferrably, the weblogic user ).
How do we do it ?
  • Upload your EAR file to a directory in the target Weblogic Server
/app/home/myUser/
  • Write a simple WLST Script to do your work and save it as "myApp.py"

print '*** WEBLOGIC : START ***'

print 'connecting to admin server....'
connect( 'weblogic', 'weblogic', 't3://localhost:8001', adminServerName='AdminServer' )

print 'stopping and undeploying ....'

stopApplication('myApplication')
undeploy('myApplication')

print 'deploying....'

deploy('myApplication', '/app/home/myUser/myApplication.ear', targets='AdminServer')
startApplication('FoundationSearch')

print 'disconnecting from admin server....'
disconnect()
exit()

print '*** WEBLOGIC : STOP ***'
  • Open a Terminal Window / Command Prompt
  • Run the setDomainEnv.sh ( or setDomainEnv.bat ) script to set the required environment variables.
  • Switch to the /common/bin directory of your Weblogic Server
  • run the wlst.sh / wlst.bat script to open the Scripting Environment.
  • Execute your WLST Script :-
execfile('myApp.py')


That's it ! You can now stop an application, undeloy it, deploy it & start an application with a simple script !

You need to watch out for two small things :-

  • The WAR File and some of the classes / libs are "cached" under the /tmp/_WL_user/myApplication/ folder. You may need to delete them before you execute your script.
  • Make sure the EAR file is available in a folder in the same node as the Server.

Friday, June 19, 2009

Oracle BPEL and Weblogic and Java - JAR Hell

" JAR hell is a term used to describe all the various ways in which the classloading process can end up not working. "

- JAR Hell ( Wikipedia )

Avijeet , Raghu and myself - we are working on a challenging customer engagement and the environment has an Oracle BPEL 10.1.3.4 Server running off an Weblogic 9.2 Server. We recently encountered a scenario where we had to have a Java Client call a BPEL process deployed in this environment.

We used to regular boiler-plate Java BPEL Client code that you can get in the documentation, blogs, etc.

You can find a good example on Charles Piazza's SOA Blog.

However, to our chagrin, we noticed that the code always returned an opaque error :-

Exception in thread "main" java.lang.Exception:
Failed to create "ejb/collaxa/system/FinderBean" bean; exception reported is: "javax.naming.CommunicationException [Root exception is java.rmi.ConnectIOException:
error during JRMP connection establishment; nested exception is:
java.io.EOFException]
at weblogic.jrmp.Context.lookup(Context.java:189)
at weblogic.jrmp.Context.lookup(Context.java:195)
at javax.naming.InitialContext.lookup(InitialContext.java:351)
at com.oracle.bpel.client.util.BeanRegistry.lookupFinderBean(BeanRegistry.java:337)
at com.oracle.bpel.client.Locator.getFinder(Locator.java:956)
at com.oracle.bpel.client.Locator.listInstances(Locator.java:585)
at com.oracle.bpel.client.Locator.listInstances(Locator.java:554)

We pciked our brains on this for almost two days - until, suddenly, it hit us !

It was a classic case of JAR hell.

I had included all the JAR libraries of Oracle BPEL 10.1.3.4 and Weblogic 9.2 - for some strange reason, a few libraries in these two sets didn't like each other and this disgust resulted in the opaque "bean" exception.

Avijeet pointed this out & we both painstakingly removed the Weblogic Jar's one-by-one, until we noticed that we only required two sets of JARs to run the Java Class :-
  1. All the Oracle BPEL 10.1.3.4 Libraries.
  2. Only the weblogic.jar from Weblogic 9.2
Cool ! So, now it works and we can celebrate another victory against JAR hell !

Moral of the storey : Be very very careful with the JARs you use !


Sunday, February 22, 2009

Recursive Java Decompiler by Adarsh

" Often we encounter situations where the only solution to a certain Java problem is to decompile the contents of an entire JAR file, edit the resulting the source, rebuild and repackage before using. "


I found myself in this situation today & was struggling with CAVAJ and JAD to recursively generate Java classes present in an EAR file. I initially tried my hand at writing my own DOS Script to do this, but soon found that it takes a lot of time, patience & effort to write a script that does what I need. And time, unfortuantely, is in very limited supply today !

I Googled around looking for solutions & landed on this post by Adarsh. The Recursive Decompiler provided by Adarsh works like a charm *& saved a lot of time !

Thanks a lot Adarsh !

Monday, February 09, 2009

DWR Hello World !

" DWR is a Java library that enables Java on the server and JavaScript in a browser to interact and call each other as simply as possible. "

- Direct Web Remoting ( DwR )

I was snooping around for an AJAX library that I can use in one of my projects & narrowed down to DWR, after reading a lot of rave reviews about it. I was looking out for some AJAX library that'll allow me to call the methods in my Java classes with minimum effort.

I decided to take it for a test drive & check out the features. The usual sources were the DWR Documentation and Google.

I don't want to duplicate the good & decent documentation available for DWR at the "Get Started" page.

At a high level, I would like to just summarize the steps involved ( with the mistakes I made highlighted ) :-
  • Put dwr.jar in your Project's lib.
  • Put the Commons Logging Jar in your Projects's lib. ( Dwr uses Apache Commons Logging )
  • Add the configuration settings in your web.xml for the DWR Servlet.
  • Add the debugging parameters for the DWR Servlet during the development phase.
  • Add the dwr.xml under WEB-INF and configure it to expose your Java Classes.
  • Add the converters in dwr.xml to ensure the conversion of Java POJOs to JavaScript Objects & vice versa.
  • Include the reference to all the JavaScript libraries required in your JSPs.
Overall, I am impressed with this & I am going ahead with my implementation using DWR.

Tuesday, February 03, 2009

WebLogic Server 10 : Deployment : Error 149003

" WebLogic Deployer:149003 Unable to access application source information "

You might bump into this error during deployment. I just noticed that someone was struggling with this error & had reported this on the OTN Forums.

The Stack Trace for the error usually looks like this :-

Error is: 'weblogic.management.DeploymentException:
[Deployer:149003]Unable to access application source information in
'/home/bea/bea/user_projects/domains/myDomain/servers/myServer/stage
app/app.war' for application 'roller'. The specific error is:
[Deployer:149158]No application files exist at
'/home/bea/bea/user_projects/domains/my/servers/myServer/stage
appapp.war'
The error occurs when the WebLogic Server is unable to locate the EAR file. The common causes for the EAR file could be :-

  • ANT Deployment : The EAR file was not uploaded to a directory that the server can access.
  • Console Deployment: You might need to look at "Source Availablity" [ Copy this application onto every target for me ], if you wish to copy the application to all the managed servers in a Cluster.
The error vanishes once the server can access the EAR file.

Spring LDAP caches user credentials

" Spring-LDAP caches environment properties by default "



I was facing this rather peculiar problem of User Credentials getting cached by Spring LDAP. I discovered this accidentally ( absent-minded, to be precise :) ) . I changed the password of a User in my ApacheDS but tried to login with the old password - and guess what ? it worked !

Well, I looked at the first place I would go to in these situations - the Spring-LDAP Community Forums.

I noticed that the problem has already been discussed in one of the threads.

The solution suggested in the thread is use the setCacheEnvironmentProperties() method in the AbstractContectSource class & set it to false. The Java doc for the API seems to explain this more :-

Set whether environment properties should be cached between requsts for anonymous environment. Default is true; setting this property to false causes the environment Hashmap to be rebuilt from the current property settings of this instance between each request for an anonymous environment.

Well, just one of those queer things in the fascinating Spring LDAP API.

JSF Managed Bean in a Servlet Filter

" How do you get a JSF Managed Bean, with session scope, in a Servlet Filter ? "

- Two bewildered comrades

The question posed above can be reworded in a simpler way :-

" Which came first, the Chicken or the Egg ? "

- A timeless paradox

We just hit this problem of accessing a JSF managed bean from a Servlet Filter. The requirement is quite simple - Oracle Single Sign On authenticates a user, passes on useful information about the user in the request headers & this information needs be passed on downstream to a Managed Bean for furthe consumption.

However, try as much as we can, we only hit the simple NullPointerException, which quaintly informs us that we aren't getting the FacesContext to proceed further.

A bit of Googling landed us on a post on the Sun Java Forums, where one of the legends of the Java Universe - Craig McClanahan - has suggested that this might not be possible. He has eloquently described how the Servlet Filters get triggered much before the Servlets & hence, the FacesContext doesn't stand a chance of getting initialized unless the flow hits the FacesServlet.

However, on further Googling, we hit upon this curious post on the Thougths About blog that offers an amazing alternative! We tried the code posted on the blog and.... it just works !

Thanks a million to the Thougths About blog for shaving off a few precious hours off the already-harried schedule of a couple of developers !

You can also find a very good explanation about the differences between a Filter and a PhaseListener on the same Blog.

Now, it's time for a cup of coffee.....

Wednesday, January 21, 2009

Spring LDAP : My experiments

" Spring LDAP is a Java library for simplifying LDAP operations, based on the pattern of Spring's JdbcTemplate. The framework relieves the user of common chores, such as looking up and closing contexts, looping through results, encoding/decoding values and filters, and more. "

Spring LDAP

I took some time to explore the Spring LDAP library & I am impressed with it. The library aims to make a developer productive by eliminating a lot of plumbing code that one would encounter with plain-vanilla JNDI. I have worked on building an User Management application using JNDI & when I compare it with the facilities provided in Spring LDAP, I defenitely would think twice before coding in regular JNDI.

I created a sample application, by using the principles listed out in the Spring LDAP Reference Documentation & some of the samples I found using my favourite Google.

The steps to use Spring LDAP are quite the same for any Spring application :-

1. Get the Spring LDAP libraries.
2. Configure the applicationContext.xml
3. Write any utility classes you may need.
4. Write the Interface and Implementation class.
5. Write a test harness to see if all these gule together & work ( of course, it will ! :) ).

Let's take it one step at a time...

1. Get the Spring LDAP libraries.

You can get it from the Spring LDAP home page.

After downloading the library, you can unizp it & have a look at the README file. The file usually outlines the dependencies very clearly. In my case, I had to include all these libraries in my project :-
  • spring-ldap-core-tiger-x.x.jar
  • Commons Logging
  • Commons Lang
  • Commons Pool
  • spring-beans
  • spring-core
  • spring-context
  • spring-jdbc
  • spring-tx
  • ldapbp
2. Configure the applicationContext.xml

Here's my applicationContext.xml :-

< ?xml version="1.0" encoding="UTF-8"? >
< !DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd" >
<>

< !-- The Spring LDAP Context Source Configuration. The information provided here is used to create an instance of InitialLdapContext -- >
< id="contextSource" class="org.springframework.ldap.core.support.LdapContextSource">
< name="url" value="ldap://ecmser.idc.oracle.com:389">
< name="base" value="cn=Users,dc=idc,dc=oracle,dc=com">
< name="userDn" value="cn=orcladmin">
< name="password" value="allstate1">
< /bean >

< !-- The Spring LDAP Template executes tcore LDAP functionalities. It requires the Context Source for its operations. -- >
< id="ldapTemplate" class="org.springframework.ldap.core.LdapTemplate">
< ref="contextSource">
< /bean >

< !-- Our User Bean that makes uses of the pre-configured Spring LDAP Template-- >
< id="user" class="com.org.sandeep.dao.impl.UserDAOImpl">
< name="ldapTemplate" ref="ldapTemplate">
< /bean >

< /beans >

3. Write any utility classes you may need.

First, I an interface as a placeholder for some of the constants :-

package com.org.sandeep.util;

public interface UserConstants
{
String FIRST_NAME = "cn";
String LAST_NAME = "sn";
String BLANK = "";
String OBJECT_CLASS = "objectclass";
String PERSON = "person";
}


Next, I wrote my bean class :-

package com.org.sandeep.bean;

public class UserBean
{
private String firstName;
private String lastName;

public UserBean()
{
}

public UserBean(String firstName,String lastName)
{
this.firstName = firstName;
this.lastName = lastName;
}

public void setFirstName(String firstName)
{
this.firstName = firstName;
}

public String getFirstName()
{
return firstName;
}

public void setLastName(String lastName)
{
this.lastName = lastName;
}

public String getLastName()
{
return lastName;
}


public String toString()
{
return firstName + " : "+lastName;
}
}

Finally, I wrote an AttributesMapper class the implements Spring's AttributeMapper interface. To quote from the Spring LDAP Reference Manual :-

An interface used by LdapTemplate for mapping LDAP Attributes to beans. Implementions of this interface perform the actual work of extracting results, but need not worry about exception handling. NamingExceptions will be caught and handled correctly by the LdapTemplate class.

Here's my AttributesMapper class :-

package com.org.sandeep.mapper;

import com.org.sandeep.bean.UserBean;
import com.org.sandeep.util.UserConstants;

import javax.naming.NamingException;
import javax.naming.directory.Attributes;

import org.springframework.ldap.core.AttributesMapper;

public class UserMapper implements AttributesMapper
{
public Object mapFromAttributes(Attributes attributes)
{
UserBean userBean = null;

String firstName = null;
String lastName = null;

try
{
firstName = (String)attributes.get(UserConstants.FIRST_NAME).get();
lastName = (String)attributes.get(UserConstants.LAST_NAME ).get();
}
catch (NamingException objNamingException)
{
objNamingException.printStackTrace();
}

if ( firstName != null || lastName != null )
{
userBean = new UserBean(firstName,lastName);
}

return userBean;
}
}


4. Write the Interface and Implementation class.

First, we need an interface :-

package com.org.sandeep.dao;

import com.org.sandeep.bean.UserBean;

import java.util.List;

public interface UserDAO
{
public List get(UserBean user);
public void add(UserBean user);
public void modify(UserBean user);
public void remove(UserBean user);
}
Next, we need an implementation class that uses the interface :-

package com.org.sandeep.dao.impl;

import com.org.sandeep.bean.UserBean;
import com.org.sandeep.dao.UserDAO;
import com.org.sandeep.mapper.UserMapper;

import com.org.sandeep.util.UserConstants;

import java.util.List;

import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.BasicAttributes;

import org.springframework.ldap.core.DistinguishedName;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.filter.AndFilter;
import org.springframework.ldap.filter.EqualsFilter;


public class UserDAOImpl implements UserDAO
{
private LdapTemplate ldapTemplate;

public UserDAOImpl()
{
}

public void setLdapTemplate(LdapTemplate ldapTemplate)
{
this.ldapTemplate = ldapTemplate;
}

public List get(UserBean user)
{

String firstName = null;
String lastName = null;

AndFilter andFilter = null;

firstName = user.getFirstName();
lastName = user.getLastName();

andFilter = new AndFilter();
andFilter.and(new EqualsFilter(UserConstants.OBJECT_CLASS,UserConstants.PERSON));
andFilter.and(new EqualsFilter(UserConstants.FIRST_NAME,firstName));
andFilter.and(new EqualsFilter(UserConstants.LAST_NAME,lastName));

return ldapTemplate.search(UserConstants.BLANK, andFilter.encode(),new UserMapper());
}

public void add(UserBean user)
{
Attributes userAttributes = null;
BasicAttribute userBasicAttribute = null;
DistinguishedName userDN = null;


userAttributes = new BasicAttributes();
userBasicAttribute = new BasicAttribute(UserConstants.OBJECT_CLASS);

userBasicAttribute.add(UserConstants.PERSON);
userAttributes.put(userBasicAttribute);
userAttributes.put(UserConstants.FIRST_NAME, user.getFirstName());
userAttributes.put(UserConstants.LAST_NAME, user.getLastName());

userDN = new DistinguishedName(UserConstants.BLANK);
userDN.add(UserConstants.FIRST_NAME, user.getFirstName());

ldapTemplate.bind(userDN, null, userAttributes);
}

public void modify(UserBean user)
{
Attributes userAttributes = null;
BasicAttribute userBasicAttribute = null;
DistinguishedName userDN = null;


userAttributes = new BasicAttributes();
userBasicAttribute = new BasicAttribute(UserConstants.OBJECT_CLASS);

userBasicAttribute.add(UserConstants.PERSON);
userAttributes.put(userBasicAttribute);
userAttributes.put(UserConstants.FIRST_NAME, user.getFirstName());
userAttributes.put(UserConstants.LAST_NAME, user.getLastName());

userDN = new DistinguishedName(UserConstants.BLANK);
userDN.add(UserConstants.FIRST_NAME, user.getLastName());

ldapTemplate.rebind(userDN, null, userAttributes);
}

public void remove(UserBean user)
{
DistinguishedName userDN = new DistinguishedName(UserConstants.BLANK);
userDN.add(UserConstants.FIRST_NAME, user.getFirstName());
ldapTemplate.unbind(userDN);
}
}


5. Write a test harness to see if all these gule together & work

Well, we have reached the finish line ! The only remaining step is to see if all these gel together !

Here's my test client :-

package com.org.sandeep.client;

import com.org.sandeep.bean.UserBean;
import com.org.sandeep.dao.UserDAO;

import java.util.List;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.dao.DataAccessException;


public class UserClient
{

public static void main(String[] args)
{
try
{
Resource resource = new ClassPathResource("applicationContext.xml");
BeanFactory factory = new XmlBeanFactory(resource);
UserDAO userDAO = (UserDAO)factory.getBean("user");

UserBean userBean = new UserBean("Sandeep","Seshan");

userDAO.add(userBean);

System.out.println("Done");

List userList = userDAO.get(userBean);

System.out.println("User "+userList);

userDAO.remove(userBean);

System.out.println("Done & Deleted");

}
catch (DataAccessException objDataAccessException )
{
objDataAccessException .printStackTrace();
}
}
}


That's it ! It's that simple !


Monday, January 19, 2009

FlashBack to JDeveloper 10.1.2.2.0

" I want to migrate my application code base from JDeveloper 10.1.3 to 10.1.2 "

One of my colleagues recently faced this problem of moving the source code of a J2EE Application from Jdeveloper 10.1.3 to JDeveloper 10.1.2.

We faced a few issues during the process & here's a partial list of the issues we faced :-

1. Platform Migration Issues

JDeveloper 10.1.2.x makes use of JDK 1.4, whereas JDeveloper 10.1.3.x makes use of JDK 1.5. Hence, the move involves changing Java code to ensure that the code is stripped of all the useful features we are used to in JDK 1.5. E.g: contains() method of java.lang.String, etc.

2. “Error (n, m): identifier OracleJspRuntime not found”

We noticed that we had to manually add the JSP Runtime Library to the new Project in jDeveloper 10.1.2.

Please see one of my previous posts for more information about this problem.

3. Error: JSP files must reside in the server root directory or a subdirectory

We noticed that we had to manually change the HTML Root Directory to the new Project in jDeveloper 10.1.2.

Please see one of my previous posts for more information about this problem.

4. Change XSD references to DTDs

The JDeveloper 10.1.2.x does not recognize references to XSDs in web.xml & other configuration files. Hence, we had to manually change these references to DTDs.

Well, we managed to backport the application after resolving these problems. I would like to hear if there are any other similar experiences.