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);
}
}
}