Tuesday, November 3, 2009

Windows vs Linux

Now I am working on windows again, I have come across the dreaded ^M (windows end of line character)... To strip these characters, on linux, open VI and type :1,$ s/{ctrl-V}{ctrl-M}//

Monday, November 2, 2009

Simple performance logging with Spring

We had a problem recently where a call/response to the server was taking 10 seconds. We needed to figure out where the delay was, and the perfect way to do that was using the Spring PerformanceMonitorInterceptor. With Spring 2.0, adding it is a breeze.

In the applicationContext.xml

<bean id="timingLogger" class="org.springframework.aop.interceptor.PerformanceMonitorInterceptor">

<aop:aspectj-autoproxy>
<aop:config>
<aop:advisor pointcut="execution(* com.yourcompany.application.dao.*.*(..))" ref="timingLogger">
</aop:advisor>
</aop:config>
</aop:aspectj-autoproxy>


and then in log4j.properties

log4j.logger.org.springframework.aop.interceptor.PerformanceMonitorInterceptor=TRACE, stdouttrace
log4j.appender.stdouttrace=org.apache.log4j.ConsoleAppender
log4j.appender.stdouttrace.layout=org.apache.log4j.PatternLayout
log4j.appender.stdouttrace.layout.ConversionPattern=%m%n


We found the problem was not in the application, but with the dev server, which was not configured properly to resolve hosts...

Thursday, October 15, 2009

GWT 1.7 (Hosted Mode): Using a data source

Spring Data Source:
Typically your Spring configuration files specify a data source that is used by your persistence layer to access the physical database.

In order to avoid having to keep changing the data source's details per environment in the Spring config files (dev, test, qa, prod), the easy way is to use a JNDI look up for your data source. Each environment will then be responsible for having the correct data source set up for use.

From the Spring configuration file:
<!-- The data source which is looked up via JNDI -->
  <jee:jndi-lookup id="dataSource" jndi-name="jdbc/MyApp" lookup-on-startup="true" />

Data Source in web application
In the web.xml file, define the data source for use:
<!-- The data source that the application uses to access the current database -->
  <resource-ref>
        <description>The Oracle database data source.</description>
        <res-ref-name>jdbc/MyApp</res-ref-name>
        <res-type>javax.sql.DataSource</res-type>
        <res-auth>Container</res-auth>
  </resource-ref> 

GWT 1.7 (Hosted Mode):
Since GWT 1,7 uses Jetty to run in hosted mode, you need to set up a Jetty data source so that Spring has its data source to use when the application is run.

Create a file in the /war/WEB-INF folder called jetty-web.xml and define your data source in there:
<?xml version="1.0"?>
<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN"
"http://jetty.mortbay.org/configure.dtd">
<Configure class="org.mortbay.jetty.webapp.WebAppContext">
  <New id="MyApp" class="org.mortbay.jetty.plus.naming.Resource"> 
    <Arg>jdbc/MyApp</Arg>
    <Arg>
      <New class="oracle.jdbc.pool.OracleDataSource">
        <Set name="user">mast</Set>
        <Set name="password">mast</Set>
        <Set name="URL">jdbc:oracle:thin:@localhost:1521:XE</Set>      
        <Set name="connectionCachingEnabled">true</Set> 
     </New>
    </Arg>
  </New>
</Configure>

