Saturday, February 18, 2006

A prototype of Jython ScriptFactory for Spring Framework

SpringFramework 2.0 M2 does not include Jython support for its scripting framework. I don't know the reason. So I decide to create a prototype to prove it is doable.

Suppose we have a Java interface Messenger:

package org.yweng.spike.Spring;

public interface Messenger {
String getMessage();
}

And we have a Jython Script, Messenger.py, which implementes this interface:

from org.yweng.spike.Spring import Messenger

class PythonMessenger(Messenger):
def getMessage(self):
return 'Message from Python Messenger'

def getInstance():
return PythonMessenger()

Notice the getInstance method in the Jython module. The idea is using "naming convention" to help the Jython ScriptFactory instantiate Jython object.

The Spring xml configuration:

<beans>
<bean class="org.springframework.scripting.support.ScriptFactoryPostProcessor"/>
<bean id="PyMessenger" class="org.yweng.spike.Spring.JythonScriptFactory">
<constructor-arg
value="classpath:org/yweng/spike/Spring/Messenger.py" />
<constructor-arg
value="org.yweng.spike.Spring.Messenger" />
</bean>
</beans>

The JythonScriptFactory class looks like this:


package org.yweng.spike.Spring;

import java.io.IOException;

import org.springframework.scripting.ScriptCompilationException;
import org.springframework.scripting.ScriptFactory;
import org.springframework.scripting.ScriptSource;
import org.springframework.util.Assert;
import org.apache.log4j.Logger;

import org.python.util.PythonInterpreter;


public class JythonScriptFactory implements ScriptFactory {
private static Logger logger =
Logger.getLogger(JythonScriptFactory.class);

private final String scriptSourceLocator;
private final Class[] scriptInterfaces;

public JythonScriptFactory(String scriptSourceLocator,
Class[] scriptInterfaces) {
Assert.hasText(scriptSourceLocator);
Assert.notEmpty(scriptInterfaces);
this.scriptSourceLocator = scriptSourceLocator;
this.scriptInterfaces = scriptInterfaces;
}

public String getScriptSourceLocator() {
return this.scriptSourceLocator;
}

public Class[] getScriptInterfaces() {
return this.scriptInterfaces;
}

public boolean requiresConfigInterface() {
return true;
}

public Object getScriptedObject(ScriptSource scriptSourceLocator,
Class[] scriptInterfaces)
throws IOException, ScriptCompilationException {
String strScript = scriptSourceLocator.getScriptAsString();

if (scriptInterfaces.length > 0) {
try {
PythonInterpreter interp = new PythonInterpreter();
interp.exec(strScript);
interp.exec("this = getInstance()");
return interp.get("this", scriptInterfaces[0]);
} catch (Exception ex) {
throw new ScriptCompilationException(ex.getMessage());
}
}
logger.error("No scriptInterfaces provided. ");
return null;
}
}


Junit Test case:

package org.yweng.spike.Spring;

import junit.framework.TestCase;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.apache.log4j.Logger;

public class TestJythonScriptFactory extends TestCase {
private static Logger logger = Logger.getLogger(TestJythonScriptFactory.class);

private ApplicationContext ctx =
new ClassPathXmlApplicationContext("org/yweng/spike/Spring/ApplicationContext.xml");

public void testPyMessenger() {
Messenger messenger = (Messenger)ctx.getBean("PyMessenger");
assertNotNull(messenger);
String msg = messenger.getMessage();
logger.info(msg);
}
}



It's not pretty but it works. :)

Saturday, February 11, 2006

The new Perforce Eclipse plugin

We had a lot of trouble with the "stable" version of the Perforce Eclipse Plugin (P4WSAD) in the past weeks. It mainly dues to the heavy load of our perforce servers and the "keep connected" nature of the perforce plugin. We were facing very long response time when we refactored our java code base. Because Eclipse's built-in refactoring does not do "p4 edit" on the files it modifies, we also have to spend some time to make sure all the modified files are in the change list. The experience is so painful that we almost decide to switch to subversion and use svk to sync between subversion and perforce repositories.

Today, I decided to give the beta version of perforce plugin a try. And I am happy I did. The new plugin introduces "unmanage" mode. The Eclipse project is disconnected with the Perforce server under this mode. Sweet!

Besides the "unmanage" feature, I have found two other features were very useful. One of them is "check consistency". The plugin can find out which files should be "edited" or "added" and put them in default change list after the refactoring. So you don't need to figure it out by yourself. Another one is "exclude from source control". You can exclude some generated artifacts from the version control so that "check consistency" won't always put them in your default change list. (This feature might be in the old version already. )

It looks like the new plugin solves most of our problems. However, there is one more thing. :) Merge is still difficult inside the perfoce plugin. P4V is still better than the plug-in in this area.

Thursday, February 09, 2006

Borland is going to sell its most valuable product line

Borland made another interesting decision: selling its famous development tools product line. Without Delphi, C++ builder, JBuilder and Interbase, is Borland "the Borland" we were talking about?

Saturday, October 15, 2005

Convert MSIL to Java bytecode

Grasshopper is a patent-pending compiler that compiles MSIL into java byte code. Nice solution for portability.

Sunday, October 09, 2005

The Anatomy of a Search Engine

The Anatomy of a Search Engine explains google's motivation and initial architecture. Besides learning good concepts such as PageRank and Anchor Text, I finally know what role Python plays in the in google's early days: The URL Server and the web crawlers. :)

Saturday, October 08, 2005

Eclipse CDT 3.0 test drive

I have used CDT 2.0 before and I felt it was not ready for big projects. Now the new CDT 3.0 has been out for a while. I already saw several reviews online talking about it. One of them is from Robert O'Callahan. He was trying to use CDT 3.0 against Mozilla code base. He mentioned that he actually managed to index most of the Mozilla and get code complete work. This is impressive considering the fact that Mozilla code base has more than 6000 C/C++ files.

It's very common for enterprise developers to analyze big legacy code. The ability to index big code base will save developer tons of time to understand legacy code. LXR, ctags and cscope can do an ok job on this, but the index result from these tools are far from prefect. So I want to try CDT 3.0 by myself and see how good it is.

My working environment:
  • OS: Fedora Core 4, kernel 2.6.13
  • CPU: P4 3.0 G
  • RAM: 1.5 G
  • CC: GCC 4.0.1-5
  • Eclipse: 3.1 with CDT 3.0
I decided to test CDT against firebird database code base. I checked out firebird 2 folder from sourceforge cvs server using Eclipse's cvs perspective, and imported it as a c++ project. CDT automatically started indexing after the creation of the project. There are about 2000 files under the firebird 2 folder, so the initial indexing process was really slow. After a while, CDT seemed stop indexing when the indexing is 40% done. Every time I went back to check the indexing status, the progress bar always told me it was 40% done. Well, it looked like Eclipse needed more memory to get this work done. So I closed Eclipse and changed the maxim heap size for Eclipse to 1G. After this change, CDT did successfully index firebird project.

I tried searching declaration, definition and reference, the speed was pretty good. Refactoring is a little bit weak. Only "rename" is available.

keep tuned. :)

Saturday, September 24, 2005

Install Skype on Fedora Core 4 | de-generationx.net

A good trick, you can use the fedora core 3 version skype rpm.