Tuesday, February 25, 2014

WAS Admin Console login error: ExceptionInInitializerError

Issue: Attempting to log into the Administration Console on my local WebSphere 7 server, I received a java.lang.ExceptionInInitializerError error message. This was caused by ClassNotFoundException: org.apache.commons.logging.impl.Log4JLogger.

Resolution: I added the commons-logging.jar to a WAS directory.

More Details:
IDE + Server: Rational Application Developer (RAD)(based on Eclipse), with WebSphere Application Server (WAS) 7.
Action Attempted: Right-click on running server, select Administration > Run Administration Console, then log in if needed. I even removed my application (Add/Remove) from the server, but was still getting the error after logging in.

Error Message:
Error Page Exception
SRVE0260E: The server cannot use the error page specified for your application to handle the Original Exception printed below.

Original Exception: 
Error Message: java.lang.Exception: java.lang.ExceptionInInitializerError
Error Code: 500
Target Servlet: action
Error Stack: 
java.lang.Exception: java.lang.ExceptionInInitializerError 
     at com.ibm.ws.webcontainer.servlet.ServletWrapper.loadServlet(ServletWrapper.java:1987) 
     at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:731) 
     at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:503) 
     at com.ibm.ws.webcontainer.servlet.ServletWrapperImpl.handleRequest(ServletWrapperImpl.java:181) 
     at com.ibm.ws.webcontainer.webapp.WebAppRequestDispatcher.forward(WebAppRequestDispatcher.java:372) 
     at com.ibm.ws.webcontainer.servlet.FilterProxyServlet.dispatch(FilterProxyServlet.java:88) 
     at com.ibm.ws.webcontainer.servlet.FilterProxyServlet.service(FilterProxyServlet.java:62) 
     at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1658) 
     at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1598) 
     at com.ibm.ws.webcontainer.filter.WebAppFilterChain.doFilter(WebAppFilterChain.java:149) 
     at com.ibm.ws.console.core.servlet.WSCUrlFilter.setUpCommandAssistence(WSCUrlFilter.java:961) 
     at com.ibm.ws.console.core.servlet.WSCUrlFilter.continueStoringTaskState(WSCUrlFilter.java:500) 
     at com.ibm.ws.console.core.servlet.WSCUrlFilter.doFilter(WSCUrlFilter.java:321) 
     at com.ibm.ws.webcontainer.filter.FilterInstanceWrapper.doFilter(FilterInstanceWrapper.java:190) 
     at com.ibm.ws.webcontainer.filter.WebAppFilterChain.doFilter(WebAppFilterChain.java:125) 
     at com.ibm.ws.webcontainer.filter.WebAppFilterChain._doFilter(WebAppFilterChain.java:80) 
     at com.ibm.ws.webcontainer.filter.WebAppFilterManager.doFilter(WebAppFilterManager.java:908) 
     at com.ibm.ws.webcontainer.filter.WebAppFilterManager.invokeFilters(WebAppFilterManager.java:997) 
     at com.ibm.ws.webcontainer.extension.DefaultExtensionProcessor.invokeFilters(DefaultExtensionProcessor.java:1078) 
     at com.ibm.ws.webcontainer.extension.DefaultExtensionProcessor.handleRequest(DefaultExtensionProcessor.java:775) 
     at com.ibm.ws.webcontainer.webapp.WebApp.handleRequest(WebApp.java:3954) 
     at com.ibm.ws.webcontainer.webapp.WebGroup.handleRequest(WebGroup.java:276) 
     at com.ibm.ws.webcontainer.WebContainer.handleRequest(WebContainer.java:942) 
     at com.ibm.ws.webcontainer.WSWebContainer.handleRequest(WSWebContainer.java:1592) 
     at com.ibm.ws.webcontainer.channel.WCChannelLink.ready(WCChannelLink.java:186) 
     at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleDiscrimination(HttpInboundLink.java:453) 
     at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleNewRequest(HttpInboundLink.java:515) 
     at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.processRequest(HttpInboundLink.java:306) 
     at com.ibm.ws.http.channel.inbound.impl.HttpICLReadCallback.complete(HttpICLReadCallback.java:83) 
     at com.ibm.ws.ssl.channel.impl.SSLReadServiceContext$SSLReadCompletedCallback.complete(SSLReadServiceContext.java:1784) 
     at com.ibm.ws.tcp.channel.impl.AioReadCompletionListener.futureCompleted(AioReadCompletionListener.java:165) 
     at com.ibm.io.async.AbstractAsyncFuture.invokeCallback(AbstractAsyncFuture.java:217) 
     at com.ibm.io.async.AsyncChannelFuture.fireCompletionActions(AsyncChannelFuture.java:161) 
     at com.ibm.io.async.AsyncFuture.completed(AsyncFuture.java:138) 
     at com.ibm.io.async.ResultHandler.complete(ResultHandler.java:204) 
     at com.ibm.io.async.ResultHandler.runEventProcessingLoop(ResultHandler.java:775) 
     at com.ibm.io.async.ResultHandler$2.run(ResultHandler.java:905) 
     at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:1646) 
     Caused by: java.lang.ExceptionInInitializerError 
     at java.lang.J9VMInternals.initialize(J9VMInternals.java:222) 
     at java.lang.Class.forNameImpl(Native Method) 
     at java.lang.Class.forName(Class.java:217) 
     at java.beans.Beans.instantiate(Beans.java:189) 
     at java.beans.Beans.instantiate(Beans.java:80) 
     at com.ibm.ws.webcontainer.servlet.ServletWrapper$1.run(ServletWrapper.java:1918) 
     at com.ibm.ws.security.util.AccessController.doPrivileged(AccessController.java:118) 
     at com.ibm.ws.webcontainer.servlet.ServletWrapper.loadServlet(ServletWrapper.java:1909) 
     ... 37 more 
     Caused by: org.apache.commons.logging.LogConfigurationException: org.apache.commons.logging.LogConfigurationException: java.lang.ClassNotFoundException: org.apache.commons.logging.impl.Log4JLogger 
     at org.apache.commons.logging.impl.LogFactoryImpl.newInstance(LogFactoryImpl.java:532) 
     at org.apache.commons.logging.impl.LogFactoryImpl.getInstance(LogFactoryImpl.java:272) 
     at org.apache.commons.logging.impl.LogFactoryImpl.getInstance(LogFactoryImpl.java:246) 
     at org.apache.commons.logging.LogFactory.getLog(LogFactory.java:395) 
     at org.apache.struts.action.ActionServlet.(Unknown Source) 
     at java.lang.J9VMInternals.initializeImpl(Native Method) 
     at java.lang.J9VMInternals.initialize(J9VMInternals.java:200) 
     ... 44 more 
     Caused by: org.apache.commons.logging.LogConfigurationException: java.lang.ClassNotFoundException: org.apache.commons.logging.impl.Log4JLogger 
     at org.apache.commons.logging.impl.LogFactoryImpl.getLogConstructor(LogFactoryImpl.java:416) 
     at org.apache.commons.logging.impl.LogFactoryImpl.newInstance(LogFactoryImpl.java:525) 
     ... 50 more 
     Caused by: java.lang.ClassNotFoundException: org.apache.commons.logging.impl.Log4JLogger 
     at java.lang.Class.forName(Class.java:184) 
     at org.apache.commons.logging.impl.LogFactoryImpl$1.run(LogFactoryImpl.java:466) 
     at java.security.AccessController.doPrivileged(AccessController.java:228) 
     at org.apache.commons.logging.impl.LogFactoryImpl.loadClass(LogFactoryImpl.java:454) 
     at org.apache.commons.logging.impl.LogFactoryImpl.getLogConstructor(LogFactoryImpl.java:406) 
     ... 51 more 

