Monday, October 20, 2008

Google App Engine will support Java ? Cool !

Well, I don't believe yet, but it seems to be that Java will be supported on GAP !

At the recently Google Developers Day in Bangalore, Keynote speaker Prasad Ram said that Google App Engine will now support Java.

Source here and here

Thursday, October 09, 2008

JBoss EJB3 Integration testing with Maven2 and Cargo

One of the most boring things in EJB development is that we need container. Compile-Build-Deploy-Run_some_testing_code - this is to long cycle to repeat it frequently without some kind of automation. I'll show you one of the possible ways to simplify this stuff. There are others, but I didn't tried them (I mean jboss microcontainer here). It's not complex, but it works and probably could be portable solution for not only my case.

So, my working environment is the following : Maven 2, JBoss 4.2.2 GA, jUnit 3.8.1 and of course EJB3. Build lifecycle with Maven 2 consists of some phases, like "...compile,test,package,integration-test...". Ok, with package and compile phases all is clear. Test... we need jboss to be up and running before we can test anything. How to start and stop jboss automatically during build ? The answer is Cargo with Maven2 plugin.

Cargo is a thin wrapper around existing containers (e.g. J2EE containers). It provides different APIs to easily manipulate containers.

Now we can assign "start container" and "stop container" goals to some Maven 2 build phase. First of all, we are interested in integration-test. Also we need to skip junit tests before integration test. To achieve this I'm using this config for cargo plugin :

<plugin>
<groupId>org.codehaus.cargo</groupId>
<artifactId>cargo-maven2-plugin</artifactId>
<version>0.3-SNAPSHOT</version>
<configuration>
<container>
<containerId>jboss4x</containerId>
<home>${jboss.home}</home>
<append>false</append>
</container>
<configuration>
<type>existing</type>
<home>${jboss.home}/server/default</home>
<properties>
<cargo.jboss.configuration>default</cargo.jboss.configuration>
<cargo.rmi.port>1099</cargo.rmi.port>
<cargo.logging>high</cargo.logging>
</properties>
</configuration>
<wait>false</wait>
</configuration>
<executions>
<execution>
<id>start-container</id>
<phase>pre-integration-test</phase>
<goals>
<goal>start</goal>
</goals>
</execution>
<execution>
<id>stop-container</id>
<phase>post-integration-test</phase>
<goals>
<goal>stop</goal>
</goals>
</execution>
</executions>
</plugin>

And this for surefire - to be able to run junit tests on integration-test phase, after container started at pre-integration-test phase :

<plugin>                                      
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
<executions>
<execution>
<id>surefire-it</id>
<phase>integration-test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<skip>false</skip>
</configuration>
</execution>
</executions>
</plugin>
I haven't any luck with "standalone" type configuration. I should say that when"existing" jboss installation is used here, overall process is quite fast:

[INFO] -------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] -------------------------------------------
[INFO] Total time: 42 seconds
[INFO] Finished at: Thu Oct 09 15:15:39 EEST 2008
[INFO] Final Memory: 9M/19M
[INFO] -------------------------------------------
42 seconds to compile code, package jar, copy jar to deploy dir, start jboss, run junit test, stop jboss and all this by doing just "mvn install" !

Complete source code available via svn here.

PS.
Time can be very different. My hardware is HP 6820s laptop. BTW, executing "mvn -o install" takes 23 sec :)

Friday, October 03, 2008

Build EJB3 with Maven 2 example with source code

My posts (the first and the second) about how to build EJB3 using Maven 2 was very popular. This post is some kind of update, but now, with complete source code. BTW, I'm going to publish some of sources I mentioned at my blog posts, since readers are asking for them. I mean source code from this post at minimum.


So, here it is !
In my further posts I'm going to highlight some of pitfalls one can face with.

Wednesday, August 27, 2008

Yet another Java Puzzle

No words here, just the code :)

class String
{
public static void main(String args[])
{
String String = new String();
}
}

Friday, July 25, 2008

Wow ! DZone.com using Acegi Security !

I've seen a very interesting alert box with exception message at dzone.com when tried to vote up for the post. It was something like "org.acegisecurity....". Hey, wait a minute, it is Acegi ! Really, login form looks as so

<form method="post" action="/links/j_acegi_security_check" 
class="loginform" id="addlinkform">
<div>
<label>Username:</label>
<input type="text" class="txt" name="j_username" size="20"/>
</div>
<div>
<label>Password:</label>
<input type="password" class="txt" name="j_password" size="20"/>
<label/>
<a href="http://zones.dzone.com/user/password"
class="forgotpass">
Forgot password?</a>
</div>
<div>
<label class="cbx">
<input type="checkbox" name="_acegi_security_remember_me"
checked=""/>
remember me
</label>
</div>
<div class="submit">
<input type="submit"
onsubmit="lightbox.prototype.deactivate();" value="Login"/>
<a rel="deactivate" class="lbAction" href="#">
<input type="button" value="Cancel"/></a>
</div>
</form>