Running the GWT Application (Eclipse using Google's GWT Plug-in):
You need to add two Jetty jars to your Eclipse's project classpath, namely:
jetty-name-6.1.x.jar and jetty-plus-6.1.x.jar.
I downloaded Jetty 6.1.19 and used the jars from it.

When you run the application (Right-click the project > Run As > Web Application), you need to modify the Run Configuration slightly.
To modify an existing instance of the application's Run Configuration, use Eclipse's menu option: Run > Run Configurations and select the correct GWT application instance.

On the Arguments tab, add the following VM argument:
-Djava.naming.factory.initial=org.mortbay.naming.InitialContextFactory

Now when you run the application in GWT hosted mode, Spring should have no trouble finding and using the specified data source.

Standalone Mode
Obviously you can do a similar set up for standlone mode (Tomcat or whatever web server you are using) - define the data source in the appropriate way so it is available for the application to use.

Note: the jetty-web.xml file obviously does not need to be deployed with the application into another web container such as Tomcat.

Extjs and Spring Security login.jsp

I went with the GXT-Spring Security approach of a separate login.jsp file, which is all and well, but it required me to worry about styling = booo, bad monkey!

Then, in a flash of inspiration, I decided to try use extjs. It seems there aren't a lot of examples out there of integrating extjs and spring security (formally known as acegi security for the spring framework), so I decided to share mine.

The only problem I face is that when using the ext.Window, I cannot get the username field to get focus. If you have a solution for that, please let me know (I am using extjs 2.0.2)


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<%@ taglib prefix='c' uri='http://java.sun.com/jstl/core_rt' %>
<%@ page import="org.springframework.security.ui.AbstractProcessingFilter" %>
<%@ page import="org.springframework.security.ui.webapp.AuthenticationProcessingFilter" %>
<%@ page import="org.springframework.security.AuthenticationException" %>

<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>Emit 1.0</title>

<link type="text/css" rel="stylesheet" href="Emit.css">
<link rel="stylesheet" type="text/css" href="css/gxt-all.css" />
<script type="text/javascript" src="javascript/ext-base.js"></script>
<script type="text/javascript" src="javascript/ext-all.js"></script>

<script>
Ext.onReady(function(){

Ext.QuickTips.init();

/*var viewport = new Ext.Viewport({
layout:'fit',
width:300,
height:150,
plain:true,
items: [{
contentEl: 'loginForm'
}]
});*/

var loginForm = new Ext.form.FormPanel({
formId: 'appLoginForm',
labelWidth: 80,
frame:true,
title:'Emit 1.0 - please login',
defaultType: 'textfield',
monitorValid: true,
keys:[
{
key : Ext.EventObject.ENTER,
fn: function() {
loginForm.getForm().submit();
}
}],
standardSubmit: true,
items:[
{
id: 'message',
xtype: 'box',
autoEl: {cn: '<font color="red"><c:if test="${!empty SPRING_SECURITY_LAST_EXCEPTION.message}">Login failed, please try again.</c:if></font>'}
},
{
fieldLabel: 'Username',
name: 'j_username',
allowBlank: false
},{
fieldLabel: 'Password',
name: 'j_password',
allowBlank: false,
inputType: 'password'
},
new Ext.form.Checkbox({
boxLabel:'Remember me for two weeks',
hideLabel: true,
name:'_spring_security_remember_me',
inputType:'checkbox'
})
],
buttons:[
{
text: 'Login',
type: 'submit',
id: 'submitButton',
formBind: true,
border: true,
handler: function() {
loginForm.getForm().submit();
}
},{
text: 'Reset',
handler: function() {
loginForm.getForm().reset();
}
}]

});

// This just creates a window to wrap the login form.
// The login object is passed to the items collection.
var win = new Ext.Window({
modal: true,
layout:'fit',
width:300,
height:160,
closable: false,
resizable: false,
draggable: false,
plain: true,
border: false,
items: [loginForm]
});
win.show();

loginForm.getForm().findField('j_username').getEl().focus(true);
loginForm.getForm().getEl().dom.action = "j_spring_security_check";

});
</script>

</head>

<body>
<div id="loginForm"></div>
</body>
</html>

Wednesday, October 7, 2009

Spring Security, customizing the access role prefix

Another Spring Security hurdle: when your access specifiers do not start with ROLE_, you will need to customize the RoleVoter and tell it what 'rolePrefix' to use (or not to use in my case).


<beans:bean id="accessDecisionManager" class="org.springframework.security.vote.AffirmativeBased">
<beans:property name="decisionVoters">
<beans:list>
<beans:bean id="roleVoter" class="org.springframework.security.vote.RoleVoter">
<beans:property name="rolePrefix" value="PREFIX_HERE" />
</beans:bean>
<beans:bean class="org.springframework.security.vote.AuthenticatedVoter"/>
</beans:list>
</beans:property>
</beans:bean>


To use your custom accessDecisionManager, reference it in the http declaration, like so:

<http auto-config="true" ... access-decision-manager-ref="accessDecisionManager">

Tuesday, October 6, 2009

Spring Security, customizing JdbcUserDetailsManager

I've been working on a Spring Security implementation on GWT (GXT to be exact). I wanted to avoid implementing my own UserDetailsService and rather go with customizing the JdbcUserDetailsManager. However, the javadocs for JdbcUserDetailsManager were a little spare (although I just looked at the parent JdbcDaoImpl and saw the tables are defined there). I had to look in the source code to see what kind of results were required, this is my resulting XML definition.

<beans:bean id="userDetailsManager" class="org.springframework.security.userdetails.jdbc.JdbcUserDetailsManager">
<beans:property name="dataSource" ref="dataSource" />
<beans:property name="authenticationManager" ref="authManager" />
<beans:property name="usersByUsernameQuery" value="SELECT user_name, password, 1 FROM users where user_name = ?" />
<beans:property name="authoritiesByUsernameQuery" value="select u.user_name, r.name from users u, role r, user_role ur where ur.user_id = u.user_id and ur.role_id = r.role_id and u.user_name = ?" />
</beans:bean>


Note: the 1 after password indicates the user is enabled.

Thursday, October 1, 2009

GWT server-side integration with Spring (@Autowired)

Old Approach:
Previously we use to load the application's Spring configuration files manually using a custom class (SpringLoader) that was a wrapper around the Spring's ClassPathXmlApplicationContext class. Seemed like an easy way to do things at the time.

All the GWT server-side services would manually look up their required Spring beans which provided the back-end/server tier functionality.
For example:
public class GwtSecurityServiceImpl extends RemoteServiceServlet implements GwtSecurityService {

  /** The service used to check user's access rights and to load user menus. */
  private UserSecurityService userSecurityService = (UserSecurityService) SpringLoader.getBean(SpringBeanId.SECURITY_SERVICE_ID);

public CatchSystemMenu isValidUser(String username, String catchSystem) 
  throws CatchSystemsGwtException {
  ...
  Boolean validUser = userSecurityService.isValidUser(username, catchSystem);
  ...
}


Better Approach:
Use the usual Spring's context listener (defined in the application's web.xml) to load the application's Spring context on application start on.
<context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>classpath:myapp-spring.xml</param-value>
</context-param>
<listener>
  <listener-class>
  org.springframework.web.context.ContextLoaderListener
  </listener-class>
</listener>

Define a base class for all the GWT service classes to extend. This class provides the injection of the Spring managed attributes, using Spring's functionality.

Base GWT service class:
public class SpringRemoteServiceImpl extends RemoteServiceServlet {

  private static final long serialVersionUID = 1L;

  @Override
  public void init() throws ServletException {
    super.init();
    setSpringServices();
  }

  private void setSpringServices() {
    WebApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());
    AutowireCapableBeanFactory beanFactory = ctx.getAutowireCapableBeanFactory();
    beanFactory.autowireBean(this);
  }
}

The individual GWT service classes just extend this class and use the usual Spring @Autowired annotation to inject their Spring-managed attributes.
public class GwtSecurityServiceImpl extends SpringRemoteServiceImpl implements GwtSecurityService {

 /** The service used to check user's access rights and to load user menus. */
 @Autowired
 private UserSecurityService userSecurityService;

 public CatchSystemMenu isValidUser(String username, String catchSystem) 
   throws CatchSystemsGwtException {
 ...
 Boolean validUser = userSecurityService.isValidUser(username, catchSystem);
 ...
 }
}

Nice and easy.
Have a banana.