EJB3 JPA error when migrating from JBoss version 4 to 5

When I tried migrating my JBoss 4.2 [war] application which uses Spring to manage transactions, to JBoss 5.1, I got the following error message.

The error message

11:18:55,683 ERROR [AbstractKernelController] Error installing to Start: name=persistence.unit:unitName=#demo state=Create
java.lang.RuntimeException: Specification violation [EJB3 JPA 6.2.1.2] - You have not defined a jta-data-source for a JTA enabled persistence context named: demo
	at org.jboss.jpa.deployment.PersistenceUnitInfoImpl.<init>(PersistenceUnitInfoImpl.java:115)
	at org.jboss.jpa.deployment.PersistenceUnitDeployment.start(PersistenceUnitDeployment.java:275)

Here’s the persistence.xml file

<?xml version="1.0" encoding="UTF-8"?>
<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-unit name="demo">
 <provider>org.hibernate.ejb.HibernatePersistence</provider>
 <class>demo.jpa.User</class>
 <class>demo.jpa.Issue</class>
 <class>demo.jpa.UploadedFile</class>
 <properties>
   <property name="hibernate.hbm2ddl.auto" value="create" />
   <property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect" />
   <property name="hibernate.show_sql" value="true" />
   <property name="hibernate.format_sql" value="true" />
   <property name="hibernate.use_sql_comments" value="true" />
 </properties>
 </persistence-unit>
</persistence>

Solution/workaround

JBoss loads file named “persistence.xml” through this file:

jboss-5.1.0.GA/server/default/deployers/ejb3.deployer/META-INF/jpa-deployers-jboss-beans.xml

… via this code snippet (line 21-95)

   <bean name="PersistenceParsingDeployer" class="org.jboss.jpa.deployers.PersistenceParsingDeployer"/>
   <bean name="PersistenceDeployer" class="org.jboss.jpa.deployers.PersistenceDeployer"/>

   <bean name="PersistenceUnitDeployer" class="org.jboss.jpa.deployers.PersistenceUnitDeployer">
    ...
   </bean>

Solution 1:

Comment out the above lines. This solution is a server configuration modification and therefore must be done on every server (dev/qa/production) that you want to run your app on. You may not be able to use this approach if you don’t have control over your [production] server configuration. See Solution 2 for an application oriented solution.

Solution 2:

  1. Rename the persistence.xml file to something else, for example, spring-persistence.xml
  2. Change the config for the spring entityManagerFactory bean to explicitly refer to this new file. See below

Spring configuration – before:

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
 <property name="dataSource" ref="dataSource" />
 <property name="jpaVendorAdapter">
   <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
 </property>
</bean>

Spring configuration – after:

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
 <property name="dataSource" ref="dataSource" />
 <property name="jpaVendorAdapter">
   <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
 </property>
 <!-- ADD THE FOLLOWING PROPERTY -->
 <!-- provide the location of new persistence.xml -->
 <property name="persistenceXmlLocation" value="classpath:META-INF/spring-persistence.xml" />
</bean>

Reference

See more details of the corresponding JIRA issue at jboss.org

<bean name=”PersistenceParsingDeployer” class=”org.jboss.jpa.deployers.PersistenceParsingDeployer”/>

<bean name=”PersistenceDeployer” class=”org.jboss.jpa.deployers.PersistenceDeployer”/>
<bean name=”PersistenceUnitDeployer” class=”org.jboss.jpa.deployers.PersistenceUnitDeployer”>

How to rotate Tomcat catalina.out

If catalina.out becomes 2GB in size, tomcat crashes and fails to start without any error message. To avoid this scenario you should rotate catalina.out frequently. This article describes how to setup auto rotation of catalina.out on a linux/unix machine.

How to automatically rotate catalina.out daily or when it becomes bigger than 5M

1. Create this file

/etc/logrotate.d/tomcat

2. Copy the following contents into the above file

/var/log/tomcat/catalina.out {
 copytruncate
 daily
 rotate 7
 compress
 missingok
 size 5M
}

About the above configuration:

  • Make sure that the path /var/log/tomcat/catalina.out above is adjusted to point to your tomcat’s catalina.out
  • daily - rotates the catalina.out daily
  • rotate – keeps at most 7 log files
  • compress – compresses the rotated files
  • size – rotates if the size of catalina.out is bigger than 5M
  • copytruncate – truncates the original log file in place after creating a copy, instead of moving the old log file and optionally creating a new one, It can be used when some program can not be told to close its logfile and thus might continue writing (appending) to the previous log file forever. Note that there is a very small time slice between copying the file and truncating it, so some logging data might be lost. When this option is used, the create option will have no effect, as the old log file stays in place.

You don’t need to do anything else.

