Monday, December 14, 2009

CVS log commit messages

Every now and then when making a release I need an alphabetical list of all CVS commit messages since a particular previous tag. This is what I use (for tag 'mytag'):

cvs log -rmytag:: -S -N | grep '^RCS\|^Working\|^head\|^branch\|^locks\|^access\|^keyword\|^total\|^description\|^-------\|^========\|^revision\|^\?\|^date\|^$\|\*\*\*' -v | sort -u

Is there anybody on this planet with a more elegant solution?

Best regards,
Ganesh

Tuesday, June 23, 2009

Hibernate Event Listeners with Spring

You can configure your Hibernate event listeners via your spring-context.xml.
When you declare your Bean from type org.springframework.orm.hibernate3.LocalSessionFactoryBean you can initilize the property "eventListeners". This attribute is from type Map. The key defines the type of the event listeners (e.g. flush, load, delete, etc.). The value defines the corresponding class which implements the EventListener interface or extend the DefaultEventListener implementation class.


Sample of your context.xml

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
...
<property name="eventListeners">
<map>
<entry key="flush">
<bean class="org.j4fry.hibernate.eventlisteners.FlushEventListener" />
</entry>
</map>
</property>
...
</bean>
Sample of a FlushEventListener

package org.j4fry.hibernate.eventlisteners;
import org.apache.log4j.Logger;
import org.hibernate.HibernateException;
import org.hibernate.event.FlushEvent;
import org.hibernate.event.def.DefaultFlushEventListener;

public class FlushEventListener extends DefaultFlushEventListener {
public void onFlush(FlushEvent fe) throws HibernateException {
super.onFlush(fe);
}
}
List of keys and the corresponding Interfaces and implementation-classes
Map-KeyInterfaceDefault implementation class
auto-flushAutoFlushEventListener
deleteDeleteEventListener
dirty-checkDirtyCheckEventListener
evictEvictEventListener
flush-entityFlushEntityEventListener
flushFlushEventListener
load-collectionInitializeCollectionEventListener
loadLoadEventListener
lockLockEventListener
mergeMergeEventListener
create-onflushPersistEventListener
post-deletePostDeleteEventListener
post-insertPostInsertEventListener
post-loadPostLoadEventListener
post-updatePostUpdateEventListener
pre-deletePreDeleteEventListener
pre-insertPreInsertEventListener
pre-loadPreLoadEventListener
pre-updatePreUpdateEventListener
refreshRefreshEventListener
replicateReplicateEventListener
save-updateSaveOrUpdateEventListener

Saturday, June 20, 2009

IE8 script cache and AJAX script replace

Today I tried debugging the MyFaces 2.0 AJAXS scripts in IE8. The debugger is quite nice. The hard side came in when I starting changing the scripts and tried testing my new script versions. IE8 prooved to be a resilient beast like it's anchestors and insisted on running an old script version. The nice button "clear browser cache" in the developer tools didn't do anything. What finally helped was the first menu option in menu "cache" - in german it says: Immer vom Server aktualisieren.
Now that I could step into my Javascript code things got even weirder. I had a simple

<span id="test"><script ... ></span>

construction and I tried do replace element "test" with an AJAX call. So what do you think happened? I did:

item.insertAdjacentHTML('beforeBegin', '<span id="test"><script ... ></span>');

and then checked item.previousSibling. I turned out IE8 had inserted:

<span id="test"></span>