So the key is, WAS seems to be looking for Log4JLogger class. A quick search shows that class is in the commons-logging.jar file. My Java application compiles and runs fine, but for some reason WAS seems to need it and cannot find it.

I looked at the WAS Console output after startup, and saw three entries that could possibly solve my problem:
  • ws.ext.dirs
  • Classpath
  • Java Library path
The Java Library path pointed mostly to /bin/ directories, not exactly a source of jar files.
Classpath pointed to a few specific jars and application-specific property folders.
But ws.ext.dirs seemed to point to libs and classes. Here was my entry, with 'C:\IBMRAD8' being the location of my RAD8 install.
ws.ext.dirs = 
C:\IBMRAD8\runtimes\base_v7/java/lib;
C:\dev\servers\MyAppServer/classes;
C:\IBMRAD8\runtimes\base_v7/classes;
C:\IBMRAD8\runtimes\base_v7/lib;
C:\IBMRAD8\runtimes\base_v7/installedChannels;
C:\IBMRAD8\runtimes\base_v7/lib/ext;
C:\IBMRAD8\runtimes\base_v7/web/help;
C:\IBMRAD8\runtimes\base_v7/deploytool/itp/plugins/com.ibm.etools.ejbdeploy/runtime

Final Resolution:
Adding commons-logging.jar in any of these folders would probably have done the trick. For me, '/base_v7/lib/ext' seemed to make the most sense, and since it was empty, should not affect anything else. I added the jar file there, restarted my WAS server, and successfully logged into the Admin Console.