How it works

  1. Every night the cron daemon runs jobs listed in the /etc/cron.daily/ directory
  2. This triggers the /etc/cron.daily/logrotate file which is generally shipped with linux installations. It runs the command “/usr/sbin/logrotate /etc/logrotate.conf
  3. The /etc/logrotate.conf includes all scripts in the /etc/logrotate.d/ directory.
  4. This triggers the /etc/logrotate.d/tomcat file that you wrote in the previous step.

Run logrotate manually

Run the following command to run the cron job manually

/usr/sbin/logrotate /etc/logrotate.conf

Is it completely safe?

See the description of copytruncate method above. There is a slight chance of a small amount of logging data loss between copy and truncate steps, usually it is acceptable but sometimes its not.

More logrotate options

To see all logrotate options on your system, see the manual:

man logrotate

Cache Java webapps with Squid Reverse Proxy

This article shows you step by step how to cache your entire tomcat web application with Squid reverse Proxy without writing any java code.

What is Squid

Squid is a free proxy server for HTTP, HTTPS and FTP which saves bandwidth and increases response time by caching frequently requested web pages. While squid can be used as a proxy server when users try to download pages from the internet, it can be also used as a reverse-proxy by putting squid between the user and your webapp. All user requests first hit Squid. If the requested page already exists in Squid’s cache it is served directly from the cache without hitting your Webapp. If the page does not exist in Squid’s cache, it is fetched from your web application and stored in the cache for future requests.

Squid reduces hits to your server by caching response pages. You don’t have to worry about building page level caching in every application that your write, Squid takes care of that part.

When should I use Squid

Ideally you should use Squid for pages which have a high ratio of reads to writes. In other words, a page that changes less frequently but is accessed very often. Here are some scenarios:

  • A dynamical web page which displays news and is updated once an hour, and receives hundreds of hits during the hour
  • A static web page accessed freqently. Squid can give performance boost by caching frequently accessed static web pages in memory

When should I not use Squid

In most cases, if the request URL is the only factor which determines the response then you can safely use Squid. See more specific examples below:

  • If the entire apps is very dynamic in nature, and the validity of pages changes immediately.
  • Squid is not suitable for apps which require login. This unfortunately is a large number of applications. Such applications need to resort to back end caching, for example use other caching frameworks like Ehcache to cache re-usable page fragments and/or cache database queries and/or other performance bottlenecks.
  • Apps which heavily use browser cookies. Squid relies on URLs to cache pages. If the page served is computed from URLs + cookies, then you should not cache those pages in Squid.

How does the overall setup work

Apache Squid Tomcat architecture

Apache Squid Tomcat architecture


Apache receives requests on port 80. Apache calls Squid with the request. Squid checks its cache to see if it has the response cached from before. If yes and if the response is not expired, it returns the cached response.In this case:

Squid will write the following header to the response:

X-Cache: HIT from www.vineetmanohar.com

If the response is not found in Squid’s cache, squid will make a call to Tomcat on port 8082. Tomcat’s proxy connector is listening on this port. It processes the request and sends the response back to Squid. Squid saves the response in its cache, unless caching is disabled for that URL. Squid returns the final response to Apache which sends the response back to the user.

What if I don’t want to use Apache

Using Apache is not required to use Squid. You can run Squid on port 80, and point your users directly to Squid. If that is the case, skip section one and directly jump to section 2 below.

Step 1/3: Apache Httpd Config

If you are using Apache as a front end, you need to instruct Apache to forward requests to Squid at port 3128. See the following code snippet. Change the server name and paths to reflect your real values.

Apache config file:

/etc/httpd/conf/httpd.conf
<VirtualHost x.x.x.x>
ServerName www.vineetmanohar.com
DocumentRoot /home/webadmin/www.vineetmanohar.com/html
# forward requests to squid running on port 3128
ProxyPass / http://localhost:3128/
ProxyPassReverse / http://localhost:3128/
</VirtualHost>

In addition to the above, you also need mod_proxy installed. If you see the following in your httpd.conf, you probably already have mod_proxy installed. If you first need to install mod_proxy.

LoadModule  proxy_module         modules/mod_proxy.so
LoadModule  proxy_http_module    modules/mod_proxy_http.so

Step 2/3: Squid Config

First make sure that Squid is installed on your server. You can download Squid from here.

The squid config file on Linux/Unix is located at this location.

/etc/squid/squid.conf

The config file is pretty long. Follow these instructions and set the values appropriately.

# leave the port to 3128
http_port 3128

# how much memory cache do you want? depends on how much memory you have on the machine
cache_mem 200 MB

# what's the biggest page that you want stored in memory. If you home page is 100 KB and
# you want it stored in memory, you may set it to a number bigger than that.
maximum_object_size_in_memory 100 KB

# how much disk cache do you want. It is 6400 MB in the following example, change it as per
# your needs. Make sure you have that much disk space free.
cache_dir ufs /var/spool/squid 6400 16 256

# this is probably the most important config section. Here you can configure the cache life for
# each URL pattern. 