j_acegi_security_check, j_username, j_password, _acegi_security_remember_me - it seems to be really Acegi !

Tuesday, July 22, 2008

Struts 2 : Deprecate or remove Dojo plugin

Sometimes it is very useful to read struts-dev mailing list. See here. In fact I'm very happy of that, because I was going to use some AJAX with Struts 2 and Dojo plugin. One thing I couldn't figure out is why Dojo ?? Why not Prototype ? Why not jQuery ? Well, OK. If developers using Dojo, I will do the same. Now the situtation is more clear and I'm not going to use Dojo anymore. Maybe Prototype ? :)

Friday, July 18, 2008

A little bit of dependency injection with Struts 2 and Spring 2

I'm using Struts 2 + Hibernate 3 + Spring 2 for my current project. I have to admit that Struts+Spring integration is really easy. The key integration point is Struts 2 Spring plugin. I'll not repeat the docs here. Only one thing I should admit that I prefer to handle spring dependencies by myself because of little bit different version of Spring - 2.0.5 in plugin and 2.0.8 in my project. So, I have this lines in my pom.xml (Maven 2 build file)

<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-spring-plugin</artifactId>
<version>2.0.11.1</version>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</exclusion>
</exclusions>
</dependency>
and
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
etc. I'm injecting Spring powered services into Struts 2 actions, but I had never had a chance to inject some kind of static list. Now I have, so the story about it.

I have a static list of countries. I think it doesn't make sense to store this info in database. The number of countries is not that large. If so, I need to store this data in some data structure and place it in memory. It could be List or Map - it depends on situation. And init this data structure once application starts. In web app when war file being deployed, Spring's WebApplicationContext initialized. So, when we define our list as Spring bean, it will be initialized at the application start and will be ready to other manipulations. I've defined it as so :

<?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:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-2.0.xsd">

<util:list id="countryList" list-class="java.util.LinkedList">
<value>item1</value>
<value>item2</value>
<value>item3</value>
</util:list>

</beans>
Here is the one question on Spring forum and official docs about it. For now we have a LinkedList filled with countries. We are going to inject it into Spring action and then show it at the "view" jsp.

Please note that id of our list is countryList. In fact it is a name of the bean. It's name really important since Struts 2 Spring pluring's default autowiring strategy is by name (I'm using default autowiring type and happy with that). It means that we can use setter injection this way
public class SomeStruts2Action extends ActionSupport
{
public List countryList;

public void setCountryList(List countryList) {
this.countryList = countryList;
}
.......
}
Please note that id and class member name with type List are equal. That is all ! But actually not all :) We have to tell where is our list definition is. In my case it's at one of jars so I have this line in web.xml :

<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext-myCountryList.xml,
/WEB-INF/appContext-web.xml</param-value>
</context-param>

Have fun !

Wednesday, July 02, 2008

Blog stats : London vs California

I see an interesting tendency with blog visitors according to Google Analytics. With visitors by country US at the top, and California hit the score. But if I take criteria "by city", London at the top.

I found it's pretty interesting. I know about Silicon Valley in CA - hudge technological center, but I don't know anything about London. Can we compare London vs. California from technological perspective? Just interesting what do you think, so feel free to comment. Of course my conclusion is based on my-only-stats and it's could be wrong.

Thursday, June 05, 2008

Spring Security 2.0 : Different target urls for different user roles

I'm evaluating Spring Security 2.0. The nice thing - it's really easier to have deal with it, rather than Acegi Security. I had an xml config file with 250+ LOC with Acegi ! Something like Rocket Science... but it is very flexible and expendable, it is very big plus.

After all, it is still not so trivial to implement some things which I found very commonly used. But... Spring rocks ! And Spring community rocks even more. I've posted message to Spring forum here.
Thanks Luke Taylor for pointing me to the right direction.

Lets imagine we have the same login form for common user and admin and we want admin to be redirected to some kind admin control panel and common user to /home /profile or something like that. In my case customized AuthenticationProcessingFilter will do the trick. The code looks like this :

package com.mycoolcompany.App.CustomSecurity;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.springframework.security.Authentication;
import org.springframework.security.AuthenticationException;
import org.springframework.security.GrantedAuthority;
import org.springframework.security.providers.
UsernamePasswordAuthenticationToken;
import org.springframework.security.ui.webapp.
AuthenticationProcessingFilter;

