Saturday, May 05, 2007

New version of Scriptlandia: 2.2.1 has been released!

This release includes new features and new supported languages. The full list of
supported languages include:

- Javascript (1.6R4);
- Groovy (1.1-beta1);
- Beanshell (2.0b5);
- Jelly (1.0);
- JRuby (0.9.9);
- Jython (2.2b1);
- Pnuts (1.1);
- Jaskell (1.0);
- JScheme (7.2);
- TCL (1.4.0);
- AWK (0.14);
- f3 (?.?);
- Fortress (build 156);
- Scala (2.4.0);
- Sleep (2.1-beta15);
- Janino (2.5.5);
- Scriptella (0.7);
- Velocity (1.4);
- Freemarker (2.3.9);
- Ant (1.7.0);
- Maven (2.0.6).

Scriptlandia: what is it? It's the effort to build scripting command line environment on top of JVM. The user don't have to worry how to install or configure libraries for different scripting languages. It will be done automatically at installation and/or at execution time.

This project is useful for doing fast prototyping in your favorite language without spending time at all on installation/configuration (AKA CoC - convention over Configuration). It's also good for building simple command-line tools.

How is it different, say, from scripting-for-java project?

1. It's not tied to Java 6 platform. You can use Java 5; it's possible to have this code ready for java 1.4.

2. You can specify dependencies for the language in the form of dependencies file (currently it is based on maven 2 pom.xml format). As the result, these dependencies will be downloaded automatically from the server to your local repository when it's required.

3. It's easy to build environment in which scripts are aware of each other. It can be done by adding new dependencies, not through ancient CLASSPATH approach, but rather through dependencies file.

4. Language gear is available through the file extension. Thanks to jdic project, corresponding gear will be executed, based on file extension.

5. Based on extension, different convenient programs-launchers can be assigned to existing extensions like jar, war etc. As an example, if jar represents micro-edition application, suitable launcher will be started. In another example we can associate jar file with ant script and extend available commands for jar file, but everything whatever could be expressed as ant target.

6. New extensions are introduced: .sl (scriptlandia) and .cw (classworld). They can be used for starting arbitrary programs with correct dependencies specified. See examples: "cafebabe", "jclasslib", "udoc", "jlgui" for details.

7. Ant and Maven scripts are first-class citizens: you can interpret them as yet another scripting languages.

8. Scriptlandia is integrated with Nailgun server. It means that for simple scripts you can keep JVM in-memory, drastically reducing start-up time for running scripts.

9. It is not nescessary to install all dependencies at installation time. Installer program will download and install only minimally required libraries. The rest will be downloaded when you invoke fitst time the script.

Friday, April 06, 2007

New plugin for Intellij IDEA: translate text from one language to another (translate.google.com)

This plugin performs translations in Intellij IDEA Editor Window from one language to another (e.g. from Russian to Spain). It uses "http://translate.google.com" service behind the scene.

Plugin is especially convenient when you are trying to translate long i18n property files in your project for different languages.

Plugin adds "Translate" item into popup menu for the editor (also, in "Code" menu and "Generate" group). It also have separate configuration screen for selecting "from" and "to" languages.

How to use

1. Select the part to be translated;
2. Select "Translate" item from popup menu;
3. "translate.google.com" web site will perform actual translation;
4. Response from the service will be inserted in place of selection.

The project is located here.

Wednesday, April 04, 2007

How to build java presistence example with maven2

Here I will show how to build a very simple example that uses java persistence API. In order to simplify the build process I use maven 2. As the result, example archive is very short in size and all required libraries will be downloaded automatically only when it's really required.

1. Create new Java class, where you map java class/properties to database table/fields. Java persistence annotations will do this job for us:


import javax.persistence.*;

@Entity
@Table(name = "MESSAGES")
public class Message {

  @Id @GeneratedValue @Column(name = "MESSAGE_ID")
  private Long id;

  @Column(name = "MESSAGE_TEXT")
  private String text;

  @ManyToOne(cascade = CascadeType.ALL) @JoinColumn(name = "NEXT_MESSAGE_ID")
  private Message nextMessage;

  public Message() {}

  public Message(String text) {
    this.text = text;
  }

  // getter and setter methods for java properties
  ...
}


As you can see, "Message" class is mapped to "MESSAGES" table, "id", "text" and "nextMessage" properties - to "MESSAGE_ID", "MESSAGE_TEXT" and "NEXT_MESSAGE_ID" fields.

2. Now we can create simple program that uses persistent "Message" object:


import java.util.*;
import javax.persistence.*;

public class HelloWorld {

  public static void main(String[] args) {

    // Start EntityManagerFactory
    EntityManagerFactory emf = Persistence.createEntityManagerFactory("helloworld");

    // First unit of work
    EntityManager em = emf.createEntityManager();
    EntityTransaction tx = em.getTransaction();
    tx.begin();

    Message message = new Message("Hello World with JPA");
    em.persist(message);

    tx.commit();
    em.close();

    // Second unit of work
    EntityManager newEm = emf.createEntityManager();
    EntityTransaction newTx = newEm.getTransaction();
    newTx.begin();

    List messages =
        newEm.createQuery("select m from Message m order by m.text asc").getResultList();

    System.out.println( messages.size() + " message(s) found:" );

    for (Object m : messages) {
      Message loadedMsg = (Message) m;
      System.out.println(loadedMsg.getText());
    }

    newTx.commit();
    newEm.close();

    // Shutting down the application
    emf.close();
  }

}


This example does not refer to any persistent framework directly. Instead, it uses symvolic names to get access to the framework in indirect way. In the abovementioned example we have "helloworld" name to refer to.