# Time is in minutes
# 1 day = 1440, 2 days = 2880, 7 days = 10080, 28 days = 40320

# do not cache url1
refresh_pattern ^http://127.0.0.1:8082/url1/           0     20%    0

# cache url2 for 1 day
refresh_pattern ^http://127.0.0.1:8082/url2/        1440     20%    1440 override-expire override-lastmod reload-into-ims ignore-reload

# cache css for 7 days
refresh_pattern ^http://127.0.0.1:8082/css         10080     20%   10080  override-expire override-lastmod reload-into-ims ignore-reload

# by default cache the whole website for 1 minute
refresh_pattern ^http://127.0.0.1:8082/                0     20%       0 override-expire override-lastmod reload-into-ims ignore-reload

# how long should the errors should be cached for. For example 404s, HTTP 500 errors
negative_ttl 0 seconds

# On which host does tomcat run. Set 127.0.0.1 for localhost
httpd_accel_host 127.0.0.1

# this is the proxy port as defined in Tomcat server.xml. By default it is "8082"
httpd_accel_port 8082

# set this to "on". Read more documentation if you want to change this.
httpd_accel_single_host on

# To access Squid stats via the manager interface, you need to enter a password here
cachemgr_passwd your_clear_text_password all

# Say "off" if you want the query string to appear in the squid logs.
strip_query_terms off

Step 3/3: Tomcat Config

Make sure that the HTTP Proxy Connector is defined in TOMCAT_HOME/conf/server.xml.

<Service name="Catalina">
<Connector port="8082"
 maxThreads="50" minSpareThreads="5" maxSpareThreads="10"
 enableLookups="false" acceptCount="100" connectionTimeout="20000"
 proxyName="www.vineetmanohar.com"
 compressableMimeType="text/html,text/xml,text/css,text/javascript,text/plain" compression="on"
 proxyPort="80" disableUploadTimeout="true" />

If needed, see additional documentation on Tomcat proxy connector.

Squid Manager Interface

You can access the Squid config and stats via the Squid Manger HTTP interface. Make sure that the “cachemgr.cgi” file which ships with squid installation is in your cgi-bin directory. More documentation on setting that up here.

Once you’ve set it up, you can access the cache manager via this URL:

http://<hostname>/cgi-bin/cachemgr.cgi

To continue enter the following values:

Cache host: localhost
Cache port: 3128
Manager name: manager
Password: <the value you entered for "cachemgr_passwd" in squid.conf>
  • Store Directory Stats shows you how much disk space is used by the disk cache.
  • Cache Client List show you the cache HIT/MISS ratio as %. You should monitor this frequently and tune your cache to get a higher hit %.

Reload Squid Config without restarting

Edit the squid config using “vi” or your favorite editor.

vi /etc/squid/squid.conf

Once you are done editing, reload the new config without restarting Squid.

/usr/sbin/squid -k reconfigure

Clearing Squid Cache

To clear Squid cache:

1) Set the memory cache to 4 MB (or a lower number)

cache_mem 8 MB

2) Set the disk cache to 8 MB (or a lower number). The disk cache must be higher that the memory cache.

cache_dir ufs /var/spool/squid 20 16 256

3) Reload squid config without restart as described in the previous section

4) You may need to wait a few hours for the cache to get cleared. Once the cache is clear, you may restore the previous cache sizes and reload the new config again. You can monitor the cache size through the Squid Manager HTTP interface.

Bypassing Squid

If for some reason you need to bypass Squid, reconfigure Apache to directly send requests to Tomcat. Edit the Apache config file /etc/httpd/conf/httpd.conf

# forward requests directly to Tomcat's proxy connector running on port 8082
ProxyPass        / http://localhost:8082/
ProxyPassReverse / http://localhost:8082/

You will need to restart Apache after making this change.

/etc/init.d/httpd restart

Conclusion

Squid is a very powerful tool for caching. It is not for all applications. Please examine the need of your application and use squid appropriately. I’ve used squid for several years for caching the output from a Java data mashup application and am very satisfied with the ease of use and benefits. Hope you found this tutorial useful. Feel free to post a comment or share your experience with squid.

References

Squid official website

Maven Docbook for beginners

Docbook is an XML format generally used for writing technical documentation. Many technical projects have documentation written in Docbook XML and checked in the source control system along with the source code. This makes it easy to ship documentation with the source and lets you keep versions of documentation in sync with the product version. This tutorial shows you how to write your first docbook documentation in a Maven project.

Write a simple docbook file

Create the following file:

src/docbkx/test.xml

A minimal docbook file

<?xml version="1.0" encoding="utf-8"?>
 <article xmlns="http://docbook.org/ns/docbook" version="5.0" xml:lang="en">
  <title>Hello, World</title>
  <para>My first documentation with Docbook</para>
 </article>

Generate html documentation

Configure pom.xml