It just left out my new script. I changed the HTML code to look like (don't ask me what gave me the idea to do so, years of suffering train intuition):

<span id="test">
<input type="hidden" />
<script ... >
</span>

and suddenly IE inserted it all like it should. If you want to know which tricks are necessary to trigger script execution have a look at the MyFaces repository:
http://svn.apache.org/repos/asf/myfaces/core/branches/2_0_0/api/src/main/javascript/META-INF/resources/myfaces/_impl/_util/_Utils.js

It's interesting code - external and embedded scripts need to be treated differently.

Friday, June 19, 2009

HowTo integrate JUnit and WebBeans

WebBeans provides an easy way to integrate it with JUnit.
I use for the examples WebBeans 1.0.0.PREVIEW1 and Junit4.

Follw these steps to integrate JUnit and WebBeans.

1. Create a base class called AbstractWebBeansContextTest
This super class contains the setup of the WebBeans Context and makes the WebBeans Manager available for its subclasses. You have to add the webbeans-se.jar to your build path. This jar provides the possibility to initialize the WebBeans context within a SE (Java StandardEdtion) environment.

import javax.inject.manager.Manager;
import org.jboss.webbeans.CurrentManager;
import org.jboss.webbeans.environment.se.StartMain;

public abstract class AbstractWebBeansContextTest {
public static final Manager manager;
static {
StartMain.main(new String[]{});
manager = CurrentManager.rootManager();
}
}

2. Put a beans.xml into the root-source directory of your testing project
In that beans.xml you could define your testing deployment types (e.g. @Mock, etc.). In our case this beans.xml left blank.

3. Create your test class
Create a new test class which is a subclass of AbstractWebBeansContextTest.
Annotate a method with @BeforeClass and initialize your WebBeans which you wan to use in your test case.
Annotate some other methods with @Test and use your initialized WebBeans.

public class MyTestCase extends AbstractWebBeansContextTest {

public static MyService service;

@BeforeClass
public static void startup() {
service = manager.getInstanceByType(MyService.class);
}

@Test
public void testServiceMethod() throws Exception {
...
service.myServiceMethod();
...
}
}

Wednesday, June 17, 2009

JSF 2.0 and dojo create NO_MODIFICATION_ALLOWED_ERR: DOM Exception 7 on Safari

When testing our dojo facelets examples in Safari I realized that they don't work with Mojarra 2.0. After some investigation it turned out that Mojarra 2.0 sends a reponse-header Content-Type: application/xhtml+xml thus triggering a bug in Safari.With JSF 1.2 (also with Facelets) it was always Content-Type: text/html. The result is that Safari throws NO_MODIFICATION_ALLOWED_ERR on some DOM operations that are needed from the dojo side.

I added a Listener to set the Content-Type to text/html and - helas! - it works just fine.

public void beforePhase(PhaseEvent event) {
FacesContext context = FacesContext.getCurrentInstance();
ExternalContext extContext = context.getExternalContext();
Object response = extContext.getResponse();
if (event.getPhaseId() == PhaseId.RENDER_RESPONSE) {
String contentType = "text/html; charset=UTF-8";
if (response instanceof ServletResponse) {
((ServletResponse) response).setContentType(contentType);
} else if (response instanceof RenderResponse) {
((RenderResponse) response).setContentType(contentType);
}
}
}

Tuesday, June 16, 2009

JSF 2.0 AJAX overview

Many AJAX JSF frameworks are on the market - but the moment you start combining them you may get random results due to incompatibilities. JSF 2.0 will help with this! Specifying the AJAX API will help assemble the different approaches under one roof. The spec (JSR-314) defines an f:ajax tag as well as a javscript API together with an AJAX enhanced JSF lifecycle.

I helped implement one of the numerous AJAX JSF approaches for years (the fry:ajax tag from J4Fry) and during the last months this approach was integrated into Apache MyFaces 2.0 while adapting it's interfaces to the new spec. The spec covers a lot of the basic features in a generic and flexible way. Btw.: MyFaces 2.0 is on its way, we're currently gluing everything together and I'm hoping for an alpha by end of august.

The most basic part of an AJAX implementation is replacing parts of the document. These are the features the JSF 2.0 API provides:
  • execute - The components that will be processed on the server in a blank separated list. Only the components named within this parameter get their decode, validate and updateModel methods called during phase 2-4. There is an @all keyword you can use to process the entire component tree.
  • render - The components that will be rendered and replaced within the HTML page in a blank separated list.
  • onevent - A JS callback that is triggered with three different events:
    • begin - occurs immediately before the request is sent
    • complete - occurs after the AJAX request has completed but before DOM manipulation has taken place
    • success - occurs after DOM manipulation has taken place (only for successfull request, else see onerror)
  • onerror - A JS callback that is triggered when the server signalizes that an error has occured.
  • params - An object that may include additional parameters to include in the request.
There have been discussions on both the MyFaces and Mojarra mailing lists on the nature of the ids in the execute and render parameters. Are they HTML ids or component ids? Here's the truth: The f:ajax tag can take either component ids that resolve relative to the nearest naming container or HTML ids. There is an algorithm that tries both. The procedural interface jsf.ajax.request(source, event, {execute: ..., render: ...}) requires HTML ids. The f:ajax tag will resolve the component and generate a behaviour that is in fact a call to jsf.ajax.request.

f:ajax provides three more attributes that offer JSF specific enhancements:
  • disabled - Indicates whether the AJAX behavior script should not be rendered.
  • listener - A method binding to execute when the AJAX request is processed on the server.
  • immediate - same as the attribute you know from the standard JSF action sources.
For Tomahawk 2.0 we are preparing a t:ajax tag that will include a bunch of extra options. Implementation will happen in J4Fry JSF 2.0 with a fry:ajax tag (targeted for end of juli) which will be repackaged for Tomahawk 2.0 when it is ready. This is the list of extra options we want to support:
  • timout - How long to wait for the HTTP response before aborting the request.
  • delay - How long to wait before issuing a request (helpfull with onkeyup or mouse move events to avoid tons of requests).
  • queuesize - Number of requests to queue (discard the oldest when the queue is full and a new one arrives).
  • partial submit - The current spec requires submission of the entire form though only the elements named in the execute parameter are being processed. Setting partial submit (or pps) to true could reduce the submit volume to the actually processed values.
  • disable - HTML id's of the components to disable while the request is running (can be implemented via onevent).
  • loadingbar - HTML id of an img tag to make visible while the request is running (can also be implemented via onevent).
  • errorhandling for errors that occur within the javascript - can be done with the onerror parameter, but the spec doesn't mention this use.
Just in case you've made it up to here (which would only happen if you are really deep into JSF and AJAX technology) you will be keen to know whether JSF 2.0 AJAX will do an auto eval on incoming scripts. If you rerender a portion of your markup that contains a script then auto eval will execute the newly arrived scripts. The spec doesn't mention this issue, Mojarra 2.0 (in it's current beta state) doesn't do auto eval but MyFaces 2.0 will.

Thursday, June 4, 2009

HowTo integrate Apache Axis and WebBeans

IMO WebBeans becomes a pretty cool dependency injection framework for Java. It works in a type-safe way (greetz to Spring ;-)) by using annotations. It provides Interceptors, Decorators and Event-Processing as well.
On the other hand Axis is a powerful framework to implement WebServices.

If you want to use the WebBeans benefits in your Axis Services you have to integrate both technologies. Axis provides two simple ways to do this:
  1. with a custom MessageReceiver
  2. with a ServiceObjectSupplier
So lets integrate WebBeans into Axis.
I'm running on Tomcat 6.0.18 with Apache Axis2 1.4.1 and WebBeans 1.0.0. Preview1.

Create a WebBeans integration class

package org.j4fry.webbeans;
import javax.inject.manager.Manager;
import org.apache.axis2.AxisFault;
import org.apache.axis2.Constants;
import org.apache.axis2.description.AxisService;
import org.apache.axis2.description.Parameter;
import org.jboss.webbeans.CurrentManager;

public abstract class WebBeansIntegration {
public static Object createInstance(AxisService axisService) throws AxisFault {
Parameter parameterServiceClass = axisService.getParameter(Constants.SERVICE_CLASS);
Class serviceClass = null;
try {
serviceClass = Class.forName(parameterServiceClass.getValue().toString());
} catch (ClassNotFoundException e) {
throw new AxisFault("There's not valid serviceClass specified", "serviceClass");
}
Manager manager = CurrentManager.rootManager();
return manager.getInstanceByType(serviceClass);
}
}

Possibility 1: Adjust Axis to use this integration class via a custom Message Receiver

package org.j4fry.webbeans;
import org.apache.axis2.AxisFault;
import org.apache.axis2.context.MessageContext;

public class CustomMessageReceiver extends org.apache.axis2.rpc.receivers.RPCMessageReceiver {
@Override
protected Object makeNewServiceObject(MessageContext msgCtx) throws AxisFault {
return WebBeansIntegration.createInstance(msgCtx.getAxisService());
}
}

Possibility 2: Adjust Axis to use this integration class via ServiceObjectSupplier

package org.j4fry.webbeans;
import org.apache.axis2.AxisFault;
import org.apache.axis2.ServiceObjectSupplier;
import org.apache.axis2.description.AxisService;

public class WebBeansObjectSupplier implements ServiceObjectSupplier {
public Object getServiceObject(AxisService axisService) throws AxisFault {
return WebBeansIntegration.createInstance(axisService);
}
}

Tomcat Configuration - web.xml
Tomcat's web.xml have to reference the WebBeans Manager (of course you have to include the AxisServlet and the mapping information as well)

<resource-env-ref>
<description>WebBeans Manager</description>
<resource-env-ref-name>app/Manager</resource-env-ref-name>
<resource-env-ref-type>javax.inject.manager.Manager</resource-env-ref-type>
</resource-env-ref>

Axis Service Configuration - services.xml
The services.xml from your Axis-Service archive (.aar file)
If you choose possibility 1 you have to include your custom Message Receiver with the following tag inside the service-element:

<messageReceivers>
<messageReceiver mep="http://www.w3.org/ns/wsdl/in-out" class="org.j4fry.webbeans.CustomMessageReceiver"/>
</messageReceivers>

If you choose possiblity 2 you have to add the "ServiceObjectSupplier" parameter to your service element like this

<parameter name="ServiceObjectSupplier">org.j4fry.webbeans.WebBeansObjectSupplier</parameter>

Use WebBeans Annotation inside your Service class
If you've finished the previous steps you can use the WebBeans Annotations to inject some resources in your service class.

Resources
WebBeans RI 1.0.0 Preview1 (thanks to JBoss): http://downloads.sourceforge.net/jboss/webbeans-1.0.0.PREVIEW1.zip
Apache Axis2 1.4.1: http://ws.apache.org/axis2/

Wednesday, May 20, 2009

Use Subversive and Putty together on Windows

1. Download Eclipse Ganymede
From http://www.eclipse.org/
2. Download Putty
From http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html
3. Extract Putty
Extract the putty.zip under C:\Apps\putty\ for instance.
4. Install Subversive (Subversion Plugin) and SVN Connectors
Open Eclipse and select "Help"->"Software Updates..."
Click on "Available Software" Tab
You need these two update sites:
Subversive Plugin: http://download.eclipse.org/technology/subversive/0.7/update-site/
SVN Connectors: http://www.polarion.org/projects/subversive/download/eclipse/2.0/update-site/
So add these two sites by clicking on "Add Site..." Button (two times)
Afterwards you see in your "Available Software" Panel the new two sites.
Expand the "Subversive Site" and select the following plugins:
Subversive SVN Team Provider Plugin
Now expand the "Subversive SVN Connectors Site" and select the following plugins:
Subversive SVN Connectors
After these steps click the "Install..." Button
If the installation is finished you have to restart Eclipse.
5. Configure PLINK
Add a new environment variable
Name: SVN_SSH
Value: C:\\Apps\\putty\\plink.exe -ssh -2 -A -l mySvnUser
You have to adjust the svn user.
Now start the PAGEANT and select your Private Key
6. Configure SVN Connectors
In Eclipse go to "Window"->"Preferences"
Select the "Team"->"SVN"
Select the "SVN Connector" Tab
Set the Option "SVN Connector" to "Native JavaHL (svn:1.6.0 (r36650) jni:0.9.0)"
Click the "Apply" Button
7. Add a new Repository Location
Go to "Window"->"Open Perspective"->"Other..." and select "SVN Repository Exploring"
Switch to the SVN Repository Perspective and click the Button "New Repository Location"
Now enter your SVN Repository (for example: svn+ssh://example.org/var/svn/myRepo)
Click the "Finish" Button.

There's one harm: Everytime when you use the Subversive Plugin via PLINK a DOS Prompt is opened by Windows :-(

Sunday, March 15, 2009

Fuzzy String Match in PostgreSQL with Debian

If you want to use FuzzyStringMatching in PostgreSQL you have to do the following steps.
Prerequisites: Debian 4.0 Etch (or higher), installed PostgreSQL 8.3, existing database in postgres

1. Install the postgresql-contrib package via apt

apt-get install postgresql-contrib

2. Switch to your postgres user

su - postgres

3. Open the psql interactive terminal with the following options database, user, password and the installation file for the fuzzy string functions

psql -d myDatabase -U myUser --password myPassword -h localhost -f /usr/share/postgresql/8.3/contrib/fuzzystrmatch.sql

Afterwards you can use the soundex, levenshtein, metaphone and double metaphone functions in your sql statements.
Offical documentation about the fuzzy string match functions: http://www.postgresql.org/docs/8.3/static/fuzzystrmatch.html

Tuesday, February 24, 2009

Comparing RIA Frameworks

If you are interested in RIA Frameworks you can have a look at that comparison http://sonymathew.blogspot.com/2009/02/comparing-ria-frameworks.html (Thanks to . ADF Oracle Faces RC you can find here, thanks to Juan Camilo Ruiz.
Unfortunately JavaFX as well as Microsoft Silverlight is not mentioned in that comparison. That's why you can find the "missing" JavaFX column here:


Platform/Technology: JavaFX/Java
User Experience: Modest Rich if you're familar with Java. Is exactly like a Desktop App. No Page refreshes, all data-access & rendering in the background. Includes also data-bindings from variables to GUI-widgets. JavaFX wraps some Swing components to use them in a JavaFX GUI. JavaFX 1.1 API
Browser Support: Support all browser. You can deploy JavaFX applications via an Java Applet, Java-WebStart (JNLP - Java Network Launching Protocol) or stand-alone applications on the desktop.
Throu Java Web Start a one-click installation is possible. Awesome feature: You drag an applet from the browser to your desktop.
UI Code: JavaFX Scripting and Java. Via JavaFX you can describe your GUI in a declarative way. JavaFX allows to bind variables to GUI-widgets (data-bindings) and provide a possibility to add triggers to variables.
You can develop the business logic in Java. There's a plugin for different Adobe Tools (e.g. Photoshop) for designing your GUI.
Access Remote Services & Data: You can invoke remote Java-Services via RMI.
Code Complexity Management: JavaFX files (JavaFX Script Programming Language), Java files, Organize into Class/Object hierarchies, Packages. It's statically typed and a compiled language.
Tool Support / Eclipse Integration: There's a JavaFX Plugin for Netbeans. The plugin in provides Code-Completion, Live-Preview of the GUI and so on. Download page
Refactoring & Code-Completion Support: All Java Refactoring & Code Completion with NebBeans.
JEE Integration: You can invoke EJBs like in any other stand-alone Java-Application.
Migration: You can use existing Backend-Services. Of course you can use existing any Java-Code inside a JavaFX-Application
Performance: Partial downloading of the JRE is one of the performances pros. So you can use JavaFX-Applications on clients which haven't got a full installed version of the JRE. Modest download-time to browser because of modularized JRE (Entire JRE: 14,5MB but you need in most cases only the Typical Applet version 4,6MB)
Static-Content (Externally Managed): You can style your widgehts with CSS
Requirements: You need JRE 1.6 Update 10
Search Engine Optimization: Not compatible.

Currently J4Fry is working on some Dojo-Tags for Facelets for RIA feelings in JSF applications.
The declarative Tag should ease the use of Dojo in JSF Applications.
There'll be news about J4Fry-DojoFaces-Project when there's a beta version for testing.

Wednesday, January 21, 2009

Pass action as Facelets-Parameter

There is a problem to pass an action as a Facelet-Parameter to a Fragment via ui:include an ui:param.
With the J4Fry-Action-Wrapper (http://www.j4fry.org/jsfErrorhandling.shtml) as a part of the J4Fry-JSF-Components (http://www.j4fry.org/jsfComponents.shtml) you've got the possibility to pass the action (e.g. for a h:commandButton) to a Facelets-Fragment.

Example
Main-Page

...
<ui:include src="Fragments/myFragment.xhtml">
<ui:param name="myAction" value="myBean.doSomething" />
</ui:include>
...

Fragment

<h:commandButton value="Execute doSomething" action="#{action[myAction].trigger}" />

To use that solution you have to download the J4Fry-JSF-Components (with dependencies described here: http://www.j4fry.org/jsfComponents.shtml) and place the JAR-File into your lib-directory from the webapplication. Thats it!

Friday, January 16, 2009

JSF VariableResolver & PropertyResolver

Resolving
Mit Hilfe des VariableResolvers und des PropertyResolvers löst JSF die EL-Expressions auf.
Der VariableResolver ist zuständig für den linken Teil der Expression. Für den restlichen rechten Teil ist der PropertyResolver zuständig.

Beispiel:
Bean Person:

public class PersonBean implements java.io.Serializable {
private Address address;
...
}

Klasse Address

public class Address implements java.io.Serializable {
private City city;
private String street;
private String zipCode;
...
}

Klasse City

public class City implements java.io.Serializable {
private String name;
...
}

JSF-Tag

<inputField value="#{personBean.address.city.name}" />

Der VariableResolver löst "personBean" auf.
Der PropertyResolver löst in Teilschritten zuerst "address" und anschließend "city" auf um zum Schluß auf die Property "name" der Klasse City zuzugreifen.

Implementierung eigener Variable- und PropertyResolver
Schritt 1
Anlegen der Klassen CustomVariableResolver und CustomPropertyResolver
Klasse CustomVariableResolver

package org.j4fry.jsf;
public class CustomVariableResolver extends VariableResolver {
private Logger log = Logger.getLogger(CustomVariableResolver.class);

// Ursprünglicher VariableResolver
private VariableResolver variableResolver;

public CustomVariableResolver(VariableResolver variableResolver) {
this.variableResolver = variableResolver;
}

@Override
public Object resolveVariable(FacesContext arg0, String arg1)
throws EvaluationException {
log.info("resolve: " + arg1);
// Delegation an ursprünglichen VariableResolver
return variableResolver.resolveVariable(arg0, arg1);
}
}

Klasse CustomPropertyResolver

package org.j4fry.jsf;
public class CustomPropertyResolver extends PropertyResolver {
private Logger log = Logger.getLogger(CustomPropertyResolver.class);

// Ursprünglicher PropertyResolver
private PropertyResolver propertyResolver;

public CustomPropertyResolver(PropertyResolver propertyResolver) {
this.propertyResolver = propertyResolver;
}

@Override
public Object getValue(Object fromObject, Object property)
throws EvaluationException, PropertyNotFoundException {
log.debug("getValue: fromObject[" + fromObject + "] property[" + property + "]");
// Delegation an ursprünglichen PropertyResolver
return propertyResolver.getValue(fromObject, property);
}

@Override
public void setValue(Object toObject, Object property, Object value)
throws EvaluationException, PropertyNotFoundException {
log.debug("setValue: toObject[" + toObject + "] property[" + property + "] value[" + value + "]");
// Delegation an ursprünglichen PropertyResolver
propertyResolver.setValue(toObject, property, value);
}

// Bei den restlichen Methoden wird einfach an den PropertyResolver delegiert

@Override
public void setValue(Object arg0, int arg1, Object arg2)
throws EvaluationException, PropertyNotFoundException {
propertyResolver.setValue(arg0, arg1, arg2);
}

@Override
public Class getType(Object arg0, int arg1) throws EvaluationException,
PropertyNotFoundException {
return propertyResolver.getType(arg0, arg1);
}

@Override
public Class getType(Object arg0, Object arg1) throws EvaluationException,
PropertyNotFoundException {
return propertyResolver.getType(arg0, arg1);
}

@Override
public Object getValue(Object arg0, int arg1) throws EvaluationException,
PropertyNotFoundException {
return propertyResolver.getValue(arg0, arg1);
}

@Override
public boolean isReadOnly(Object arg0, int arg1)
throws EvaluationException, PropertyNotFoundException {
return propertyResolver.isReadOnly(arg0, arg1);
}

@Override
public boolean isReadOnly(Object arg0, Object arg1)
throws EvaluationException, PropertyNotFoundException {
return propertyResolver.isReadOnly(arg0, arg1);
}

}

Die Klassen werden jeweils von den JSF-eigenen Resolvern abgeleitet. Zudem bekommt jeder CustomResolver einen Konstruktor der den ursprünglichen Resolver übergeben bekommt. Das ist wichtig um in den Methoden ggf. die Verarbeitung an diesen Resolver zu delegieren.

Schritt 2
CustomResolver in der faces-config.xml bekannt machen

<application>
<variable-resolver>
org.j4fry.jsf.CustomVariableResolver
</variable-resolver>
<property-resolver>
org.j4fry.jsf.CustomPropertyResolver
</property-resolver>
</application>

Interpretierung der Log-Ausgaben
Als Beispiel dient die o.g. EL-Expression #{personBean.address.city.name}

Lesender Zugriff
1. Auflösen von personBean durch VariableResolver
Logausgabe: resolve: personBean
2. Auflösen von address durch PropertyResolver
Logausgabe: getValue: fromObject[org.j4fry.beans.PersonBean@1f68572] property[address]
3. Auflösen von city durch PropertyResolver
Logausgabe: getValue: fromObject[org.j4fry.model.Address@1b335b7] property[city]
4. Auflösen von name durch PropertyResolver
Logausgabe: getValue: fromObject[org.j4fry.model.City@15c018] property[name]

Schreibender Zugriff
1. Auflösen von personBean durch VariableResolver
Logausgabe: resolve: personBean
2. Auflösen von address durch PropertyResolver
Logausgabe: getValue: fromObject[org.j4fry.beans.PersonBean@1f68572] property[address]
3. Auflösen von city durch PropertyResolver
Logausgabe: getValue: fromObject[org.j4fry.model.Address@1b335b7] property[city]
4. Setzen von name durch PropertyResolver
Logausgabe: setValue: toObject[org.j4fry.model.City@15c018] property[name] value[Munich]

Thursday, January 15, 2009

HttpURLConnection connection pool

Lately i had to set up a server to server HTTP connection with up to 200 parallel open connections. After some fiddling I succeeded with a nice and small sized URLConnection solution. It' identical for HttpURLConnection and HttpsURLConnection (with SSL). At first, you need to know that URLConnection's design requires a new URLConnection instance for every request you want to make. Cast the URLConnection to HttpURLConnection to gain access to the HTTP specific properties like requestMethod and connectionTimeout:

URL url = new URL("HTTPS", server, port, serverPath);
huc = (HttpURLConnection) url.openConnection();

Now you need some configuration. These are the properties I needed (using org.apache.commons.util.Base64):

huc.setDoOutput(true);
huc.setReadTimeout(socketTimeout);
huc.setConnectTimeout(connectionTimeout);
huc.setRequestMethod("POST");
authorizationString = "Basic " + new String(Base64.encode(username + ":" +password)).getBytes("ISO-8859-1")), "ISO-8859-1");
huc.setRequestProperty ("Authorization", authorizationString);
os = huc.getOutputStream();

Write your request (it goes to the buffer):

os.write(request);
os = huc.getOutputStream();

When you call getInputStream() your request is issued to the server and you get the response stream for further processing. You need to close the InputStream to free the underlying Socket for reuse. It's internally pooled:

try {
is = huc.getInputStream();
response = readResponse(is, huc.getContentLength());
} finally {
is.close();
}

private String readResponse(InputStream is, int length) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int b = 0;
int read = 0;
while (read < length) {
b = is.read();
baos.write(b);
}
return baos.toString("ISO-8859-1");
}

Configure your connection pool with Java system properties:

-Dhttp.maxConnections=200
-Dsun.net.http.errorstream.enableBuffering=true

Monday, January 12, 2009

Upgrading from MyFaces 1.1.5 to JSF 1.2 RI

When upgrading the example project I encountered 7 issues:
  • Using the same tag attribute for a JSF tag twice was silently ignored with 1.1.5 and now throws an exception with 1.2
  • Using less columnClasses than columns in a panelGrid rendered the remaining columns without CSS class with 1.1.5 and now repeats the columnClasses for the remaining columns with 1.2
  • MyFaces 1.1.5 rendered either a name or and id attribute for each tag, so scripts could always identify them. 1.2 RI renders commandLinks with neither name nor id, imposing minor scripting changes
  • MyFaces 1.1.5 updated the model with null, when a radio button not clicked and the bean property is a String, the 1.2 RI updates with ""
  • 1.2 RI writes an exception stacktrace to the log when a phase listener throws a bug. MyFaces 1.1.5 was silently ignoring them
  • When a bean implemented Map and a bean property was set through DI in faces-config, MyFaces 1.1.5 called Map.put(). 1.2 RI doesn't, so implementing a separate setter for upgrading was necessary
  • When a property of a bean in session scope is set through DI (faces-config) and the property is a bean in request scope this would silently upgrade the ssecond beans life to session scope. MyFaces 1.1.5 would ignore this while 1.2 RI throws an exception
Thanks to Ganesh for identifying the differences.

Fehlendes Bundle com.sun.el.Messages

Auf Grund von einem fehlenden Bundle kann es bei der Nutzung von Faclets zu folgender java.util.MissingResourceException kommen:

java.util.MissingResourceException: Can't find bundle for base name com.sun.el.Messages, locale de_DE
at java.util.ResourceBundle.throwMissingResourceException(ResourceBundle.java:836)
at java.util.ResourceBundle.getBundleImpl(ResourceBundle.java:805)
at java.util.ResourceBundle.getBundle(ResourceBundle.java:549)
at com.sun.el.util.MessageFactory.(Unknown Source)
at com.sun.el.parser.AstValue.getTarget(Unknown Source)
at com.sun.el.parser.AstValue.getType(Unknown Source)
at com.sun.el.ValueExpressionImpl.getType(Unknown Source)
at com.sun.facelets.el.TagValueExpression.getType(TagValueExpression.java:60)
at com.sun.facelets.el.LegacyValueBinding.getType(LegacyValueBinding.java:94)

Ein Grund für die Exception könnte ein NullPointer innerhalb einer EL-Expression sein die JSF bzw. Facelets versucht aufzulösen.

Um die ursprüngliche (etwas aussagekräftigere ;-)) Exception zu sehen könnt ihr einfach folgendes JAR-File in eure Webapplication einbinden: http://j4fry.org/resources/el-messages.jar.
Enthalten sind die englischen und deutschen Property-Files.