Tuesday, October 11, 2011

Sample Ant Builds

Below are two Ant builds for Java Web JEE projects, using default Eclipse folder structure. Each copies some files that need to be different in the Test vs. Prod build. These were run using Ant 1.8. I'm not indicating these use "best practices," just some that worked for me.

Ant Build.xml One

<project name="myproject" default="dist" basedir=".">

<property name="project.name" value="MyProject" />
<property name="dist.dir" location="dist" />
<property name="dist.prod.dir" location="${dist.dir}/prod" />
<property name="dist.test.dir" location="${dist.dir}/test" />
<property name="conf.prod" location="conf/prod" />
<property name="conf.test" location="conf/test" />
<property name="web.dir" location="WebContent" />
<property name="web.lib" location="${web.dir}/WEB-INF/lib" />
<property name="web.script" location="${web.dir}/scripts" />

<path id="classpath">
<pathelement location="${web.lib}/jstl.jar"></pathelement>
<pathelement location="${web.lib}/standard.jar"></pathelement>
</path>

<target name="dist">
<tstamp />
<echo message="${ant.project.name}: ${ant.file}" />
<delete dir="${dist.dir}"/>
<mkdir dir="${dist.test.dir}"/>
<mkdir dir="${dist.prod.dir}"/>

<echo>Building PROD war file</echo>
<copy file="${conf.prod}/script/validate.js" tofile="${web.script}/validate.js"
overwrite="true" />
<copy file="${conf.prod}/WEB-INF/web.xml" tofile="${web.dir}/WEB-INF/web.xml"
overwrite="true" />
<war destfile="${dist.prod.dir}\${project.name}.war" webxml="${web.dir}\WEB-INF\web.xml">
<fileset dir="${web.dir}" />
</war>

<echo>Building TEST war file</echo>
<copy file="${conf.test}/script/validate.js" tofile="${web.script}/validate.js"
overwrite="true" />
<copy file="${conf.test}/WEB-INF/web.xml" tofile="${web.dir}/WEB-INF/web.xml"
overwrite="true" />
<war destfile="${dist.test.dir}\${project.name}.war" webxml="${web.dir}\WEB-INF\web.xml">
<fileset dir="${web.dir}" />
</war>
<echo>${ant.project.name} build complete</echo>
</target>

</project>


Ant Build.xml Two

<?xml version = '1.0' encoding = 'windows-1252'?>

<project name="myproject" default="make" basedir=".">

<!--Set the output directories-->
<property name="compile.outdir" value="build/classes"/>
<property name="dist.outdir" value="dist"/>

<!-- Project directories -->
<property name="src.dir" value="src"/>
<property name="web.dir" value="WebContent"/>
<property name="web.lib.dir" value="WebContent/WEB-INF/lib"/>
<property name="conf.dir" value="conf"/>
<property name="test.dir" value="test"/>
<property name="prod.dir" value="prod"/>

<!-- Project configuration -->
<property name="debuglevel" value="source,lines,vars"/>
<property name="target" value="1.6"/>
<property name="source" value="1.6"/>

<!-- Web application names -->
<property name="webapp.name.test" value="myproject"/>
<property name="webapp.name.prod" value="myproject"/>

<!-- Create a fileset of the webapp libraries -->
<fileset dir="${web.lib.dir}" id="webapp.lib" />

<!-- Create a fileset of the webapp libraries -->
<fileset dir="external.lib/" id="external.lib" />

<!--Set the classpath-->
<path id="classpath">
<pathelement location="${compile.outdir}"/>
<fileset refid="webapp.lib" />
<fileset refid="external.lib" />
</path>

<!--Set the source path-->
<path id="srcpath">
<pathelement location="${src.dir}"/>
</path>

<target name="init">
<tstamp/>
</target>