The maven docbook plugin converts your docbook xml file to user friendly documentation in HTML. Add the following plugin declaration to your pom.xml

<build>
<plugins>
<plugin>
 <groupId>com.agilejava.docbkx</groupId>
 <artifactId>docbkx-maven-plugin</artifactId>
 <dependencies>
  <dependency>
   <groupId>org.docbook</groupId>
   <artifactId>docbook-xml</artifactId>
   <version>4.4</version>
   <scope>runtime</scope>
  </dependency>
 </dependencies>

 <executions>
  <execution>
   <phase>pre-site</phase>
   <goals>
    <goal>generate-html</goal>
   </goals>
  </execution>
 </executions>
</plugin>

Run the plugin

The above config runs the plugin in pre-site phase, and will automatically be called when you run mvn site. You can use the following command to manually run the plugin for purpose of testing:

mvn pre-site

This simple config scans the src/docbkx directory and produces the html documentation in target/docbkx/html directory. You should see the following output file:

target/docbkx/html/test.html

First docbook generated HTML

More plugin options

The plugin goal used above generate-html converts the docbook xml to html. There are advanced options to configure the CSS/XSLT used. Also, there are other goals available to generate documentation in more formats including pdf. Here’s the reference page for plugin documentation.

Learning Docbook format

Now that you are able to create a sample docbook and publish it, you might want to learn the Docbook format itself. Here are some links that should help you get started:

FAQ

  1. Are there other docbook plugins for Maven? Yes, there are a few other plugins. However, this one seems to be the easiest to use. See more info here.

References

http://opensource.bureau-cornavin.com/crash-course/en/index.htmlThis

What is Google Buzz?

Google Buzz is yet another way to share photos, status updates, videos, news and more with friends and family.

Buzz is part of Gmail, so unlike other social networking sites where you have to build your community from scratch, Buzz lets you start from your existing Gmail contacts. If you’re not already on Gmail then it makes it less attractive to try it, in my opinion.

Buzz also shows you activities from Picasa, Google Reader, Flickr and Twitter so you can see all of that in one place.

There is no need to register, download or setup anything. Buzz is automatically available from your Gmail. Just go to your Gmail and you should see a new ‘Buzz’ link under your ‘Inbox’ in the left hand pane. Buzz is being rolled out so if you don’t see the ‘Buzz’ link, you don’t have it yet.

The buzz official website is: http://buzz.google.com. Here’s the official intro video from Google.

3 ways to serialize Java Enums

This article shows you best practice for serializing Java enums to database (via Hibernate, JPA) or file. It discusses three ways to serialize enums with code examples, the pros and cons of each way and also recommends the best way. You should know this if you are serializing an Object with an enum field to a file or mapping a POJO to a database table using technologies like Hibernate or JPA.

What exactly is a Java enum constant? A Java enum is a sub-class of java.lang.Enum. An enum constant is simply an object instance of the enum class. The enum constructor must be private. Enum constants are created by the JVM via an invocation of the private constructor. Customizing the constructor signature is the most common way of adding more data to the enum class. You can add methods to the enum class just like any other class.

What does serialization and deserialization of enum mean? Serialization involves converting the enum to a value (usually primitive or a String) which can be easily stored on the disk or a database. Deserialization involves reading a stored value and converting it back to an enum. It is important to understand the different ways in which enum serialization and deserialization works. Sometimes ORM implementations (like Hibernate) may automatically do the enum serialization for you, however there are drawbacks to some of these approaches that you should know.

Let’s say we want to serialize the following enum

public enum Color {
 RED, GREEN, BLUE;
}

Following are 3 different approaches. The last approach is the most reliable way of serializing an enum class, however you should know approaches 1 and 2 so you can understand their drawbacks.

Approach 1: using the ordinal() value

Approach 2: using the name() value

Approach 3: Using a user defined business valueBest practice!

Approach 1: using the ordinal() value

Ordinal of an enum constant is the value is its position in its enum declaration. This is true for all enums. In the above example:

RED.ordinal()   == 0
GREEN.ordinal() == 1
BLUE.ordinal()  == 2

You can serialize the enum by converting the enum to its ordinal() value.

Color color = Color.GREEN;
int ordinal = color.ordinal(); // ordinal == 1
// save ordinal

At a later point, you can deserialize the saved int using the values() method on the enum which returns all the enum constants in the order in this they were declared.

// retrieve from saved value
Color savedColor = Color.values()[savedOrdinal];

This approach is simple and works. Some ORM implementations may automatically use this approach if you map your enum to and Integer column. However, the biggest drawback of this approach is that if new constants are introduced out of order then the serialized values will not be properly reconstructed.

Here’s the error scenario:

  1. Serialize an enum value Color.GREEN. Saved value gets stored as 1
  2. Developer adds a new color ORANGE between RED and GREEN
  3. The previously serialized value of 1 is now mapped to ORANGE.

Approach 2: using the name() value