So, who is doing the persistence work here? We can use various frameworks here, but they should comply with java persistence API. For example, Hibernate or Toplink.

3. In this example we use Hibernate (http://hibernate.org) as persistence framework and hsqldb (http://hsqldb.org) as database. Let's take a look ad the hibernate configuration file (persistence.xml) where we describe "helloworld" factory:


<persistence xmlns="http://java.sun.com/xml/ns/persistence"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
   http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
   version="1.0">

  <!-- persistence.xml -->

  <persistence-unit name="helloworld">

    <!-- The provider only needs to be set if you use several JPA providers -->
    <provider>org.hibernate.ejb.HibernatePersistence</provider>

    <properties>
      <!-- Scan for annotated classes and Hibernate mapping XML files -->
      <property name="hibernate.archive.autodetection" value="class, hbm"/>

      <!-- SQL stdout logging -->
      <property name="hibernate.show_sql" value="true"/>
      <property name="hibernate.format_sql" value="true"/>
      <property name="use_sql_comments" value="true"/>

      <property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/>

      <property name="hibernate.connection.driver_class" value="org.hsqldb.jdbcDriver"/>
      <property name="hibernate.connection.url" value="jdbc:hsqldb:file:persistence-db/test"/>
      <property name="hibernate.connection.username" value="sa"/>
      <property name="hibernate.hbm2ddl.auto" value="create"/>

      <property name="hibernate.c3p0.min_size" value="5"/>
      <property name="hibernate.c3p0.max_size" value="20"/>
      <property name="hibernate.c3p0.timeout" value="300"/>
      <property name="hibernate.c3p0.max_statements" value="50"/>
      <property name="hibernate.c3p0.idle_test_period" value="3000"/>
    </properties>
  </persistence-unit>

</persistence>


This file should be located on your CLASSPATH within META-INF directory. "hibernate.hbm2ddl.auto" property will take care of creating database table automatically.

4. Maven 2 file is responsible of downloading all dependent libraries, building correct CLASSPATH for the project and running the example (we use "exec:java" plugin for it):


<?xml version="1.0" encoding="UTF-8"?>

<project>
  <modelVersion>4.0.0</modelVersion>

  <groupId>persistence-deps</groupId>
  <artifactId>persistence-deps</artifactId>
  <version>1.0</version>

  <dependencies>
    <dependency>
      <groupId>commons-logging</groupId>
      <artifactId>commons-logging</artifactId>
      <version>1.0.4</version>
    </dependency>

    <dependency>
      <groupId>hsqldb</groupId>
      <artifactId>hsqldb</artifactId>
      <version>1.8.0.7</version>
    </dependency>

    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate</artifactId>
      <version>3.2.2.ga</version>
    </dependency>

    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-annotations</artifactId>
      <version>3.2.1.ga</version>
    </dependency>

    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-entitymanager</artifactId>
      <version>3.2.1.ga</version>
    </dependency>

    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-tools</artifactId>
      <version>3.2.0.beta9a</version>
    </dependency>

    <dependency>
      <groupId>c3p0</groupId>
      <artifactId>c3p0</artifactId>
      <version>0.9.1</version>
    </dependency>
  </dependencies>

  <build>
    <defaultGoal>compile</defaultGoal>

    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <configuration>
          <source>1.5</source>
          <target>1.5</target>
        </configuration>
      </plugin>

      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>exec-maven-plugin</artifactId>
        <executions>
          <execution>
            <goals>
              <goal>java</goal>
            </goals>
          </execution>
        </executions>

        <configuration>
          <mainClass>hello.HelloWorld</mainClass>
        </configuration>
      </plugin>
    </plugins>
  </build>

  <repositories>
    <repository>
      <id>scriptlandia-repo</id>
      <name>Scriptlandia Maven2 repository</name>
      <url>http://scriptlandia-repository.googlecode.com/svn/trunk/tools</url>
    </repository>
  </repositories>
</project>


5. Now, you can run compete example in one line:


>mvn compile exec:java


Complete example is located here.

Tuesday, April 03, 2007

How to compile and run Scala program with Ant and Maven 2

We have small scala program:


// HelloWorld.scala

object HelloWorld {

  def main(args: Array[String]) = {
    Console.println("Hello, world!")
  }

}


and want to compile/run it. In order to do it, we have to perform some additional steps.



    Compile/run with Ant


a). Scala is preinstalled

You need to have "scala-library" and "scala compiler" libraries in order to compile Scala programs.
You can download them from Scala web site (http://scala-lang.org).

Your ant script will start with the following lines:


<!-- 1. Define common properties. -->

<property name="src.dir" value="src/main/scala"/>
<property name="build.dir" value="target/classes"/>

<property name="repository.home" value="c:/maven-repository"/>
<property name="scala-compiler.jar" value="${repository.home}/scala/scala-compiler/2.4.0/scala-compiler-2.4.0.jar"/>
<property name="scala-library.jar" value="${repository.home}/scala/scala-library/2.4.0/scala-library-2.4.0.jar"/>

<!-- 2. Define Scala CLASSPATH. -->

<path id="scala.classpath">
  <pathelement location="${scala-compiler.jar}"/>
  <pathelement location="${scala-library.jar}"/>
</path>

<!-- 3. Define project CLASSPATH. -->

<path id="project.classpath">
  <path refid="scala.classpath"/>

  <pathelement location="${build.dir}"/>
</path>

<!-- 4. Define scala compiler command. -->

<taskdef resource="scala/tools/ant/antlib.xml">
  <classpath refid="scala.classpath"/>
</taskdef>


Now you can compile sources by using "scalac" command:


<!-- 5. Compiles sources by using "scalac" command. -->

<target name="compile">
  <mkdir dir="${build.dir}"/>

  <scalac srcdir="${src.dir}" destdir="${build.dir}" classpathref="project.classpath" force="changed">
    <include name="**/*.scala"/>
  </scalac>
</target>


Once compiled, you can run scala program:


<!-- 6. Runs scala executable. -->

<target name="run" depends="compile">
  <java classname="scala.tools.nsc.MainGenericRunner" fork="true">
    <classpath>
      <path refid="project.classpath"/>
    </classpath>

    <arg line="HelloWorld"/>
  </java>
</target>


Run this command:


>ant run


It will compile and then run scala example.


b). scala is being installed by maven 2


