Thursday, January 28, 2010

Enable scala in your appengine/sculptor project

I've recently started to interest myself in the Scala language. It is a language that runs on the jvm. It's very rich in its syntax and it has a very pleasant mix of OO- and functional programming.
But since I always starts my explorations with the solid foundation of maven the first problem I encountered was how to integrate scala in my build process in a project that already mixes GAE and Sculptor. I.e. I start off from a project that has been created with our maven appengine archetype. So this is a log of my steps for making this happen.

1) In your pom, add a property for the version of Scala:


<scala.version>2.7.7</scala.version>


2) In your pom, add repository for scala:


<repository>
<id>scala-tools.org</id>
<name>Scala-Tools Maven2 Repository</name>
<url>http://scala-tools.org/repo-releases</url>
</repository>


3) In your pom , add pluginRepository:


<pluginRepository>
<id>scala-tools.org</id>
<name>Scala-Tools Maven2 Repository</name>
<url>http://scala-tools.org/repo-releases</url>
</pluginRepository>


4) In your pom, add dependency:


<dependency>
<groupId>org.scala-lang</groupId>
<artifactId>scala-library</artifactId>
<version>${scala.version}</version>
</dependency>


5) In your pom, add entry in maven-dependency-plugin in the build section:


<artifactItem>
<groupId>org.scala-lang</groupId>
<artifactId>scala-library</artifactId>
<version>${scala.version}</version>
<outputDirectory>war/WEB-INF/lib</outputDirectory>
</artifactItem>


6) In your pom, add dependency to specs-library (if you want it):


<dependency>
<groupId>org.specs</groupId>
<artifactId>specs</artifactId>
<version>1.4.3</version>
<scope>test</scope>
</dependency>


7) In your pom, add the scala-plugin to the build section:


<plugin>
<groupId>org.scala-tools</groupId>
<artifactId>maven-scala-plugin</artifactId>
<executions>
<execution>
<id>scala-compile-first</id>
<phase>process-resources</phase>
<goals>
<goal>add-source</goal>
<goal>compile</goal>
</goals>
</execution>
<execution>
<id>scala-test-compile</id>
<phase>process-test-resources</phase>
<goals>
<goal>testCompile</goal>
</goals>
</execution>
</executions>
<configuration>
<scalaVersion>${scala.version}</scalaVersion>
<args>
<arg>-target:jvm-1.5</arg>
</args>
</configuration>
</plugin>


8) In your project file structure, add a simple scala file: src/main/scala/org/foo/App.scala


package org.foo

/**
* Hello world!
*
*/
object App extends Application {
println( "Hello World!" )
}

9) In your project file structure, add a simple scala test: src/test/scala/org/foo/AppTest.scala


package org.foo

import org.junit._
import Assert._

@Test
class AppTest {

@Test
def testOK() = assertTrue(true)

}

10) In the root of your project file structure, run mvn install to see that everything builds ok

Tuesday, January 26, 2010

How to Remove Sculptor

When taking the decision to try a tool, such as Sculptor, it is important to know what it takes to stop using it if doesn't turn out as expected. Therefore I will in this post explain how to remove Sculptor. You don't have to do all steps and you don't have to do everything at once.

Step 1
The first step is to remove the code generation. This will take you less than 10 minutes.

a) In the maven pom.xml you remove the following:
  • plugin fornax-oaw-m2-plugin
  • plugin maven-clean-plugin
  • plugin fornax-checksum-m2-plugin
  • dependency fornax-cartridges-sculptor-generator
b) Remove these files in src/main/resources:
  • model files, .btdesign, .guidesign
  • sculptor-generator.properties
  • templates/SpecialCases.xpt
  • extensions/SpecialCases.ext
c) Move generated files
  • src/generated/java -> src/main/java
  • src/generated/resources -> src/main/resources
  • src/test/generated/java -> src/test/java
  • src/test/generated/resources -> src/test/resources
d) Run mvn eclipse:eclipse to generate eclipse project without generated source directories

Step 2
You don't need to do more right away, but later you would probably like to refactor the gap classes. Separation of generated and manually written code is done by a generated base class and manually written subclass. E.g. Person and PersonBase. You would probably like to collapse those into one class. To do this you can use the 'Push Down' refactoring in Eclipse, or simply copy paste the code from the base class to the subclass, and remove the extension.

This takes a few minutes per class, so you should be able to do a whole project within a few hours. It is a trivial and safe refactoring.

Step 3
Sculptor is a development tool, but it also has a small runtime library, with classes of utility and general character. This blog post explains why we have a runtime library. You can continue to use those classes as is. If you feel uncomfortable with that you can copy the source and remove classes that you don't use. The runtime library is not advanced at all, and you will have no problems to understan, maintain and change it as you need.