The name() of any enum is the literal that is used to represent the enum constant in the Java program.

RED.name().equals("RED")
GREEN.name().equals("GREEN")
BLUE.name().equals("BLUE")

Serialize as follows:

Color color = Color.GREEN;
String savedValue = color.name();
// save value

Deserialize as follows:

Color savedColor = Color.valueOf(savedValue);

valueOf() is a built-in method which returns the enum constant with the specified specified name

This method works as well. Some ORM implementations may automatically use this approach if you map your enum to and String (char, varchar) column.The serialized form is String (as opposed to int in the previous example). The main drawback of this approach is that the serialized value, which can then be stored on disk or in database and can be persisted for a long term, is now dependent on a Java constant name. A developer may accidentally rename the constant name without realizing that it will make the previously serialized values unreadable.

Here’s the error scenario:

  1. Serialize an enum value Color.GREEN. Saved value gets stored as “GREEN”
  2. Developer renamed enum constant from Color.GREEN to Color.Green.
  3. The previously serialized value of “GREEN” can no longer be mapped to an existing color.

Approach 3: Using a user defined business value – Recommended approach!

This approach involves assigning a an explicit user defined value to each enum constant and defining a toValue() and fromValue() methods on the enum to do the serialization and deserialization.

public enum Color {
 RED("RED"), GREEN("GREEN"), BLUE("BLUE"), UNKNOWN("UNKNOWN");

 private final String value;

 Color(String value) {
   this.value = value;
 }

 public static Color fromValue(String value) {
   if (value != null) {
     for (Color color : values()) {
       if (color.value.equals(value)) {
         return color;
       }
     }
   }

   // you may return a default value
   return getDefault();
   // or throw an exception
   // throw new IllegalArgumentException("Invalid color: " + value);
 }

 public String toValue() {
   return value;
 }

 public static Color getDefault() {
   return UNKNOWN;
 }
}

This approach is better than approach 1 and approach 2 above. It neither depends on the order in which the enum constants are declared nor on the constant names.

To serialize:

Color color = Color.GREEN;
String savedValue = color.toValue();
// save value

To deserialize:

Color savedColor = Color.fromValue(savedValue);

Note: You can choose an Integer instead of String as a value, but remember this value must not change or you will be unable to retrieve you persisted values.

Mapping enum to database column using JPA/Hibernate

You can use any of the 3 approaches discussed above.

  1. Map the enum to an integer column. The persistence implementation should automatically convert enum to ordinal() and back for you.
  2. Map the enum to a String column. The persistence implementation should automatically convert the enum value to String value via the name() function.
  3. Map the enum using a business value. You should mark the enum field as @Transient, and create another String field which you can map to a String column in your database table. Here’s an example code snippet.
@Entity
public class Product {
 @Column
 private String colorValue;

 @Transient
 public Color getColor() {
  return Color.fromValue(colorValue);
 }

 public void setColor(Color color) {
  this.colorValue = color.toValue();
 }
}

Conclusion

We saw 3 different ways to serialized enums in this article. Approach 1 and 2 above use ordinal() and name() respectively, and require no additional work, but are inherently unsafe to use. The safest way is approach 3 which uses a custom user defined value as shown in the example above. When persisting enums with Hibernate/JPA first convert them to a user defined value.

Code Generation for Web Applications with Clickframes

What is Clickframes?

Clickframes is a Code Generation framework written in Java designed specifically to generate (Java) web applications.

Philosophy behind Clickframes

There are 2 aspects to a web application:

  1. What the application does.
  2. How it does it.

The key idea behind Clickframes is separation of these two concerns.

What the application can be defined by focusing on end user experience – what the end user sees, what the user clicks and so on. When users open a webapp in a browser they see a page, links, forms, inputs, content. They don’t see how the page was produced, which technology, framework or database was used on the back end. Defining what an application does boils does to defining a web page, after all a web application is most part is a collection of web pages linked to each other via links and form actions.

On the other hand, how an application is implemented consists of every little detail that happens “behind the scenes”. Which technology, platform and database is used, all the choices which result in a working application – but are never directly seen by the end user directly.

Clickframes separates these two aspects of the application by defining an application model called Appspec. Appspec is a rich data structure which represents the application behavior. The business analyst defines the application behavior using the Appspec model. The developer writes code generators to implement a generic Appspec and then runs them for the specific Appspec written by the business analyst. Appspec becomes a contract and a way of communication between the analyst and the developer. In the meantime QA takes the Appspec and writes tests against it. Appspec becomes a way of communication and the single source of truth for the various members of the team.

