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
Monday, December 14, 2009
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
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-classesMap-Key | Interface | Default implementation class |
---|---|---|
auto-flush | AutoFlushEventListener | |
delete | DeleteEventListener | |
dirty-check | DirtyCheckEventListener | |
evict | EvictEventListener | |
flush-entity | FlushEntityEventListener | |
flush | FlushEventListener | |
load-collection | InitializeCollectionEventListener | |
load | LoadEventListener | |
lock | LockEventListener | |
merge | MergeEventListener | |
create-onflush | PersistEventListener | |
post-delete | PostDeleteEventListener | |
post-insert | PostInsertEventListener | |
post-load | PostLoadEventListener | |
post-update | PostUpdateEventListener | |
pre-delete | PreDeleteEventListener | |
pre-insert | PreInsertEventListener | |
pre-load | PreLoadEventListener | |
pre-update | PreUpdateEventListener | |
refresh | RefreshEventListener | |
replicate | ReplicateEventListener | |
save-update | SaveOrUpdateEventListener |
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
construction and I tried do replace element "test" with an AJAX call. So what do you think happened? I did:
and then checked item.previousSibling. I turned out IE8 had inserted:
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):
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.
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.
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.
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.
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:
f:ajax provides three more attributes that offer JSF specific enhancements:
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)
- begin - occurs immediately before the request is sent
- 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.
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.
- 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.
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:
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
Possibility 1: Adjust Axis to use this integration class via a custom Message Receiver
Possibility 2: Adjust Axis to use this integration class via ServiceObjectSupplier
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)
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:
If you choose possiblity 2 you have to add the "ServiceObjectSupplier" parameter to your service element like this
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/
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:
- with a custom MessageReceiver
- with a ServiceObjectSupplier
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
<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 :-(
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 :-(
Tags:
Eclipse,
Putty,
Subversion,
Subversive,
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
2. Switch to your postgres user
3. Open the psql interactive terminal with the following options database, user, password and the installation file for the fuzzy string functions
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
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
Tags:
Database,
Debian,
FuzzyString,
PostgreSQL,
Soundex
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 Sony Mathew). 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.
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
Fragment
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!
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!
Tags:
Action,
Facelets,
JavaServer Faces,
JSF,
Parameter
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:
Klasse Address
Klasse City
JSF-Tag
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
Klasse CustomPropertyResolver
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
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]
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:
Now you need some configuration. These are the properties I needed (using org.apache.commons.util.Base64):
Write your request (it goes to the buffer):
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:
Configure your connection pool with Java system properties:
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
Tags:
JavaServer Faces,
JSF,
MyFaces
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:
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.
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.
Tags:
Facelets,
MissingResourceException
Saturday, January 10, 2009
Facelets Template-Parameter
Es gibt mehrere Möglichkeiten Facelets-Templates zu parameterisieren.
Facelets Template-Client:
Ü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.
- Über ui:insert und ui:define
- Über EL und ui:param
<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.
Tags:
Facelets,
JavaServer Faces,
JSF,
Parameter,
Template
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/
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/
Subscribe to:
Posts (Atom)