If you don't want to install scala libraries manually, you can use maven tasks for ant
(see http://maven.apache.org/ant-tasks.html for further details):


<project name="scala-compile-test2" default="compile" basedir="."
         xmlns:artifact="antlib:org.apache.maven.artifact.ant">

  <!-- 1. Define common properties. -->

  <property name="src.dir" value="src/main/scala"/>
  <property name="build.dir" value="target/classes"/>

  <!-- 2. Define Scala CLASSPATH with the help of Maven 2. -->

  <!--property name="repository.home" value="c:/maven-repository"/-->

  <artifact:localRepository id="local.repository" location="${repository.home}" layout="default"/>

  <artifact:pom file="scala-compile-test2.maven" id="maven.project" />

  <artifact:dependencies pathId="scala.classpath" filesetId="compile.fileset" useScope="compile">
    <pom refid="maven.project"/>
  </artifact:dependencies>


Steps 3-6 are the same as in previous example.


    Compile/run with Maven2


There are 2 maven plugings to work with scala sources. First plugin is implemented as
standard extension to the plexus compiler
(http://svn.codehaus.org/plexus/plexus-components/trunk/plexus-compiler/plexus-compilers).

The extension is located in the following repository:
http://scriptlandia-repository.googlecode.com/svn/trunk/languages

Another plugin for scala is implemented as regular maven plugin
(see details here: http://millstone.iodp.tamu.edu/~blambi/maven-scala-plugin).

a). plexus-compiler-scalac

First, you have to specify the location of scala sources. We'll do it with the help of
"build-helper-maven-plugin":


  <plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>build-helper-maven-plugin</artifactId>
    <executions>
      <execution>
        <id>add-source</id>
        <phase>generate-sources</phase>
        <goals>
          <goal>add-source</goal>
        </goals>
        <configuration>
          <sources>
            <source>src/main/scala</source>
          </sources>
        </configuration>
      </execution>
    </executions>
  </plugin>


Then you configure "maven-compiler-plugin" plugin:


  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <configuration>
      <compilerId>scalac</compilerId>

      <includes>
        <include>**</include>
      </includes>
    </configuration>

    <dependencies>
      <dependency>
        <groupId>org.codehaus.plexus</groupId>
        <artifactId>plexus-compiler-scalac</artifactId>
        <version>1.5.3</version>

        <scope>runtime</scope>
      </dependency>
    </dependencies>
  </plugin>


And don't forget about right repository:


  <repositories>
    <repository>
      <id>scriptlandia-repo</id>
      <name>Scriptlandia Maven2 repository</name>
      <url>http://scriptlandia-repository.googlecode.com/svn/trunk/languages</url>
    </repository>
  </repositories>


Now, compilation is easy:


>mvn compile


In order to run compiled code we'll use "exec" maven plugin:


  <plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>exec-maven-plugin</artifactId>
    <executions>
      <execution>
        <goals>
          <goal>java</goal>
        </goals>
      </execution>
    </executions>

    <configuration>
      <mainClass>HelloWorld</mainClass>
    </configuration>
  </plugin>


And run it:


>mvn exec:java


b). maven-scala-plugin

This plugin contains 2 parts: compiler and runner. It requires small configuration:


  <plugin>
    <groupId>iodp.usio</groupId>
    <artifactId>maven-scala-plugin</artifactId>

    <configuration>
      <mainClass>HelloWorld</mainClass>
    </configuration>
    <executions>
      <execution>
        <phase>compile</phase>
        <goals>
          <goal>compile</goal>
        </goals>
      </execution>
    </executions>
  </plugin>


You also have to specify the location of this plugin:


  <pluginRepositories>
    <pluginRepository>
      <id>maven2.iodp.usio</id>
      <name>IODP Maven2 Repository</name>
      <url>http://millstone.iodp.tamu.edu/maven2</url>
    </pluginRepository>
  </pluginRepositories>


Now you will be able to compile and run scala code now:


>mvn scala:compile

>mvn scala:run -DmainClass=HelloWorld

Wednesday, March 28, 2007

How to build completely dynamic example with Spring 2, Scriptlandia, Beanshell, Groovy and JRuby (revisited)

I made small modifications to previously explained example in order to use the custom dynamic language tags from Spring 2 to define dynamic-language-backed beans. Finally, the spring configuration file looks like

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:lang="http://www.springframework.org/schema/lang"
       xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang-2.0.xsd">

  <!-- Creates cat. -->
  <lang:groovy id="cat" script-source="classpath:Cat.groovy">
    <lang:property name="name" value="cat-name"/>
  </lang:groovy>

  <!-- Creates dog. -->
  <lang:jruby id="dog" script-interfaces="Animal" script-source="classpath:Dog.ruby"
              refresh-check-delay="5000"> <!-- switches refreshing on with 5 seconds between checks -->

    <lang:property name="name" value="dog-name"/>
  </lang:jruby>

  <!-- Creates cow. -->
  <lang:bsh id="cow" script-interfaces="Animal" script-source="classpath:Cow.bsh">
    <lang:property name="name" value="cow-name"/>
  </lang:bsh>

  <!-- Creates ant (inline script). -->
  <lang:groovy id="ant">
    <lang:inline-script>
      class Ant implements Animal {
        String name

        void makeSound() {
          println name + ": Shhh..."
        }
      }
    </lang:inline-script>
    <lang:property name="name" value="ant-name" />
  </lang:groovy>

  <!-- Creates animal farm. -->
  <bean id="farm" class="AnimalFarm">
    <property name="animals">
      <list>
        <ref bean="cat"/>
        <ref bean="dog"/>
        <ref bean="cow"/>
        <ref bean="ant"/>
      </list>
    </property>
  </bean>

</beans>



The final version of example is located here.

Monday, March 19, 2007

How to build completely dynamic example with Spring 2, Scriptlandia, Beanshell, Groovy and JRuby

Recently, I found this project: GroovyWorks;.
It tries to use together such things as Java, Groovy, Spring 2 and Struts 2. Because Struts actions are written as Groovy scripts, it is not required to restart web application for each and every change. It is possible because of dynamic nature of Groovy language.

But still, it's not completely dynamic. Small portion of the system is written in Java and for each change in Java you have to recompile and redeploy your web application. Is it possible to make it completely dynamic?

In the following lines I will explain how to build such completely dynamic code. It is standalone application, so Struts 2 is not required. But we still want to have IoC container. Spring 2 fits for our needs, especially with new struts-scripting library, that supports 3 popular languages: Groovy, JRuby and Beanshell.

1. In order to work with scripts inside Spring 2 we have to create Java classes first. Let's create animal farm that consists of animals:


// Animal.java

public interface Animal {

public void makeSound();

}

// AnimalFarm.java

import java.util.List;

public class AnimalFarm {
private List animals;

public AnimalFarm() {
System.out.println("New Animal farm has been created.");
}

public void setAnimals(List animals) {
this.animals = animals;
}

public void wakeUp() {
for(int i=0; i < animals.size(); i++) {
Animal animal = (Animal)animals.get(i);

animal.makeSound();
}
}

}


2. Now, we can implements different animals in different languages:


// Cat.groovy

class Cat implements Animal {

void makeSound() {
println "Meow!"
}

}

# Dog.rb

require "java"

include_class("Animal")

class Dog < Animal
def makeSound
puts "Bark!!!"
end
end

Dog.new

// Cow.bsh

void makeSound() {
System.out.println("Moo...");
}


3. We'll keep all required libraries in the form of maven2 dependencies file.
Because current version of spring (2.0.3) is not compatible with jruby version 0.9.8
(see bug SPR-3255),
we have to keep reference to temporary repository:
http://scriptlandia-repository.googlecode.com/svn/trunk/patches.

4. All required beans are defined inside spring file:


<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

<!-- dynamo-test.xml -->

<beans>
<!-- Enables spring-scripting. -->
<bean class="org.springframework.scripting.support.ScriptFactoryPostProcessor"/>

<!-- Creates cat. -->
<bean id="cat" class="org.springframework.scripting.groovy.GroovyScriptFactory">
<constructor-arg value="file:Cat.groovy" />
</bean>

<!-- Creates dog. -->
<bean id="dog" class="org.springframework.scripting.jruby.JRubyScriptFactory">
<constructor-arg value="file:Dog.ruby" />
<constructor-arg value="Animal" />
</bean>

<!-- Creates cow. -->
<bean id="cow" class="org.springframework.scripting.bsh.BshScriptFactory">
<constructor-arg value="file:Cow.bsh" />
<constructor-arg value="Animal" />
</bean>

<!-- Creates animal farm. -->
<bean id="farm" class="AnimalFarm">
<property name="animals">
<list>
<ref bean="cat"/>
<ref bean="dog"/>
<ref bean="cow"/>
</list>
</property>
</bean>
</beans>


5. The trickiest part here is how to avoid compilation of java code, making code
completely dynamic. To achieve it, we use janino library (http://www.janino.net/)
with JavaSourceClassLoader. We load class from source file, retrieve it as array of bytes
and then add this array as a class to our class loader.

To load required classes/libraries to CLASSPATH we use Scriptlandia API (http://scriptlandia.sf.net).
The complete example is represented below:


// dynamo-test.bsh

org.sf.scriptlandia.ScriptlandiaHelper.addMavenDependencies("pom.xml");

import org.sf.scriptlandia.launcher.ScriptlandiaLauncher;
import org.codehaus.janino.*;

import org.sf.scriptlandia.util.*;
import org.codehaus.classworlds.ClassRealm;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;


public class Dynamo {
private ClassRealm classRealm;
private ApplicationContext factory;

public Dynamo(String basedir, String[] classNames, String beansFile) {
ScriptlandiaLauncher launcher = ScriptlandiaLauncher.getInstance();

classRealm = launcher.getMainRealm();

register(basedir, classNames);

factory = new FileSystemXmlApplicationContext(new String[] { basedir + "/" + beansFile });
}

private void register(String basedir, String[] classNames) {
ScriptlandiaLauncher launcher = ScriptlandiaLauncher.getInstance();

ClassLoader sourceClassloader = new JavaSourceClassLoader(
launcher.getClass().getClassLoader(), // parentClassLoader
new File[] { new File(basedir) }, // optionalSourcePath
(String) null, // optionalCharacterEncoding
DebuggingInformation.NONE // debuggingInformation
);

for(int i=0; i < classNames.length; i++) {
loadClass(classNames[i], sourceClassloader);
}
}

/**
* Loads class specified by the name.
*/
private void loadClass(String name, ClassLoader classLoader) {
String[] args = new String[] { name };

Map bytecodes = ReflectionUtil.invokePrivateMethod(
classLoader,
new Object[] { name },
JavaSourceClassLoader.class,
"generateBytecodes",
new Class[] { String.class });

classRealm.addConstituent(name, bytecodes.get(name));
}

public Object getBean(String beanName) {
return factory.getBean(beanName);
}

public static void main(String[] args) throws Exception {
// Java classes that needs to be registered.
String[] classNames = new String[] {"Animal", "AnimalFarm" };
String basedir = System.getProperty("user.dir");

Dynamo dynamo = new Dynamo(basedir, classNames, "dynamo-test.xml");

AnimalFarm animalFarm = dynamo.getBean("farm");

animalFarm.wakeUp();
}

}

Thursday, March 08, 2007

Building GUI frontend for Maven2 archetype plugin (Beanshell, Swing, Scriptlandia)

There are multiple archetypes available for developers:
  • standard Maven 2 distribution contains 5 archetypes: "archetype", "j2ee-simple", "mojo", "quickstart", "site", "webapp";
  • AppFuse 2.0 project (http://appfuse.org) now is rewritten in form of different archetypes (8): "basic-jsf", "basic-spring", "basic-struts", "basic-tapestry", "modular-jsf", "modular-spring", "modular-struts", "modular-tapestry";
  • WebTide site (http://www.webtide.com/resources.jsp) published archetypes for web development (10): "ActiveMQ", "DOJO", "DWR", "JSF", "SiteMesh", "Spring", "SpringJpa", "Struts", "Tapestry", "WebWork";
  • JPA 101 (http://jroller.com/page/cmaki?entry=jpa_maven_2_archetype) archetype ("hibernate-archetype").
How to handle this amount of different types?

I wrote simple front-end with the help of Swing and Beanshell that displays all input parameters for the project (group ID, artifact ID, version and arche-type). After selecting appropriate archetype and clicking on "Create archetype" button, new project will be created in the current directory.

The source for this script is located here: create-archetype.bsh.

This program uses behind the scene Scriptlandia API to execute maven2 tool:

ScriptlandiaHelper.executeMaven(args);

After this work is done, it's easy to create simple starters for different archetype implementations.

For starting standard maven 2 archetypes:

// maven-archetype.bsh

sourceRelative("create-archetype.bsh");

String[] archetypes = {
"archetype", "j2ee-simple", "mojo", "quickstart", "site", "webapp"
};


CreateArchetype frame = new CreateArchetype("WebTide");

frame.setArchetypes(archetypes);
frame.setArchetypeGroupId("org.apache.maven.archetypes");
frame.setArchetypeArtifactIdPrefix("maven-archetype-");
frame.setArchetypeVersion("1.0");

frame.setVisible(true);

For starting AppFuse archetypes:

// appfuse-archetype.bsh

sourceRelative("create-archetype.bsh");

String[] archetypes = {
"basic-jsf", "basic-spring", "basic-struts", "basic-tapestry",
"modular-jsf", "modular-spring", "modular-struts", "modular-tapestry"
};


CreateArchetype frame = new CreateArchetype("Appfuse");

frame.setArchetypes(archetypes);
frame.setArchetypeGroupId("org.appfuse");
frame.setArchetypeArtifactIdPrefix("appfuse-");
frame.setArchetypeVersion("1.0-m3");
frame.setRemoteRepositories("http://static.appfuse.org/repository");

frame.setVisible(true);


For starting WebTide archetypes:

// webtide-archetype.bsh
// Resource: http://www.webtide.com/resources.jsp

sourceRelative("create-archetype.bsh");

String[] archetypes = {
"ActiveMQ", "DOJO", "DWR", "JSF", "SiteMesh", "Spring", "SpringJpa", "Struts", "Tapestry", "WebWork"
};


CreateArchetype frame = new CreateArchetype("WebTide");

frame.setArchetypes(archetypes);
frame.setArchetypeGroupId("com.webtide");
frame.setArchetypeArtifactIdPrefix("maven-archetype-");
frame.setArchetypeVersion("1.0");
frame.setRemoteRepositories("http://scriptlandia-repository.googlecode.com/svn/trunk/tools");

frame.setVisible(true);


For starting Jpa 101 archetype:

// jpa-archetype.bsh

// Resource: http://jroller.com/page/cmaki?entry=jpa_maven_2_archetype

sourceRelative("create-archetype.bsh");

String[] archetypes = {
"hibernate-archetype"
};

CreateArchetype frame = new CreateArchetype("JPA");

frame.setArchetypes(archetypes);
frame.setArchetypeGroupId("com.sourcebeat");
frame.setArchetypeArtifactIdPrefix("jpa-");
frame.setArchetypeVersion("1.0-SNAPSHOT");
frame.setRemoteRepositories("http://scriptlandia-repository.googlecode.com/svn/trunk/tools");

frame.setVisible(true);

Wednesday, March 07, 2007

New version of Scriptlandia: 2.2.0 has been released!

This release includes new features and new supported languages. The full list of
supported languages include:

- Javascript (1.6R4);
- Groovy (1.0);
- Beanshell (2.0b5);
- Jelly (1.0);
- JRuby (0.9.8);
- Jython (2.2b1);
- Pnuts (1.1);
- Jaskell (1.0);
- JScheme (7.2);
- TCL (1.4.0);
- AWK (0.14);
- f3 (?.?);
- Fortress (?.?);
- Scala (2.3.3);
- Janino (2.5.5);
- Scriptella (0.7);
- Velocity (1.4);
- Freemarker (2.3.9);
- Ant (1.7.0);
- Maven (2.0.5).

What is it: Scriptlandia? It's the effort to build environment on top of JVM. The user don't have
to worry how to install or configure libraries for different scripting languages. It will be done
automatically at installation and/or at execution time.

This project is useful for doing fast prototyping in your favorite language without spending time
on installation/configuration (aka CoC). It's also good for building simple command-line tools.

How is it different from, say scripting-for-java project?

1. It's not tied to Java 6 platform. You can use Java 5; it's possible to have this code ready for java 1.4.

2. You can specify dependencies for the language in the form of maven 2 project file. As the result, these dependencies will be downloaded automatically from the server to your local repository.

3. It's easy to build environment in which scripts are aware of each other. It can be done by adding new dependencies (not through ancient CLASSPATH approach).

4. Language gear is available through the file extension. Thanks to jdic project, corresponding
gear will be executed, based on extension.

5. Based on extension, different convenient programs-launchers can be assigned to existing extensions like jar, war etc. As an example, if jar represents micro-edition application, suitable launcher will be started. In another example we can associate jar file with ant script and extend available commands for jar file (now execute command only, see jdk documentation), but everything whatever could be expressed as ant target.

6. New extensions are introduced: .sl (scriptlandia) and .cw (classworld). They are used for starting arbitrary programs with correct dependencies specified.

7. Ant and Maven scripts are first-class citizens: you can interpret them as another scripting languages.

8. Scriptlandia is integrated with Nailgun server. It means that for simple scripts you can keep
JVM in-memory, drastically reducing start-up time for running scripts.

Wednesday, December 13, 2006

New JiniExamples (2.1.001) Project

This new project is dedicated to Jini Technology. It is reincarnation of my very old project for Jini ver. 1.0. Now it's adapted to Jini ver. 2.1.

The project includes 22 examples, starting from simplest toward more practical examples. The advantages of this project over another similar projects are:
- up to date examples;
- ready to use Ant scripts (zero configuration);
- Maven 2 project file for automatic downloads of required dependent files.

As the result, even beginner could start examples before looking at actual sources for examples. And they are as simple as possible - I try to focus on one aspect only at the same time.

Hope it accelerates development speed as well as attracts more interest to this underestimated technology.

Structurally, all examples are divided into 3 groups:

Simple Tests

# Common tests
# Developing simple service
# Simple Remote Service over JERI
# Simple Remote Service over JERI started from configuration file
# Client as servlet/JSP
# Simple service as service UI

Advanced Tests

# Client listening for events
# Building event generator
# Administrable service
# Activatable Jeri service
# Administrable and Activatable service
# EventMailbox (mercury) example
# Norm example
# Fiddler example
# JavaSpace example
# JavaSpace (Blitz) examples
# Federate example
# Failover example

Practical Examples

# Jini and NetLib library
# Jini and Database
# Speaker service (Speech API)
# Jini Services for home (music, speech, time)

Wednesday, September 20, 2006

Java Kernel (Browser Edition)

It looks like Sun is trying to make right steps:

Ethan Nicholas's Blog

Feedback from Artima site

It's not only about the size, it's more about well designed system.

Wednesday, August 23, 2006

Friday, August 18, 2006

How to run Rails on JRuby

Im order to do it, you have to perform the following steps.


1. Install ruby interpreter into ${ruby.home} (e.g. c:\ruby-1.8.4-20).
You can download latest version for Windows from here:

http://rubyforge.org/frs/download.php/11926/ruby184-20.exe

Test it (check ruby version):

>ruby.exe -v


Ruby installation has packaging tool called gem. Test it's version:

>gem.bat -v



2. Install rails. You can do it in one command:

>gem.bat --no-rdoc --no-ri --include-dependencies install rails


If you are behind the proxy, download gems separately and then install them individually:

>gem.bat install --no-rdoc --no-ri activesupport-1.3.1.gem
>gem.bat install --no-rdoc --no-ri activerecord-1.14.4.gem
>gem.bat install --no-rdoc --no-ri actionpack-1.12.5.gem
>gem.bat install --no-rdoc --no-ri actionmailer-1.2.5.gem
>gem.bat install --no-rdoc --no-ri actionwebservice-1.1.6.gem
>gem.bat install --no-rdoc --no-ri RbYAML-0.1.0.gem
>gem.bat install --no-rdoc --no-ri rails-1.1.6.gem

All of these gem files could be downloaded from http://rubyforge.org site.

You can also update gem tool to the latest version:

>gem.bat install --no-rdoc --no-ri rubygems-update-0.9.0.gem

Test rails version:

>rails.bat -v



3. Install jruby library into ${jruby.home} folder (e.g. c:\jruby-0.9.1).
Prepare jruby.bat script file:

SET RUBY_HOME=c:\ruby-1.8.4-20
SET JRUBY_HOME=c:\jruby-0.9.1

SET CLASSPATH=%JRUBY_HOME%\lib\jruby.jar;%JRUBY_HOME%\lib\jvyaml.jar;%JRUBY_HOME%\lib\plaincharset.jar;%JRUBY_HOME%\lib\asm.jar

java -Djruby.home=%RUBY_HOME% -Djruby.shell="cmd.exe" -Djruby.script=jruby.bat -classpath %CLASSPATH% org.jruby.Main


The trick here is that we use native ruby libraries from ruby installation (not from jruby installation).

Now you can execute all commands, required for building/running Rails application.



4. Create new project (testrails). Keep in mind that the project will be created in the current directory:

>jruby.bat c:\ruby-1.8.4-20\bin\rails testrails


Newly generated project has already some commands inside, so we need to change the current directory:

>cd testrails



5. Modify testrails\config\database.yml to point to your database. By default, it's MySQL database.



6. Start the database. Create database for devepoment: testrails_development



7. Generate the model

>jruby.bat .\script\generate controller MyTest



8. Generate the controller

>jruby.bat .\script\generate controller MyTest



9. Start the WEBrick server

>start jruby.bat .\script\server



10. Test if server is started properly in the browser:

>http://localhost:3000/my_test

Now you should see your view.


Rails on JRuby is very slow. Let's wait for improvements from JRuby team.

Monday, June 19, 2006

How to pre-compile JSP pages for Weblogic8 with Ant

It can be done in similar way as for Tomcat Application Server (see this link). The only difference is: we have another JSP compiler which takes different input parameters and expects JSP pages in well specified locations. It does not "like" JSP pages within WEB-INF folder, so you need to follow this rule. Otherwise you have to copy files with "wrong" locations into "right" locations.

1. Specify "project.classpath" for your project. It will include all jars required to compile or run your project:


<path id="project.classpath">
  ...
</path>


2. Specify "weblogic.jsp.classpath". You need to have Weblogic Web Server installed ar ${weblogic.home}. You also need to specify, where you have your implementation of logging system ("${repository.home}/log4j").


  <path id="weblogic.jsp.classpath">

    <!-- 1. You have to include jars from your project. -->

    <path refid="project.classpath"/>

    <!-- 2. Weblogic jsp compiler and dependent classes (including JavaEE/Servlet/JSP interface classes). -->

    <fileset dir="${weblogic.home}/server/lib">
      <include name="weblogic.jar"/>
    </fileset>

    <!-- 3. This library is required by Weblogic jsp compiler (not in weblogic installation!). -->

    <fileset dir="${repository.home}/saxpath">
      <include name="saxpath-1.0-FCS.jar"/>
    </fileset>

    <!-- 4. Weblogic jsp compiler internally uses Java compiler. -->

    <fileset dir="${java.home}/lib">
      <include name="tools.jar"/>
    </fileset>

    <fileset dir="${java.home}/../lib">
      <include name="tools.jar"/>
    </fileset>

    <!-- 5. Implementation of logging system (if it is not in "project.classpath" yet). -->

     <fileset dir="${global.repository.home}/log4j">
       <include name="log4j-1.2.8.jar"/>
     </fileset>
  </path>


3. Now we can generate Java sources for JSP files.


  <property name="jsp.src.dir" value="<the root for your JSP files>"/>
  <property name="jsp.package.name" value="<the package name for your JSPs, like com.mycompany.jsp>"/>

  <property name="build.dir" value="target/build"/>
  <property name="jsp.generated.src.dir" value="${build.dir}/jsp_sources"/>
  <property name="jsp.classes.dir" value="${build.dir}/jsp_classes"/>

  <target name="tomcat.jsp.generate">
    <mkdir dir="${jsp.generated.src.dir}"/>
    <mkdir dir="${jsp.classes.dir}"/>

    <java classname="org.apache.jasper.JspC" fork="yes">
      <classpath refid="tomcat.jsp.classpath" />

      <arg line="-uriroot ${jsp.src.dir} -d ${jsp.generated.src.dir} -p ${jsp.package.name} -webapp ${jsp.src.dir}" />
    </java>
  </target>

  <target name ="weblogic.jsp.generate">
    <mkdir dir="${jsp.generated.src.dir}"/>
    <mkdir dir="${jsp.classes.dir}"/>

    <java classname="weblogic.jspc" fork="yes">
      <classpath refid="weblogic.jsp.classpath" />

      <sysproperty key="weblogic.jsp.windows.caseSensitive" value="false"/>

      <arg line="-forceGeneration -keepgenerated -compileAll -webapp ${jsp.src.dir} -d ${jsp.generated.src.dir}"/>
    </java>
  </target>


It is very important to set "weblogic.jsp.windows.caseSensitive" to "false". At the same step Weblogic will compile Java sources into Java classes (-forceGeneration and -keepgenerated). Compiled JSP java classes will be located in same folders as JSP compiled classes. We will separate them on next step.

You don't have to specify package name for JSP pages. JSP compiler will assign default "jsp_servlet" package name for all JSP pages. Each folder will be converted with the "_" prefix plus original name, each jsp page into "__" prefix plus original name.

4. Now, it's better to separate generated Java sources from compiled files.


  <target name ="weblogic.jsp.compile" depends="weblogic.jsp.generate"
          description="Separates sources from classes">
    <move todir="${jsp.classes.dir}/jsp_servlet">
      <fileset dir="${jsp.generated.src.dir}/jsp_servlet">
        <include name="**/*.class"/>
      </fileset>
    </move>
  </target>


If, on this step you don't have compiler errors, your source code (JSP part) is not broken.

When you assemble war file, you should include everything from ${jsp.src.dir} folder except JSP files and their includes.

Friday, June 02, 2006

How to handle JSP Error Page

At first glance it looks like a very straightforward task.


1. Each JSP page should use "errorPage" attribute. For example:

<%-- /example.jsp --%>

<%@ page errorPage="/WEB-INF/templates/errorPage.jsp"%>

<%-- some JSP content --%>


If you don't want to repeat this for each JSP page, use Tiles template or specify error page in "web.xml" file:

<web-app>
  ...
 
  <error-page>
    <exception-type>java.lang.Throwable</exception-type>
    <location>/WEB-INF/templates/errorPage.jsp</location>
  </error-page>

  ...
 
</web-app>



This description registers "errorPage.jsp" JSP page as error page for all JSP pages within web application.


2. You need to create error page, which displays runtime exceptions:

<%-- /WEB-INF/templates/errorPage.jsp --%>

<%@ page isErrorPage="true" %>

<%
  out.println("Exception: " + exception);
%>



By using "isErrorPage" attribute you declare this JSP page as error page. As a result, you have access to "exception" JSP variable (in addition to regular "application", "session",
"request", etc.).


This is basic. The problem happened, when your JSP page generates big output (bigger than page buffer) before the exception. In this case your error page will be appended to the current content instead of displaying in the new page.

To overcome the problem you can:


3.A. Play with "buffer" attribute. Say, you know, that the size of your page will never be more than 1MB. In this case add these attributes to the page:


<%-- /example2.jsp --%>

<%@ page errorPage="/WEB-INF/templates/errorPage.jsp"%>

<%@ page buffer="1024kb"%>
<%@ page autoFlush="false"%>

<%-- some JSP content --%>


This approach is not perfect, because you cannot guarantee the maximum page size. Another drawback is that page will be refreshed only after completing the operation. This could hurt user's perception.


3.B.1. Use custom javascript code to clear flushed already output. By using "document.getElementById()" function we canget reference to the body and rewrite it:


<%-- /WEB-INF/templates/errorPage.jsp, ver.1 --%>

<%@ page isErrorPage="true" %>

<html>
  <head>
    <script type="text/javascript">
      function newPage() {
        var exception = '<%= exception %>';

        var body = document.getElementById("body");

        body.innerHTML =
            "<html>" +
            " <body>" +
            " Exception: " + exception +
            " </body>" +
            "</html>";
        }
      }
    </script>
  </head>

  <body/>

</html>


This solution fits for simple error pages only. If you want to display full-featured error page, you have to look for another solution (see 3.B.2).



3.B.2. Redirect to another page.


This scenario is based on 3.B.1 solution. Now, instead of preparing the content to display, we'll submit the form, redirecting the flow to the requested page. In order to get the reference to javascript's "document" obect and clear it, we'll use document.open()" function:


<%-- /WEB-INF/templates/errorPage.jsp, ver.2 --%>

<%@ page isErrorPage="true" %>

<%
  // We want to have exception available on the redirected page.
  session.setAttribute("javax.servlet.error.exception",
                        request.getAttribute("javax.servlet.error.exception"));
%>

<html>
  <head>
    <script type="text/javascript">
      function newPage(action) {
        var newDoc = document.open("text/html", true);

        if(newDoc) {
          var errorFormName = 'errorForm';
          var txt =
            "<html>" +
            " <body>" +
            " <form id='" + errorFormName + "' method='get'/>" +
            " </body>" +
            "</html>";

          newDoc.write(txt);
          newDoc.close();

          var form = newDoc.getElementById(errorFormName);
          form.action = action;
          form.submit();

          return true;
        }

        return false;
      }

      newPage("someURL"); // direct execution of javascript custom function
    </script>
  </head>

  <body/>

</html>


This solution does not work properly yet. The problem is, that at the time of javascript execution the html page is not completely generated yet. As the result, "document.open()" call will return "null" object and the conten for the redirection will not be generated. See 3.B.3 for the solution.


3.B.3. Using timer object.


This scenario is based on 3.B.2 solution. It is exactly the same, the only difference is how we call "newPage()" function. Instead of direct call we'll do it indirectly from the timer:

<%-- /WEB-INF/templates/errorPage.jsp, ver.3 --%>

<%@ page isErrorPage="true" %>

<%
  // We want to have exception available on the redirected page.
  session.setAttribute("javax.servlet.error.exception",
                        request.getAttribute("javax.servlet.error.exception"));
%>

<html>
  <head>
    <script type="text/javascript">
      function newPage(action) { ... }

      var timer = new Timer("timer");
      timer.setScript("newPage('someURL')");

      timer.start();
    </script>
  </head>

  <body/>

</html>


Timer is the special custom javascript class that performs call to a given script periodically until the script returns "true" value. After this, the timer will stop execution.

You can download inplementation for the timer from here:

http://home.comcast.net/~shvets/blog/timer.js

Now JSP error page work properly.

Wednesday, May 24, 2006

Search Engine for Maven 2 (and other Java artifacts) from SourceLabs.

CJAR is the combination of Maven2 structured repository of Java artifacts with powerful Lucene based search engine and related tools.

Tuesday, May 23, 2006

CafeBabe bytecode editor v.1.4 - welcome back!

This is my very old project - I started it probably in 1997-1998.

By using CafeBabe you can view/edit the content of Java bytecodes. Also it understands the format of serialized files. Initially the project had some oprimization/obfuscation tools. I removed them in favor of simplicity.

Project contains libraries that can be used separately:

* classfile - parsing of Java class file;
* serfile - parsing of Java *.ser file;
* MDI - represents Multi Document Interface implementation;
* Net Lib - library for working with sockets (similar to servlet API, but not attached to any container).

Project is well modularized and uses Maven 2 as the build (...) tool.