To give you a concrete sense of what I am talking about, let’s say that the Appspec has a page called “home”. The developer may choose to implement this using a simple jsp file “home.jsp”. The developer then generalizes this implementation and creates a code generator to produce a file called [page id].jsp for every page in the Appspec. Again, the philosophy being “if I can figure out how to implement one page, I can apply the same approach for all pages”. This approach implemented via a set of code generators applied against the application definition (or Appspec) is the key idea of the Clickframes approach. The result is an automatically generated application for a given target platform/technology (e.g. “jsp” in the previous example) which produces consistent code for the entire application. This code is produced using code generators at minute zero of your project, i.e. even before you start working on your project. You can then take the generated code and start customizing it. This is a great productivity boost as you can use the same code generators from one project to another as they are not specific to any particular application, but are written for the generic Appspec model for the given target technology/platform. Such code generators usually exists are code generation templates and are referred to as Clickframes Plugin.

Terminology

To recap the terminology:

Appspec (Application Specification) – Appspec is what the web application does, from an end user’s perspective. It essentially captures the behavior of the application. How many pages does the application have, how many forms does each page have. How many input fields on each page. What type of input fields (e.g. text, textarea, radio, dropdown). Are there any validation rules on the input fields (e.g. must be 8-12 characters, or must be a zipcode, must be a valid email format). What is the next page when the user submits a form on a page. How many links on the page, do the links point to another page in the application or an external link. The list goes on, but you get the idea.

Clickframes Plugin – Clickframes Plugin is a code generator, usually implemented by creating a set of templates, which inputs an Appspec and generates code. A plugin is usually a zip file consisting of dozens of templates written in plain text or velocity. Plugins can also be written or extended in Java using the Clickframes Plugin API.

Clickframes Plugin Authors – (Usually) Senior or Experienced developers who have a good understanding of the target technology create a plugin to implement the Appspec. Note that this activity needs to be done only once per technology. For example, once I have created a Seam2 plugin, you can generate any number of applications by simply writing an Appspec for your application and generate Seam code by using the plugin.

Target language/platform – Clickframes is a Code Generation framework that you use before you even start your project. It generates code that you then compile and run. Target platform refers to the platform on which the generate code runs. Example target platforms are Java/Tomcat, Java/Seam/JBoss, JSF/Tomcat, PHP. If you are willing to write your own code generation templates, you can generate code for any language/target platform.

Why Clickframes?

One advantage of Clickframes is that it acts as a medium of communication between the various members of the team.

However, the most powerful feature of Clickframes is the Clickframes Code Generation Plugins. Once you write a plugin for a technology or platform, you can instantly generate a full working application by simply writing the Appspec for that application and running the Clickframes Plugin on this Appspec . Writing an Appspec should be much easier than implementing the application itself.

Hello, World example

Let say an application has one page which has the text “Hello, World”. You can create the Appspec by either using the Java API or XML format.

Creating appspec via XML

<appspec>
  <pages>
    <page id="home">
     <contents>
      <content id="message1">Hello, world</content>
     </contents>
    </page>
  </pages>
</appspec>

Creating appspec via Java

Appspec appspec = new Appspec();
Page home = new Page();
Content message1 = new Content();
message1.setId("message1");
message1.setText("Hello, World");
home.getContents().add(message1);
appspec.getPages().addPage(home);

Clickframes sample JSP Plugin

Now lets build a simple JSP code generator. This code generator is just for the purpose of illustration and is not intended to be a real production quality plugin.

Create a file called ${page.id}.jsp. Since the file name consists of the variable ${page} this file will automatically be applied to all pages in the application.

Contents of ${page.id}.jsp below. All templates are written in Apache Velocity.

The ${page} variable passed to the template represents the Java object defined above.

<html>
 <body>
#foreach ($content in $page.contents)
  <div id="${content.id}">${content.text}</div>
#end
 </body>
</html>

Running this plugin against the above model will produce one file called “home.jsp” with the following content.

<html>
 <body>
  <div id="message1">Hello, World</div>
 </body>
</html>

You can now add a dozen pages to your application and reuse the same code generation template.

A more comprehensive demo

The above example is good to give you a quick sense of how the code generation works. However, real applications contains forms, links, inputs, actions, entities, databases and so on. The following example uses a JSF Seam2 plugin which is used to generate a simple Issue Tracker Application.

The best way to jump in and get your feet wet is by seeing and running the code. I have created a JSF Seam2 plugin which generates JSF2 and Seam based web applications.

Here’s the Appspec for the application and you can browse the generated code here. There is a hosted version of running demo at http://demo.clickframes.org/tracker/

1. Checkout the project code:

svn checkout http://clickframes-seam-issuetracker-demo.googlecode.com/svn/trunk/ clickframes-seam-issuetracker-demo

2. Run it:

cd clickframes-seam-issuetracker-demo
mvn glassfish:run

See the application run at:
http://localhost:8080/issuetracker/
You can type any login/password to login. The login module implemented by default does passes any input. In the future I plan modify the plugin to properly implement login.

Key demo features:

  • Security: pages with login-required=”true” will automatically prompt you for login.
  • AJAX input validation: inputs with validation will prompt you with an error as you type if the validation fails
  • Built-in CRUD implementation using in-memory database: actions marked with “update” or “create” will actually create an entity and store it in an in memory database