<target name="compile" depends="init">
<mkdir dir="${compile.outdir}"/>
<echo>My Project compile</echo>
<!--Compile Java source files-->
<javac debug="true" debuglevel="${debuglevel}" destdir="${compile.outdir}" source="${source}" target="${target}" includeantruntime="false">
<classpath refid="classpath"/>
<src refid="srcpath"/>
</javac>
<!--Copy files to output directory-->
<copy file="${src.dir}/com/mysite/myproject/dbutil/Database.properties"
tofile="${compile.outdir}/com/mysite/myproject/dbutil/Database.properties"/>
<copy file="${src.dir}/messages.properties" tofile="${compile.outdir}/messages.properties"/>
<copy file="${src.dir}/log4j.xml" tofile="${compile.outdir}/log4j.xml"/>
<copy file="${src.dir}/log4j.dtd" tofile="${compile.outdir}/log4j.dtd"/>
</target>

<target name="clean">
<!--Delete output directories-->
<delete dir="${compile.outdir}"/>
</target>

<target depends="clean" name="cleanall">
<delete dir="${dist.outdir}"/>
</target>

<target name="make" depends="compile"/>

<target name="rebuild" depends="clean,compile"/>

<macrodef name="build-war">
<attribute name="dist.conf" />
<attribute name="webapp.name" />
<sequential>
<!-- Files differ between Test and Prod in conf dir: -->
<!-- Database.properties, log4j.xml, web.xml, logon.jsp -->
<mkdir dir="${dist.outdir}/@{dist.conf}" />
<mkdir dir="${dist.outdir}/@{dist.conf}/classes" />
<copy todir="${dist.outdir}/@{dist.conf}/classes">
<fileset dir="${compile.outdir}" />
</copy>
<copy todir="${dist.outdir}/@{dist.conf}/classes" overwrite="true">
<fileset dir="${conf.dir}/@{dist.conf}/classes" />
</copy>
<copy file="${conf.dir}/@{dist.conf}/WebContent/signon.jsp"
todir="${web.dir}" overwrite="true" >
</copy>

<war destfile="${dist.outdir}/@{dist.conf}/@{webapp.name}.war" webxml="${conf.dir}/@{dist.conf}/WebContent/WEB-INF/web.xml">
<fileset dir="${web.dir}/" excludes="test*.jsp,/workqueue/reports/**/*.csv"/>
<classes dir="${dist.outdir}/@{dist.conf}/classes" excludes="" />
</war>

<delete dir="${dist.outdir}/@{dist.conf}/classes" />
</sequential>
</macrodef>

<target name="dist" depends="cleanall,rebuild">
<build-war dist.conf="${prod.dir}" webapp.name="${webapp.name.prod}" />
<build-war dist.conf="${test.dir}" webapp.name="${webapp.name.test}" />
</target>
</project>

Monday, October 10, 2011

Favorite Free Development Utilities

Here is a list of software that I've found helpful for various development tasks. Best of all, they are all free.

Text Editor: Notepad++ - if you are still using Window's default Notepad or Wordpad, you have got to get this. Text formatting and tabbed documents are two of the many features.

File Compare: ExamDiff - does a better job than WinMerge when comparing two files.

Folder Compare: WinMerge - good for comparing folder tree structure, seems to generate a lot of false hits when just comparing two files.

Screen Capture: PrintScreen by Gadwin - drag a rectangle around anything on your screen, press enter and it's on your clipboard

Quick image editing: Paint.NET - especially good if you are relying on Window's default Paint.

Load Testing: JMeter - basic web load testing

Web Service Testing: soapUI - create test XML, send it to a SOAP web service, see the XML response

Tuesday, September 27, 2011

Connecting Grails to an Oracle Database

These steps used Grails 1.3.4 and Oracle 11g.

datasource.groovy

dataSource {
pooled = true
}
hibernate {
cache.use_second_level_cache = true
cache.use_query_cache = true
cache.provider_class = 'net.sf.ehcache.hibernate.EhCacheProvider'
}
// environment specific settings
environments {
development {
dataSource {
driverClassName = "org.hsqldb.jdbcDriver"
username = "sa"
password = ""
dbCreate = "create-drop" // one of 'create', 'create-drop','update', or can be left out
/* create-drop - Drop and re-create the database when Grails is run
* create - Create the database if it doesn't exist, but don't modify it if it does. DELETES existing data.
* update - Create the database if it doesn't exist, and modify it if it does exist
*/
url = "jdbc:hsqldb:file:devDB;shutdown=true"
//loggingSql = true
}
}

test {
dataSource {
driverClassName = "oracle.jdbc.driver.OracleDriver"
username = "APP_USER"
password = "APP_PASSWORD"
//dbCreate = "update" LEAVE COMMENTED OUT - NOT NEEDED
url = "jdbc:oracle:thin:@servername:1521:schema"
dialect="org.hibernate.dialect.Oracle10gDialect"
//loggingSql = true
}
hibernate {
default_schema="schema"
}
}
production {
// same as test
}
}


