Installing Spring Security On Spring MVC Project

These are steps required to install Spring Security for a form authentication implementation on a Spring MVC project.

  1. Maven Dependencies.

    <dependency>
    	<groupId>org.springframework.security</groupId>
    	<artifactId>spring-security-core</artifactId>
    	<version>3.1.4.RELEASE</version>
    </dependency>
    <dependency>
    	<groupId>org.springframework.security</groupId>
    	<artifactId>spring-security-config</artifactId>
    	<version>3.1.4.RELEASE</version>
    </dependency>
    <dependency>
    	<groupId>org.springframework.security</groupId>
    	<artifactId>spring-security-web</artifactId>
    	<version>3.1.4.RELEASE</version>
    </dependency>
    
  2. Add Spring Security filter to web.xml
    <!-- Spring Security Filter -->
    <filter>
    	<filter-name>springSecurityFilterChain</filter-name>
    	<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>
    
    <filter-mapping>
    	<filter-name>springSecurityFilterChain</filter-name>
    	<url-pattern>/*</url-pattern>
    </filter-mapping>
    
  3. Add a security-context.xml spring beans config file. You can place all your security config on root application context xml but separating it would produce clearer code without namespace prefix clutter
    <!-- On root-context.xml -->
    <import resource="security-context.xml"/>
    
    <!-- On security-context.xml" -->
    <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/security http://www.springframework.org/schema/security/spring-security-3.1.xsd
    		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
    </beans:beans>
    
  4. Add basic HTTP form authentication and provider as seen on Spring reference manual
    <http auto-config='true'>
    	<intercept-url pattern="/**" access="ROLE_USER" />
    </http>
    
    <authentication-manager>
    	<authentication-provider>
    	  <user-service>
    	    <user name="jimi" password="jimispassword" authorities="ROLE_USER, ROLE_ADMIN" />
    	    <user name="bob" password="bobspassword" authorities="ROLE_USER" />
    	  </user-service>
    	</authentication-provider>
    </authentication-manager>
    

Connecting to MongoDB On Visual C++ / Visual Studio 2010

Environment / Dependencies:

  • Windows 7 64bit
  • Visual Studio 2010 (Win32-Release target project)
  • MongoDB 2.2.3
  • Git

Visual Studio 2010 sample client project doesn’t appear to compile on the latest version of mongodb source code (2.4.3 at the time of this writing). It seems the last working sample is version 2.2.3. Follow these steps to compile and use it as your starting point

  1. Clone the source code from git:
    git clone git://github.com/mongodb/mongo.git C:\mongodbsrc
  2. Open command prompt to C:\mongodbsrc, switch to version 2.2.3 by running:
    git checkout r2.2.3
  3. Double click C:\mongodbsrc\src\mongo\client\examples\simple_client_demo.vcxproj. If Visual Studio prompt to upgrade, don’t do it
  4. Compile the project on visual studio and test it. Use this as your starting point
  5. If you’re trying to copy the settings into your own project, pay particular attention to following items:
    • Boost cpp files and mongo_client_lib.cpp inclusion
    • VC++ Directories
    • C/C++ –> General –> Additional Include Directories
    • C/C++ –> Preprocessor –> Preprocessor Definitions
    • Linker –> Input –> Additional Dependencies
    • Additional preprocessor definitions only for these boost files: thread.cpp, tss_dll.cpp, tss_pe.cpp
    • Different Output Files for utf8_codecvt_facet.cpp file

Quick Cheat Sheet

// Connecting to mongodb on c++
mongo::DBClientConnection conn;
conn.connect("localhost");

// mongo shell
db.mycoll.insert({name: "Gerry", age: "25"})

// c++
conn.insert("mydb.mycoll", BSON("name" << "Gerry" << "age" << 25));

// mongo shell
db.mycoll.update({name: "Gerry"}, {name: "Gerry", age: "30"}, {upsert: "true"})

// c++
conn.update("mydb.mycoll", BSON("name" << "Gerry"), BSON("name" << "Gerry" << "age" << 30), 1);

Documentations:

Changing Eclipse Colour Theme

The default eclipse colour scheme is too bright and quite painful to the eye. Trying to change it isn’t the easiest thing to do either as I have spent 30min with no luck. But thanks to the guys behind Eclipse Color Theme plugin, you can change the color theme in an instant.

eclipsecolor

Installing the plugin is way too easy too, just drag and drop button below to running eclipse window (not on the text editor bit — but on the menu / other area)


Once installed and eclipse restarted, you will find following menu on the preference window to change colours

eclipse color theme 01

Unfortunately this only changes the editor window. Many other community attempts to change other components is available here: http://stackoverflow.com/questions/5053834/eclipse-ide-for-java-full-dark-theme but so far I haven’t found one that’s effective & looks good for Eclipse 4 running on Windows 7. Stay tuned will keep you posted.

Binding Date Form Input On Spring MVC

So you have a form that takes a date input like this:

dateform

It’s always handy to represent the form as a Pojo that gets bound automatically to/from your controller class:

public class AddCustomerForm {
  private String name;
  private String email;
  private Date dob;

  /* getters & setters */
}