Note that this application is 100% generated directly from the Appspec. What is means is that you can modify the application behavior by modifying the Appspec and regenerate the application.

Regenerate:

mvn clickframes:generate

Can you really model every single thing about a web application?

No. Clickframes focuses on things which can be easily modeled. Even if you are able to capture 50% of the application features in the Appspec, you can generate a working application which implements 50% of requirement without writing a single line of code. That’s quite a jump in productivity. You can then hand code the remaining application the usual way.

Case for Clickframes

Clickframes is not for all web applications. If the Clickframes model fits your application model then I urge you to give Clickframes a try. With Clickframes you can produce consistent code for your entire application. You can bake the best practices right into the code generation templates. Moreover, you can use these templates from one project to another.

References and Links

Publishing to Maven Central Repo in 5 steps

Maven Central Repo is the official Maven repository where all “official” jars are published. It is also known as the “central” repo and is part of the super pom.xml which is implicitly included by every Maven project. The URL of the Maven Central Repo is http://repo1.maven.org/maven2/.

If you need to share your Maven artifacts with the world, you too can publish it on the official Maven repo! Let others discover your artifacts without any repository configuration. This article is intended to be a practical, step by step, easy to follow tutorial to publish your artifacts to the central repo.

Step 1: pom.xml configuration

  • Required elements: These elements must be present in your pom.xml: modelVersion, groupId, artifactId, packaging, name, version, description, url, licenses, scm url, dependencies
  • No <repositories> or <pluginRepositories> tag allowed. All you dependencies must be present in the central repo.
  • Choose a groupId that you own. Most common way to do this is to have control over the domain name corresponding to your groupId. For example, if your groupId is com.vineetmanohar then your must own or have control over the domain name vineetmanohar.com. This is required as maven will only download artifacts for a groupId from the corresponding domain.
  • You can only publish releases, not snapshots.

Step 2: Create your domain repo

This assumes that you have a hosted server somewhere which runs apache (or similar web server to host static files), and describes how to create a repo using by defining an path in a apache virtual server. If you have root access to the machine, Login as root and create a new user called ‘repo’

 # adduser repo
 # su - repo

As the repo user and create the repo directories.

# su - repo
$ cd /home/repo
$ chmod 755 .
$ mkdir -p html/releases html/snapshots

Now map this directory to apache

Map /home/repo/html/ to http://repo.<your domain>.com

Edit the /etc/httpd/conf/httpd.conf file and add the following mapping. Change IP address and server name as applicable. Remember that server name must match or should be a sub-domain of your groupId.

 <VirtualHost 215.12.34.111:80>
  <Directory /home/repo/html>
   Options +Indexes
   AllowOverride Limit
  </Directory>

  ServerName repo.vineetmanohar.com
  DocumentRoot /home/repo/html
  CustomLog "/home/repo/access_log" "combined"
  ErrorLog "/home/repo/error_log"
  SuexecUserGroup repo repo
 </VirtualHost>

Restart apache

/etc/init.d/httpd restart

Step 3: Publish artifacts to your repo

Add a <distributionManagement> section to your pom.xml. Here’s an example, change it to reflect your server names and paths.

<distributionManagement>
 <repository>
   <id>vineetmanohar-release-repo</id>
   <name>vineetmanohar.com Release Repo</name>
   <url>scp://repo.vineetmanohar.com/home/repo/html/releases/</url>
 </repository>

 <snapshotRepository>
   <id>vineetmanohar-snapshot-repo</id>
   <name>vineetmanohar.com Snapshot Repo</name>
   <url>scp://repo.vineetmanohar.com/home/repo/html/snapshots/</url>
 </snapshotRepository>
</distributionManagement>

Once you are ready to release, change your pom.xml version to a non-SNAPSHOT version, e.g. 0.0.1. Remember that if your version is a non-SNAPSHOT version, you cannot have any SNAPSHOT dependencies either, that’s just a universal maven rule.

Now deploy your version to your release repo.

mvn deploy

If you use scp to deploy (as in the example above) you will be asked to enter your password. Alternatively you can configure to SSH without password.

PS: Alternatively you can automatically increment version and deploy automatically by using the Maven Release plugin.

Step 4: Give permission to Maven to access your repo

The simplest way is to authorize Maven by adding its private key to your repo’s authorized ssh keys. Make sure that the permissions are set as described below.

# su - repo
$ mkdir -p .ssh
$ chmod 700 .ssh
$ cd .ssh
$ vi authorized_keys
<paste maven's public key in file authorized keys>
$ chmod 400 authorized_keys

Copy the contents of Maven’s public key and paste it in /home/repo/.ssh/authorized_keys

Step 5: Submit a request to the Maven folks

You have your artifacts published in a public repo and Maven has the permission to rsync your repo over SSH. All you need to do now is to submit a request to Maven to add your server to the list of servers they sync with.