Set up a sequence Grails can use and tell this Grails domain object which tablename and sequence to use.
DomainObject.groovy

static mapping = {
table 'APP_TABLENAME'
id generator:'sequence',params:[sequence:'APP_SEQ']
}


Here is the SQL used to create the table.

CREATE TABLE schema.APP_TABLENAME
(
ID NUMBER(10,0) NOT NULL,
FIELD1 VARCHAR2(100 CHAR) NOT NULL,
// MORE COLUMNS
LAST_UPDATED TIMESTAMP DEFAULT SYSDATE NOT NULL,
LAST_UPDATE_IP VARCHAR2(15 CHAR),
LAST_UPDATE_USER VARCHAR2(10 CHAR) DEFAULT 'import' NOT NULL,
DATE_CREATED TIMESTAMP DEFAULT SYSDATE NOT NULL,
DATE_CREATED_USER VARCHAR2(10 CHAR) DEFAULT 'import' NOT NULL ,
VERSION NUMBER(19,0)
)
TABLESPACE APP_DATA
;

ALTER TABLE schema.APP_TABLENAME ADD
CONSTRAINT APP_TABLENAME_PK PRIMARY KEY (ID)
;

CREATE SEQUENCE schema.APP_SEQ;

CREATE OR REPLACE TRIGGER schema.APP_TABLENAME_TRG
BEFORE INSERT ON schema.APP_TABLENAME
FOR EACH ROW
WHEN (new.id IS NULL)
BEGIN
SELECT APP_SEQ.NEXTVAL INTO :new.id FROM dual;
END;

Populate JSP with messages from a properties file

I had a series of JSP pages that used certain values, questions or messages. Some of these were long, and potentially subject to change by the business group.

To eliminate typing the messages in multiple places, and potentially miss one should it change in the future, I put them all in a properties file, then loaded them to the JSP that way. Here's my setup:

1) Create the messages.properties file in the Eclipse project folder 'WebContent > WEB-INF > classes'. Entries are in the 'title=Page Title' format.

2) Create a new JSP file, messages.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
<fmt:bundle basename="messages">
<fmt:message key="title" var="title"/>
</fmt:bundle>


3) At the top of the JSP you wish to use the messages, just include the 'messages.jsp' file. Then reference them like any other variable.

<%@ include file="messages.jsp" %> // ADDED HERE
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>${title}</title> // USED HERE

Masking numeric values with JQuery

The JQuery plugin Masked Input is great if you want to auto-format a numeric field. for example, you can add '/' in a date field, '-' in a phone field, etc. Then the user just types in the numbers, and the field is automatically formatted.

HTML setup

<script language="javascript" type='text/javascript' src='scripts/jquery-1.6.1.min.js'></script>
<script language="javascript" type='text/javascript' src='scripts/jquery.maskedinput-1.3.min.js'></script>
<script language="javascript" type="text/javascript">
jQuery(function($){
$("#birthDate").mask("99/99/9999");
$("#phone").mask("(999) 999-9999");
$("#zip").mask("99999");
});
</script>
</head>

Custom JSTL tags

To add custom tags to your JSP page, create the tag file and put it in the Java project folder WebContent > WEB-INF > tags

In this example, we create a tag that can be used to escape user-inputted values for display on the next page.

escape.tld
<?xml version="1.0" encoding="ISO-8859-1" ?>
<taglib xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd"
version="2.0">

<description>
calls StringEscapeUtils.escapeHtml for value
</description>
<tlib-version>1.0</tlib-version>
<short-name>escape</short-name>
<uri>escape</uri>
<function>
<name>esc</name>
<function-class>org.apache.commons.lang.StringEscapeUtils</function-class>
<function-signature>
java.lang.String escapeHtml( java.lang.String )
</function-signature>
</function>
</taglib>


In the JSP page

<%@ taglib uri="escape" prefix="es" %>

${es:esc(param.home)}