Notice the usage of java.util.Date type for the dob field. If you do nothing, the binding wouldn’t work and resulting in error instead because Spring MVC doesn’t know how to convert the text form input into a Date object.

The trick here is to add @DateTimeFormat annotation on the date property:

  @DateTimeFormat(pattern = "dd/MM/yyyy")
  private Date dob;

(Since Spring 3.2 you don’t need Joda library to use this annotation)

Now on your controller the form input will automatically binds into your pojo

public String addCustomer(@ModelAttribute("addCustomerForm") AddCustomerForm form) {
  // do something with form input ..
}

Auto Incrementing Field On Spring Data MongoDB

MongoDB came with all sophisticated ObjectId generation feature, but often you just jumped the ship from relational database, and you still want an easy to read / communicate numeric identifier field which automatically increments every time new record is inserted.

One neat suggestion from MongoDB tutorial is to use a counter collection with a ‘counter name’ as its id, and a ‘seq’ field to store the last used number:

db.counters.insert({
  _id: "users",
  seq: 0
})

Then use findAndModify function to increment and obtain the next value.

db.counters.findAndModify({
	query: { _id: name },
	update: { $inc: { seq: 1 } },
	new: true
})

When developing using Spring Data MongoDB, this neat trick can be written as a simple service. Here I used the collection name as the counter name so it’s easy to guess / remember.

import static org.springframework.data.mongodb.core.query.Query.*;
import static org.springframework.data.mongodb.core.query.Criteria.*;
import static org.springframework.data.mongodb.core.FindAndModifyOptions.*;

@Service
public class CounterService {
  @Autowired private MongoOperations mongo;
  
  public int getNextSequence(String collectionName) {

    Counter counter = mongo.findAndModify(
      query(where("_id").is(collectionName)), 
      new Update().inc("seq", 1),
      options().returnNew(true),
      Counter.class);
      
    return counter.getSeq();
  }
}

Counter is just a simple class representing the collection. Please beware the usage of int data type, this will limit to 2^31 entries maximum.

@Document(collection = "counters")
public class Counter {
  @Id private String id;
  private int seq;
  /* getters & setters .. */
}

Then when inserting a new entry (with help of Spring MongoDB Repository support), just set the id field like this before you save it

User newUser = new User();
newUser.setId(counterService.getNextSequence("users"));
newUser.setUsername(username);
newUser.setPassword(password);

userRepository.save(newUser);

You’ll get an incrementing simple numeric id each time you insert new object

Windows 7 nslookup Resolves But Ping And Others Failed

As a wannabe network admin at the office, I’ve been dealing with a really tricky problem for the past few days. Long story short, I have few development servers and I want to setup CNAMEs pointing to it so it’s easy to remember.

The problem is every 15-20min the CNAME will stop resolving. If I try to ping it gives name not found. However nslookup still resolves fine.

I’ve tried many different things with no luck until I finally found the problem: we mistakenly configured multiple public DNS on our DHCP settings alongside our primary internal DNS hosted on Windows Small Business Server 2011 (SBS). As shown below the configuration after we fixed it, only 1 entry is listed pointing to our internal DNS

ipconfig

It seems if multiple DNS servers are configured, windows will pick a primary one at random / round robin. If the primary happens to be the one other than our internal DNS, it won’t be able to resolve the CNAME entries.

This setting can be changed on DHCP configuration tool on SBS as shown below

dhcpconfig

And to make sure internet-wide name resolution still works. The public DNS have to be setup on the internal DNS forwarder on SBS DNS configuration

dnsforwarder

Add to the original confusion was I kept wondering why non CNAME alias still can be resolved all this time. This turns out due to the fact Windows uses not only DNS, but a set of other services to translate hostname into IP:

  1. Client check if the name queried is of its own
  2. Client checks local hosts file (eg: %Systemroot%\System32\Drivers\etc)
  3. DNS are queried
  4. NetBIOS

(Quoted from http://support.microsoft.com/kb/172218)

Notice that if DNS fails on step 3 regular PC names still can be resolved using NetBIOS, but in the case of CNAME it wouldn’t work.

Using GMail With Your Own Domain E-mail

If you own a domain name (for small business or so), myname@mydomain.com email will look more professional than myname@gmail.com. However you might be annoyed having to check multiple mailboxes. Here’s how you can link everything into one GMail mailbox.

Setup Incoming Mail Forwarding On Your Domain Hosting Service

  1. Login into your domain hosting control panel. If you’re on GoDaddy, login to MyAccount and launch E-mail product
  2. Select Create Forward, enter myname@mydomain.com and forward it to myname@gmail.com (you can even add multiple e-mails)
  3. Wait for a few minutes, and at this point you should get incoming mail forwarded to your gmail mailbox

Configure GMail For Sending As myname@mydomain.com

  1. Go to GMail setting (gear icon on the top right), select Accounts and Import
  2. Under Send Mail As section, select Add Another Email You Own, follow the prompt and verification
  3. When sending email, don’t forget to change the From address to myname@mydomain.com