public class CustomAuthenticationProcessingFilter
extends AuthenticationProcessingFilter
{
@Override
public Authentication attemptAuthentication(HttpServletRequest request)
throws AuthenticationException {
String username = obtainUsername(request);
String password = obtainPassword(request);

if (username == null) {
username = "";
}

if (password == null) {
password = "";
}

username = username.trim();

UsernamePasswordAuthenticationToken authRequest =
new UsernamePasswordAuthenticationToken(username, password);

// Place the last username attempted into HttpSession for views
HttpSession session = request.getSession(false);

if (session != null || getAllowSessionCreation()) {
request.getSession()
.setAttribute(SPRING_SECURITY_LAST_USERNAME_KEY,
escapeEntities(username));
}

// Allow subclasses to set the "details" property
setDetails(request, authRequest);

//role&URLs stuff
final Authentication auth =
this
.getAuthenticationManager().authenticate(authRequest);
final GrantedAuthority[] grantedAuthorities = auth.getAuthorities();
boolean isAdmin = false;
for(GrantedAuthority grantedAuthority : grantedAuthorities)
{
if("ROLE_SUPERVISOR".equals(grantedAuthority.toString()))
{
isAdmin = true;
break;
}
}
String outcome = null;
if(isAdmin)
{
outcome = "/adminArea";
}
else
{
outcome = "/someOtherUserArea";
}
//actual change of default url for user
this.setDefaultTargetUrl(outcome);

return auth;
}
public static String escapeEntities(String s) {
StringBuffer sb = new StringBuffer();
for (int i=0; i < s.length(); i++) {
char c = s.charAt(i);

if(c == '<') {
sb.append("&lt;");
} else if (c == '>') {
sb.append("&gt;");
} else if (c == '"') {
sb.append("&#034;");
} else if (c == '\'') {
sb.append("&#039;");
} else {
sb.append(c);
}
}

return sb.toString();
}
}
And XML config :

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

<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-2.0.1.xsd">

<http auto-config="false"
entry-point-ref
="authenticationProcessingFilterEntryPoint">
<intercept-url
pattern
="/secure/extreme/**"
access="ROLE_SUPERVISOR"/>
<intercept-url
pattern
="/someDefaultUrl/**"
access
="ROLE_SUPERVISOR"/>
<intercept-url
pattern="/secure/**"
access
="IS_AUTHENTICATED_REMEMBERED" />
<intercept-url
pattern="/**"
access
="IS_AUTHENTICATED_ANONYMOUSLY" />
<anonymous />
</http>

<!--
Usernames/Passwords are
rod/koala
dianne/emu
scott/wombat
peter/opal
-->
<authentication-provider>
<password-encoder hash="md5"/>
<user-service>
<user name="rod"
password
="a564de63c2d0da68cf47586ee05984d7"
authorities
="ROLE_SUPERVISOR, ROLE_USER, ROLE_TELLER" />
<user name="dianne"
password
="65d15fe9156f9c4bbffd98085992a44e"
authorities
="ROLE_USER,ROLE_TELLER" />
<user name="scott"
password
="2b58af6dddbd072ed27ffc86725d7d3a"
authorities="ROLE_USER" />
<user name="peter"
password
="22b5c9accc6e1ba628cedc63a72d57f8"
authorities
="ROLE_USER" />
</user-service>
</authentication-provider>

<authentication-manager alias='authenticationManagerAlias'/>
<beans:bean id="authenticationProcessingFilterEntryPoint"
class="org.springframework.security.ui.webapp.
AuthenticationProcessingFilterEntryPoint
">
<beans:property
name
="loginFormUrl"
value="/login.jsp"/>
<beans:property
name="forceHttps"
value
="false" />
</beans:bean>
<beans:bean id="myAuthenticationProcessingFilter"
class="com.mycoolcompany.App.CustomSecurity.
CustomAuthenticationProcessingFilter
">
<beans:property
name
="filterProcessesUrl"
value
="/j_spring_security_check" />
<beans:property
name
="defaultTargetUrl"
value="/someDefaultUrl/index.jsp"/>
<beans:property
name="authenticationManager"
ref="authenticationManagerAlias"/>
<custom-filter position="AUTHENTICATION_PROCESSING_FILTER"/>
</beans:bean>
</beans:beans>

The end.

Wednesday, March 12, 2008

Search with Spring Hibernate Lucene and Aspect Oriented Programming in action

I've read a lot about AOP and what it's used for. It is useful for logging, tracing, declarative transactions management and even caching. Great ! I'm going to share with you yet another AOP use case. BTW, I found it really interesting. So, the story.