Open an account at http://jira.codehaus.org, if you don’t have one already. Once you have created an account, submit your request here.

Here is an example request that I submitted. It took them 7 days to close the ticket, so be patient. After the ticket has been closed, it might take half a day for the servers to gets sync’d, after which I could see my artifacts appear here.

Reference

Linux command line puzzler

The file “hello.txt” shows up in directory listing via the “ls” command. The puzzler is about trying to display the contents on the file via the “cat” command.

Following is a real transcript demonstrating the puzzler.

$ whoami
vineet
$ ls -al
total 12
drwxr-xr-x  2 vineet vineet 4096 Nov 15 11:15 .
drwx------ 15 vineet vineet 4096 Nov 15 11:14 ..
-rw-r--r--  1 vineet vineet   42 Nov 15 11:14 hello.txt
$ cat hello.txt
cat: hello.txt: No such file or directory

Puzzler: Why can’t we display the contents of the file “hello.txt”?

Know the answer? Post your response below.

Tweet your builds with Maven Twitter Plugin

Introduction

Maven Twitter Plugin lets you send Twitter status updates from Maven, without writing any Java code. It increases communication between Project owners and Project users by automatically tweeting build and release status via Twitter.

Configuration

1. Add Plugin repository to your <build> <plugins> section in pom.xml

You need to add this to your list of existing plugin repositories.

<pluginRepository>
 <id>vineetmanohar-release-repo</id>
 <name>Vineet Manohar Release Repo</name>
 <url>http://repo.vineetmanohar.com/releases</url>
</pluginRepository>

2. Add your twitter username, password to your ~/.m2/settings.xml file

For security reasons, it is recommended that you put your twitter username and password in your local settings file.

<settings>
 <profiles>
  <profile>
   <id>default</id>
   <activation>
    <activeByDefault>true</activeByDefault>
   </activation>
   <properties>
    <twitterUsername>your twitter username</twitterUsername>
    <twitterPassword>your twitter password</twitterPassword>
   </properties>
  </profile>
 </profiles>
</settings>

Usage

Add the Twitter plugin to your <build> <plugins> section in pom.xml

Define the plugin as shown in example below.

<build>
 ...
 <plugins>
  <plugin>
   <groupId>com.vineetmanohar</groupId>
   <artifactId>maven-twitter-plugin</artifactId>
   <version>0.1</version>
   ...
  </plugin>
</plugins>

Now add one <execution> block to the above, for every Tweet you want to send per build. The <twitterStatus> config element defines your Twitter message and will be executed in the phase specified by the <phase> subelement.

<execution>
 <phase>...</phase>
 <configuration>
   <twitterStatus>...</twitterStatus>
 </configuration>
</execution>

You can define as many blocks as you want.

Example

This example send 2 tweets: one in the “test” phase and the other in the “deploy” phase.

<plugin>
 <groupId>com.vineetmanohar</groupId>
  <artifactId>maven-twitter-plugin</artifactId>
  <version>0.1</version>
  <executions>
   <!-- phase: test -->
   <execution>
    <id>test-passed</id>
    <configuration>
     <!-- anything you want, upto 140 chars -->
     <twitterStatus>My first tweet from using #maven twitter plugin</twitterStatus>
    </configuration>
    <phase>test</phase>
    <goals>
     <goal>tweet</goal>
    </goals>
   </execution>

   <!-- phase: deploy -->
   <execution>
    <configuration>
     <!-- Tell your users that the project is deployed -->
     <twitterStatus>Version ${project.versionId} of XYZ deployed</twitterStatus>
    </configuration>
    <id>deploy</id>
    <phase>deploy</phase>
    <goals>
     <goal>tweet</goal>
    </goals>
   </execution>
  </executions>
</plugin>

FAQ

What can I put under the <twitterStatus> element

  • static text
  • You can be creative and put variables related to your project. ${project} maps to the Maven Project Model. Examples are ${project.groupId}, ${project.artifactId}, etc
  • You can put hash tags by simply putting # before a word
  • You can put @usernames directing the message to a specific twitter account
  • You resolved twitter message, after resolving any ${vars}, should be maximum 140 chars

What happens if I send multiple message with the same text

  • Twitter seems to ignore status updates if there is not status change from your.

What happens if my <twitterStatus> is more than 140 characters

The current version does not check for length and will send your message to Twitter. Twitter will respond with an error.

Does this plugin support URL shortening?

Version 0.1 does not support URL shortening.

Does maven execution stop if the Twitter Plugin fails

No. All errors are logged, but no Exception is thrown.

Is there a limit to how many messages I can send?

Yes. Twitter has a rate limit of 150 message per hour. See details.

What are all the different Maven phases

Here’s Maven’s documentation on Phases

Reference

Get Adobe Flash playerPlugin by wpburn.com wordpress themes