Saturday, January 10, 2009

Facelets Template-Parameter

Es gibt mehrere Möglichkeiten Facelets-Templates zu parameterisieren.
  1. Über ui:insert und ui:define
  2. Über EL und ui:param
Facelets Template:

<html>
<head>
<link rel="stylesheet" type="text/css" href="#{myStylesheet}" media="screen, projection" />
</head>
<body>
<ui:insert name="myContent">No content supplied.</ui:insert>
</body>
</html>

Facelets Template-Client:

<ui:composition template="MyTemplate.xhtml">
<ui:param name="myStylesheet" value="http://my.host.com/css/style.css" />
<ui:define name="content">
<h1>My Content</h1>
</ui:define>
</ui:composition>


Über ui:insert ist es möglich Blockplatzhalter zu definieren.
Mit ui:param können auch Inline-Passagen definiert werden.

Die Frage wurde in unserem XING JSF-Developers-Forum (https://www.xing.com/net/jsf) gestellt.

Welcome! / Willkommen!

Welcome to the J4Fry Blog.
In this blog the J4Fry members have got the opportunity to post sth about Java especially about Java-Web-Development.
We're looking foward to read some comments to our blog posts.

Have fun!
So long, cheerz Alex
____________________________________

Willkommen im J4Fry Blog.
In diesem werden wir J4Fry Members hin und wieder etwas über Java speziell über Java-Webentwicklung posten.
Wir freuen uns eure Kommentare zu unseren Posts zu lesen.

Viel Spaß!
mfg Alex
____________________________________

J4Fry Website: http://www.j4fry.org/
J4Fry Team: http://www.j4fry.org/team.shtml
Webprofil Alexander Bell: http://www.j4fry.org/alexanderbell.shtml
Webprofil Ganesh Jung: http://www.gpsjava.de/