I have some entity with with field "content" which is HTML text. The number of entries is large and keep growing. It is natural that I want to find some entry which contain some text. So, I need search. Since text is in HTML format, database full text search is not the best solution possible. I've decided to try Lucene. It is a "high-performance, full-featured text search engine library". To use Lucene I need to crate an index, add my objects into it and then I will able to query index to get search results.

Since I'm using Spring, I was looking for Lucene-Spring integration. Bingo ! It is available as one of Spring modules project. This integration has two aspects - one for index management and another for performing actual search. Complete configuration :

<bean id="fsDirectory"
class="org.springmodules.lucene.index.support.FSDirectoryFactoryBean">
<property name="create" value="true"/>
<property name="location" value="file:///C:/temp/index" />
</bean>

<alias name="fsDirectory" alias="indexDirectory"/>

<bean
id="indexFactory"
class="org.springmodules.lucene.index.support.SimpleIndexFactoryBean">
<property name="create" value="true"/>
<property name="directory">
<ref bean="indexDirectory" />
</property>
<property name="analyzer">
<bean class="org.apache.lucene.analysis.standard.StandardAnalyzer"/>
</property>
</bean>

<bean id="indexAccessor"
class="com.mycoolcompany.app.search.LuceneIndexerService">
<property name="indexFactory">
<ref local="indexFactory" />
</property>
</bean>

<bean id="searcherFactory"
class="org.springmodules.lucene.search.factory.SimpleSearcherFactory">
<property name="directory">
<ref bean="indexDirectory" />
</property>
</bean>

<bean id="searchService"
class="com.mycoolcompany.app.search.LuceneSearchService">
<property name="searcherFactory">
<ref local="searcherFactory" />
</property>
<property name="analyzer">
<bean class="org.apache.lucene.analysis.standard.StandardAnalyzer" />
</property>
</bean>

I can pre-populate index by querying database and adding objects to index. But what to do when new entry has been added ? How to keep index up to date ? After some Googling I found solution with custom hibernate interceptor. It looks like this :

import java.io.Serializable;
import org.hibernate.EmptyInterceptor;
import org.hibernate.type.Type;

public class CustomHibernateInterceptor extends EmptyInterceptor
{
private static final long serialVersionUID = -1214372449390884955L;

//injected by spring
private LuceneIndexerService indexAccessor;
public LuceneIndexerService getIndexAccessor() {
return indexAccessor;
}
public void setIndexAccessor(LuceneIndexerService indexAccessor) {
this.indexAccessor = indexAccessor;
}

public boolean onSave(
Object entity,
Serializable id,
Object[] state,
String[] propertyNames,
Type[] types)
{
if (entity instanceof Entry)
{
//adding to index
indexAccessor.add((Entry)entity);
}
return super.onSave(entity, id, state, propertyNames, types);
}
}
Is it something wrong with this solution ? I guess no, it's working. But I have and idea to use AOP here. I guess, adding to index and persisting object to database at the same time is some king of cross-cutting concern. I'm using a Spring-Hibernate DAO for CRUD operations. My idea to resolve this issue is in using aspect. Aspect has a pointcut defined to intercept execution of my dao method addEntry(Entry entry) and "after" advice - this is the place where we can add object to index, after object has been persisted. Please notice that search service is injected into aspect :) All this stuff is very abstract but is pretty interesting to digg. Here is the source code of aspect :
@Aspect
public class IndexForSearchAspect
{
public IndexForSearchAspect()
{
super();
}
//will be injected
private LuceneIndexerService indexAccessor;
public void setIndexAccessor(LuceneIndexerService indexAccessor)
{
this.indexAccessor = indexAccessor;
}
//defining pointcut
@Pointcut("execution (* ....dao.BlogEntryDao.addEntry(....model.Entry))")
public void saveEntryToDB() {}

//add object to index after it has been persisted
@After("saveEntryToDB()")
public void addEntryToLuceneIndex(JoinPoint joinpoint)
{
//getting argument of dao.addEntry()
Entry entry = (Entry) joinpoint.getArgs()[0];
// adding to index
indexAccessor.add(entry);
}
}
Spring configuration for aspect :

<aop:aspectj-autoproxy/>
<bean id="searchindexAspect"
class="com.mycoolcompany.app.search.IndexForSearchAspect">
<!--indexer service will be injected -->
<property name="indexAccessor">
<ref local="indexAccessor"/>
</property>
</bean>

I know, I've missed a lot of details here, so this post is something like show-case, not cookbook :) Any opinions are welcome !