Thursday, January 21, 2010

Why we Combine Code Generator with Runtime Library

Sculptor is a development tool, but it also has a small runtime library. Some people find it scaring to bring in yet another library in their software stack.

It contains classes of utility and general character. It is not advanced at all. We could have generated those also and have no runtime dependency at all. Instead, we try to only generate things that must be variable, such as application specific structure and glue code. Static content should not be generated.

If we would have decided to not use a runtime library I think it would be a high risk that we would have generated code with bad design, such as repeated, duplicated code. We think in terms of DRY for the generated code. We always try to produce code as if we would have written it by hand, without a code generator. There are some exceptions to this rule, for example separation of generated and hand written code in separate classes.

It is interesting to compare Spring Roo and Sculptor. I see a lot of similarities, but also differences. One difference related to this topic is that Roo doesn't have a runtime library (except ordinary Spring Framework). They generate everything. They are using this as a selling point, but I think they have fallen into the trap of generating duplicated code. Take a look at the persistence methods in the ITD for an Entity.
   @Transactional 
public void Planet.remove() {
if (this.entityManager == null) this.entityManager = entityManager();
if (this.entityManager.contains(this)) {
this.entityManager.remove(this);
} else {
Planet attached = this.entityManager.find(Planet.class, this.id);
this.entityManager.remove(attached);
}
}
What happens if you decide to remove Roo? Then you will have to maintain a lot of duplicated code, that was generated initially. I think it illustrates how easy it is to forget or not bother about ordinary design principles when you solve everything with code generation. DRY should of course be used even when you have a code generator in your hands.

In Sculptor we have placed the general persistence operations in parameterized access objects, in the runtime library.

Saturday, January 16, 2010

Pick 'n' Choose Target Implementation

This article gives an overview of the options you have regarding the generated target implementation. We add new stuff all the time so this describes what is available at the time of this writing, i.e. in Sculptor 1.7.0.

The default target implementation is using:
  • JPA with Hibernate as provider
  • Spring with annotations, no EJBs
  • Web CRUD GUI client with JSF, Facelets, and Spring Web Flow
  • In-memory Hsqldb as database
  • Deployment as war in Jetty
The default choices gives a good starting environment with minimal requirements of installation of external software, such as database and application server.

For each of these areas there are alternative implementations that are supported by Sculptor out of the box. The features are selected with simple configuration.

















If you have a different reference architecture than what is provided by Sculptor out of the box you can rather easily customize the generator to fit your needs. It is possible to add your own code generator templates or redefine sections of existing templates. All that is described in the Developer's Guide.

Test Scaffold

I must admit that when I use Sculptor I often skip completing the JUnit tests for the ordinary CRUD operations. To my defense I would say that they are trivial and completely generated, but anyway I think that is a bad habit that should be changed. Therefore I wrote a small Eclipse template for them. Maybe useful for you also:


@${testType:newType(org.junit.Test)}
public void testFindById() throws Exception {
${DomainObject:localVar(org.fornax.cartridges.sculptor.framework.domain.AbstractDomainObject)} obj = ${service:field}.findById(getServiceContext(), 1L);
assertNotNull(obj);
}

@${testType:newType(org.junit.Test)}(expected=${DomainObject}NotFoundException.class)
public void testFindByIdWithNotFoundException() throws Exception {
${service}.findById(getServiceContext(), -1L);
}

@${testType:newType(org.junit.Test)}
public void testFindAll() throws Exception {
${listType:newType(java.util.List)}<${DomainObject}> found = ${service}.findAll(getServiceContext());
assertEquals(1, found.size());
}

@${testType:newType(org.junit.Test)}
public void testSave() throws Exception {
int countBefore = countRowsInTable(${DomainObject}.class);
${DomainObject} obj = new ${DomainObject}();
// TODO complete...
// obj.set${cursor}
${service}.save(getServiceContext(), obj);
assertEquals(countBefore + 1, countRowsInTable(${DomainObject}.class));
}

@${testType:newType(org.junit.Test)}
public void testDelete() throws Exception {
int countBefore = countRowsInTable(${DomainObject}.class);
${DomainObject} obj = ${service}.findById(getServiceContext(), 1L);
${service}.delete(getServiceContext(), obj);
assertEquals(countBefore - 1, countRowsInTable(${DomainObject}.class));
}


Add it in Eclipse > Preferences > Java > Editor > Templates
Name: testScaffold
Context: Java type members
Description: JUnit test methods for Sculptor CRUD operations