But its usually quite difficult to establish a proper naming convention, so its far eassier to use an existing naming convention that can be ammended if needed. On java.net a project exists that establishes such a naming convention for J2EE projects, very handy!
Thursday, May 10, 2007
Naming conventions
But its usually quite difficult to establish a proper naming convention, so its far eassier to use an existing naming convention that can be ammended if needed. On java.net a project exists that establishes such a naming convention for J2EE projects, very handy!
Friday, April 20, 2007
Using JConsole
To do so I needed to start eclipse using JDK 5, with the system property
-Dcom.sun.management.jmxremote.Now JConsole is able to connect to the eclipse process and show its memory consumption.
After playing a while with eclipse the OOM exception hapened again, but saidly JConsole has lost its connection, so nothing to see what/.where had happened.
The story continues...
Tuesday, April 03, 2007
Mocking a base class
javax.portlet.GenericPortlet. How can these method calls be mocked?In the unit test implementation an inner class is defined that extends the class under test.
This inner class can then mock any base class method called from the class under test:
public class MyPortletTest extends TestCase {
private PortletContext portletContext = EasyMock.createMock(PortletContext.class);
protected void setUp() throws Exception {
super.setUp();
// Use the inner class derived from the actual CUT that provides
// overrides for the base class methods.
testObject = new TestObject();
}
// Additional methods removed for clarity...
/**
* Need to extend the portlet under test for overriding base class methods.
*/
private class TestObject extends MetaInfoPortlet {
/**
* A mock needs to be returned
*/
@Override
public PortletContext getPortletContext() {
return portletContext;
}
}
}Using this scheme one can override any of the base classes methods used in the class under test (CUT), and provide a mock based implementation.Thursday, March 29, 2007
EasyMock and IllegalStateException
I have been using EasyMock for some time now, and every now and then I stumble over the problem IllegalStateException problem. Sometimes this is caused by not having 'replay'ed the mocks, but now its different. The stack look s like this:
java.lang.IllegalStateException: 2 matchers expected, 1 recorded.This exception is thrown when executing
at org.easymock.internal.ExpectedInvocation.createMissingMatchers(ExpectedInvocation.java:41)
at org.easymock.internal.ExpectedInvocation.(ExpectedInvocation.java:33)
at org.easymock.internal.ExpectedInvocation.(ExpectedInvocation.java:26)
at org.easymock.internal.RecordState.invoke(RecordState.java:64)
at org.easymock.internal.MockInvocationHandler.invoke(MockInvocationHandler.java:24)
at org.easymock.internal.ObjectMethodsFilter.invoke(ObjectMethodsFilter.java:45)
request.setAttribute(MetaInfoPortlet.BEAN_ATTR, EasyMock.anyObject());.So why is this excpetion being thrown at me? The message gives a hint, 2 matchers expected, recorded 1. So it lacks a matcher...
If I now change the code to
request.setAttribute(EasyMock.matches(MetaInfoPortlet.BEAN_ATTR), EasyMock.anyObject());, it works fine. Now why is this? If I change the code to request.setAttribute(MetaInfoPortlet.BEAN_ATTR, "something");, it works as well, but now I get the following:java.lang.AssertionError:So it looks like the you either have to supply your mock with fixed values or you have to supply it with matchers, as it says in EasyMocks documentation: "If you would like to use matchers in a call, you have to specify matchers for all
Unexpected method call setAttribute("bean", {test=Let's see if this tst value comes through?}):
setAttribute("bean", "something"): expected: 1, actual: 0
arguments of the method call."
Bottom line: read the documentation.
Wednesday, March 21, 2007
JSTL and JSP Expression Language used in JSP 2.0
From now on you can use expressions throughout the whole JSP page.
There appeared to be some limitations though, when mixing expressions with tags, you can only use expressions within tag attribute values.
So name is ${your.name}. is perfectly legal, as well as href="${link.url}" />But ${attrName} is not.
When trying to figure this out, I stumbled over several issues before I got the desired output. First you must declare your application as a 2.4 webapp using the following declaration:
<web-app 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 web-app_2_4.xsd" version="2.4" />
When using the JSTL taglibrary, you must be aware that the taglib url is different, jsp is added prior to jstl within the URL.
For 2.3 webapps you should use taglib
<%@taglib uri="http://java.sun.com/jstl/core" prefix="c"%> while for 2.4 webapps you use <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> />Using Performancing when blogging
I think this can become a very handy tool that eases posting to my blog!
Some interesting features are the use of a rich text editor.
See ya next time.
Thursday, November 30, 2006
JCR Portlet demo
Currently I am working on a demo for connecting a portlet application to a JCR repository.
The portlet application consists of 2 portlets, one show a table of contents, and the other shows the selected content item.
The first problem I stumble into after creating a web project using maven 2, was that the war file created contained the portlet-api.jar causing a ClassCastException in pluto.
Adding a
Wednesday, November 23, 2005
Parsing an xml file without having access to the associated DTD
I have finally found the solution to my problem...
But lets start from the begin, well somewhat from the beginning.
I needed to change the logfile location as defined in a log4j.xml file from code.
So I started of with a DOM based solution using JDK1.4 features to parse the log4j.xml file, using jaxen to select nodes based on XPath expressions and then updating the found Node with the given value.
But... parsing the log4j.xml file failed because my application could not find the log4j.dtd file.
Removing the log4j.dtd file from the log4j.xml file solved the parsing problem but caused another problem, log4j would not accept the file anymore.
Also setting the validating flag to false did not solve the problem.
After searching the internet and trying several options, I found in the JBoss source code the solution, create inner class anonymous that implements the EntityResolver interface:
EntityResolver resolver = new EntityResolver () {
public InputSource resolveEntity (String publicId, String systemId) {
String empty = "";
ByteArrayInputStream bais = new ByteArrayInputStream(empty.getBytes());
System.out.println("resolveEntity:" + publicId + "|" + systemId);
return new InputSource(bais);
}
};
builder.setEntityResolver(resolver);
The returned InputSource consists solely of an empty string, this satisfises loading the dtd, since validation is set to false, the read document is not validated.
Now lets see if is actaully correctly written back to disk.
Tuesday, March 22, 2005
Using JBossPortal RC3
But the requirements for our environment still remain.
We need to connect to a MaxDB database and deploy the portal onto JBoss AS 4.0.2.
So first lets see how I can connect JBpossPortal to a MaxDB database.
Connecting to MaxDB
Reading through the user guide, the steps to deploy JBoss Portal seem fairly simple.
It should be just a matter of creating the database, the database connector file, copying the jboss-portal.sar structure into the deploy directory and starting JBoss.
But obviously it wasn't as simple as that. When starting JBoss I got a NullPointerException:
2005-06-13 13:10:11,709 DEBUG [org.jboss.resource.adapter.jdbc.local.LocalManagedConnectionFactory] Using properties: {user=portal, password=--hidden--}
2005-06-13 13:10:11,709 DEBUG [org.jboss.resource.adapter.jdbc.local.LocalManagedConnectionFactory] Checking driver for URL: jdbc:sapdb://dhu400d.internal.epo.org/portal
2005-06-13 13:10:11,710 DEBUG [org.jboss.resource.adapter.jdbc.local.LocalManagedConnectionFactory] Driver not yet registered for url: jdbc:sapdb://dhu400d.internal.epo.org/portal
2005-06-13 13:10:11,739 DEBUG [org.jboss.resource.connectionmanager.IdleRemover] run: IdleRemover notifying pools, interval: 450000
2005-06-13 13:10:11,782 DEBUG [org.jboss.resource.adapter.jdbc.local.LocalManagedConnectionFactory] Driver already registered for url: jdbc:sapdb://dhu400d.internal.epo.org/portal
2005-06-13 13:10:12,264 INFO [org.hibernate.cfg.SettingsFactory] RDBMS: SAP DB, version: Kernel 7.5.0 Build 018-121-079-776
2005-06-13 13:10:12,264 INFO [org.hibernate.cfg.SettingsFactory] JDBC driver: SAP DB, version: package com.sap.dbtech.jdbc, MaxDB JDBC Driver, MySQL MaxDB, 7.6.0 Build 000-000-003-247
2005-06-13 13:10:12,266 ERROR [org.jboss.portal.core.hibernate.SessionFactoryBinder] Starting failed portal:service=Hibernate
java.lang.NullPointerException
at java.util.Hashtable.put(Hashtable.java:393)
at java.util.Properties.setProperty(Properties.java:102)
at org.hibernate.cfg.SettingsFactory.buildSettings(SettingsFactory.java:106)
at org.hibernate.cfg.Configuration.buildSettings(Configuration.java:1509)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1054)
at org.jboss.portal.core.hibernate.SessionFactoryBinder.createSessionFactory(SessionFactoryBinder.java:261)
at org.jboss.portal.core.hibernate.SessionFactoryBinder.startService(SessionFactoryBinder.java:127)
at org.jboss.system.ServiceMBeanSupport.jbossInternalStart(ServiceMBeanSupport.java:272)
at org.jboss.system.ServiceMBeanSupport.start(ServiceMBeanSupport.java:173)
at org.jboss.portal.server.util.Service.start(Service.java:73)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)This makes working with open source projects so nice, to find out what the problem is, you just have to download the source package, and...
So I downloaded the source package for hibernate, and opened the file org/hibernate/cfg/SettingsFactory.java.
Around line 6 it contains:
if ( props.getProperty( Environment.DIALECT ) == null ) {
props.setProperty( Environment.DIALECT, DIALECTS.getProperty(databaseName) );
}
The constant DIALECTS is a Properties field that contains a mapping between databasenames and SQL dialect class, but it does not contain a mapping for SapDB (or MaxDB for that matter).
The above snippet shows that it is possible to supply the SQL dialect as en environment variable.
So I added
-Dhibernate.dialect=org.hibernate.dialect.SAPDBDialect to the JBoss start command, and that did the trick.Tuesday, February 01, 2005
Deploying jetspeed 2 on JBoss 4.0.1, succeeded!
He wrote a proper description for J2's wiki.
It all came down to portlet deployment. The portlets can only be deployed after JBoss is started.
According to his description the portlets even need to be undeployed before stopping JBoss, and re-deployed after starting.
Obviously I tried to stop and start JBoss without undeploying the portlets and J2 still worked fine.
In short these are the steps I followed to deploy J2 M1 on JBoss 4.0.1, assuming that a database on MaxDB is already configured:
- Copy the default server configuration and name it e.g. jetspeed.
- Create a new subdirectory in the directory /jboss-4.0.1/server/jetspeed/lib named j2lib
- Copy the sapdb driver jar into that directory
- Copy the maxdb datasource descriptor file into the /jboss-4.0.1/server/jetspeed/deploy directory
- Open the file /jboss-4.0.1/server/jetspeed/conf/jboss-service.xml
- Locate the line that reads
<classpath codebase="lib" archives="*"> - Add a similar line below it that reads
<classpath codebase="lib/j2lib" archives="*"> - Copy the jars pluto-1.0.1-rc1.jar, portals-bridges-common-0.1.jar, jetspeed-commons-2.0-M1.jar, jetspeed-api-2.0-M1.jar and portlet-api-1.0.jar into the directory /jboss-4.0.1/server/jetspeed/lib/j2lib
- Create the directory /jboss-4.0.1/server/jetspeed/deploy/jetspeed.war
- Extract the contents of the file jetspeed.war into that directory
- Move the jars commons-logging-1.0.3.jar, log4j-1.2.8.jar, xerces-2.3.0.jar and xml-apis-2.0.2.jar from the directory /jboss-4.0.1/server/jetspeed/deploy/jetspeed.war/WEB-INF/lib into /jboss-4.0.1/server/jetspeed/lib/j2lib
- Open the file /jboss-4.0.1/server/jetspeed/deploy/jetspeed.war/WEB-INF/assembly/jetspeed-spring.xml
- Locate the bean definition with id 'org.apache.jetspeed.tools.pamanager.servletcontainer.ApplicationServerManager' and comment out the Tomcat version and uncomment the JBoss version.
- Start JBoss
- Copy all desired portlet war files into the directory /jboss-4.0.1/server/jetspeed/deploy/jetspeed.war/WEB-INF/deploy
You need at least the file jetspeed-layouts.war.
Thursday, January 20, 2005
Deploying Jetspeed-2 on JBoss 4.0.1, revisited...
After that all kinds of, less obvious problems, occured.
Like deployment of portlets complaining with ClassNotFound exceptions for classes in their own jar file.
It appeared that after re-enabling that setting again, but removing the commons-logging-1.0.3.jar and log4j-1.2.8.jar files from the directory ../jetspeed.war/WEB-INF/lib, jBoss started without complaining, altough still showing portlets without a body.
The latter is because the JBossManager class, as defined in .../jetspeed.war/WEB-INF/assembly/jetspeed-spring.xml, is not implemented. It only contains stub implementations.
But thats for next time, now its skiing time...
Monday, January 10, 2005
Deploying Jetspeed-2 on JBoss 4.0.1
In the previous post I showed how one can connect J2 to a MaxDB database server.
This post describes the results of my first, failed, attempt to deploy J2 on JBoss using that same MaxDB database.
I am using the M1 binary release package of Jetspeed 2, and most of the steps taken originate from J2,'s wiki.
First I have created a copy of the default jboss server and named it jetspeed.
To keep the jetspeed jar files seperated from JBoss's jars, I created a sub-directory named j2 in the lib directory, and added the following line to the jboss-service.xml:
<classpath codebase="lib/j2" archives="*"/>I added a datasource file named jetspeed-maxdb-ds.xml to the deploy directory, to allow jetspeed to connect to my maxdb database server:
<?xml version="1.0" encoding="UTF-8"?>To be able to use the datasource, the JDBC driver needs to be present on the server's classpath. Therefor I placed the sapdbc-7_6_00_00_3247.jar in the lib/j2 directory.
<!-- The MaxDB database JCA connection factory config for the Jetspeed database -->
<datasources>
<local-tx-datasource>
<jndi-name>/JetspeedDS</jndi-name>
<connection-url>jdbc:sapdb://md80469a.internal.epo.org/j2prod?sqlmode=ORACLE</connection-url>
<driver-class>com.sap.dbtech.jdbc.DriverSapDB</driver-class>
<user-name>j2admin</user-name>
<password>ep0l1ne</password>
<min-pool-size>5</min-pool-size>
<max-pool-size>20</max-pool-size>
<idle-timeout-minutes>0</idle-timeout-minutes>
</local-tx-datasource>
</datasources>
The binary M1 release contains a directory named shared/lib, I copied all jar files in that directory into the newly created lib/j2 directory.
The binary M1 release also has a directory named jetspeed. This dir contains the extracted contents of the war file.
I copied this directory completely into the deploy directory and renamed it to jetspeed.war.
By default J2 is configured to use the tomcat as application server, to change this into JBoss the file
deploy/jetspeed.war/WEB-INF/assembly/jetspeed-spring.xmlneeds to be editted.
So I commented out the
org.apache.jetspeed.tools.pamanager.servletcontainer.ApplicationServerManagerdefinition for Tomcat and uncommented the definition fo rJBoss.
After that I started JBoss...
The following is the first ERROR that popsup in the server log file:
2005-01-11 09:39:28,291 ERROR [org.apache.commons.modeler.BaseModelMBean] Error creating class org.apache.commons.logging.LogConfigurationException: org.apache.commons.logging.LogConfigurationException: org.apache.commons.logging.LogConfigurationException: Class org.apache.commons.logging.impl.Log4JLogger does not implement Log
This might show a potential class loading problem....
In the JBoss docs, chapter 9. Web Applications, I found the following:
UseJBossWebLoader:Setting this setting to false, solved a lot of the problems. Now J2/JBoss starts fine, but the portlets only show their titlebar and not the contents.
This flag indicates that Tomcat should use a JBoss unified class loader as the web application class loader.
The default is true, which means that the classes inside of the WEB-INF/classes and WEB-INF/lib directories of the WAR file are incorporated into the default shared class loader repository described in Chapter 2, The JBoss JMX Microkernel.
This may not be what you want as its contrary to the default servlet class loading model and can result in sharing of classes/resources between web applications.
You can disable this by setting this attribute to false.
Running Jetspeed-2 using a MaxDB database
The portal server framework is not chosen yet, altough it most likely will become jetspeed 2.
JBoss 4.0.1 will be used as application server, and MaxDB as database management system.
I have just succeeded to run Jetspeed-2 M1 using the MaxDB database.
First you need to setup 2 databases on MaxDB, a production database and a test database, the latter is used during compilation, when executing unit tests.
To allow the jetspeed 2 build process to create the database, you have to create or edit a build.properties file and add the following lines to it:
# -------------------------------------------------------------------------
# configure MaxDB Test DB
# -------------------------------------------------------------------------
org.apache.jetspeed.test.database.default.name=oracle
org.apache.jetspeed.test.database.url=jdbc:sapdb://<db-host>/j2test?sqlmode=ORACLE
org.apache.jetspeed.test.database.driver=com.sap.dbtech.jdbc.DriverSapDB
org.apache.jetspeed.test.database.user=<dba-user>
org.apache.jetspeed.test.database.password=<password>
org.apache.jetspeed.test.jdbc.drivers.path=<path-to>/sapdbc-7_6_00_00_3247.jar
# -------------------------------------------------------------------------
# configure MaxDB Production DB
# -------------------------------------------------------------------------
org.apache.jetspeed.production.database.default.name=oracle
org.apache.jetspeed.production.database.url=jdbc:sapdb://<db-host>/j2prod?sqlmode=ORACLE
org.apache.jetspeed.production.database.driver=com.sap.dbtech.jdbc.DriverSapDB
org.apache.jetspeed.production.database.user=<dba-user>
org.apache.jetspeed.production.database.password=<password>
org.apache.jetspeed.production.jdbc.drivers.path=<path-to>/
# -------------------------------------------------------------------------
Now when running maven allClean allBuild, the database will be created on MaxDB.
All we now need to do to access the MaxDB database from j2 running on tomcat, is change the connection settings in ${CATALINA_HOME}/conf/Catalina/localhost/jetspeed.xml.
The JBoss 4 Application Server Guide
This can be quite usefull during development.
Tuesday, July 20, 2004
Checking for null or empty string values
Its test attribute can contain an EL expression.
To test if a value is
null you can compare the attribute to null like: <c:if test="${valueToTest eq null}">If the value exists but is empty you can test it using: <c:if test="${empty valueToTest}">I assumed that the empty operator was a binairy operator but after thourough testing it appeared to be a unairy operator.
Tuesday, June 01, 2004
Map iterations using c:forEach
Using the c:forEach custom tag, it is easy to iterate over collections including map's.
Altough you have to keep in mind that the resulting value is a MapItem.
The MapItem has 2 properties named key and value.
These properties can be treated as javabeans theirselves, hence its properties being retrieved according to the javabean specification.
Hereunder follows a sample that iterates over a map, the key is of type String and the value of a type that complies to the javabean specification:
<table>The output of the above sample is:
<c:forEach var="item" items="myMap">
<tr>
<td>
<c:out value="${item.key}"/>
</td>
<td>
<c:out value="${item.value.givenName}"/>
</td>
<td>
<c:out value="${item.value.surName}"/>
</td>
</tr>
</c:forEach>
</table>
| 1 | John | Doe |
| 2 | Jane | Doe |
| 3 | Johnny jr. | Doe |
Friday, May 14, 2004
Using custom objects in JSTL's expression language
If you are going to use JSTL's expression language, take care that the attributes you want to use needs to be within scope.
Usually the necessary attributes wil be available on the request, session or pagecontext. But sometimes you need to use a variable, or constant, that is NOT available yet. In that case you have to add it to the opagecontext yourself.
This can be achieved using a scriptlet:
<%
pageContext.setAttribute("myVar", MyClass.myConstant);
%>
But you can also achieve using the jstl tag c:set:
<c:set var="myVar"><%=MyClass.myConstant%></c:set>
Now it can be used in EL expressions within jstl tags:
<c:out value="${myVar.name}"/>
