Skip to content

Understanding JSR299, Contexts and Dependency Injection explained

Forget Session, Application, Request, and Coversation Scope. All these scopes, though useful, still have to be managed by hand. ie.,
– a reference must be created in a session or request (the context)
– a utility method must be written to manage this context (& cleanup eventually)
– the component needs to have access to this utlity method or the context (session, request) to retrive the reference

Most importantly, the “client” component and original “context holder” have direct coupling of the refereced object. With JSR299, it’s like this:

a reference to any object can be injected into any object without actually referring to the object

Really? That’s crazy.

Exactly.

JSR299 container manages thereferences for you in a context (session, requestm, conversation, etc.,) and provides a type-safe way of retrieving these references by a quaifier annotation. For ex, let’s say a PersonSearch Service needs to know the currently logged in user. Normally, you would use a utility function that will return the user. In Spring that would be SecurityContextHolder.getContext().getAuthentication().getPrincipal(). In Seam, it would be something simpler. But what if you don’t want to deal with a service that takes no method parameters and all that you want is a typed object in return?

Think. No parameters.

Would it be easier if you had somethinkg like this?

@LoggedIn
Principal principal;

in your service bean?

By injecting this annotated field, any component in the application can get the “reference to loggedIn user object.” The container holds this reference for any component that asks for it, and it holds it in the scope that the original reference was created. In this case, maye an Authenticator bean created it to keep it in SessionScope. In other words, any “managed” bean (ie., managed by the container, so Stateless, SessionScoped, ApplicatinScoped, etc.,) can get the reference to the logged in user by simply injecting a User object with a qualifier @LoggedInUser. Forget about static methods and manual context management!

But how do you create a @LoggedIn user? Simple, actually.

@Produces @LoggedIn @Named
public User getCurrentUser() {
    return currentUser;
}

In this case, a sessionScoped Authenticator component has a method that returns an instance variable, currentUser.

The advantage of this is loose coupling and at the same time, strong typing. Further, by providing multiple qualifier like @Produces and overriding scopes, the injectable object can be custom defined both at the injectable context and the point of creation (Producer).

Another fine example. Let’s say in the above person search, you want to return the list of persons and tie it to the request scope so that any other component in the same underlying request cycle can retrieve it (JSF page).

@Produces @Named @RequestScoped
public List&<Person> getPersons() {
    return em.createQuery( "select p from Person p" ).getResultList();
}

Even better, you’d like to have a static lookup across the session.

@Produces @Named @SessionScoped public List<Person> getPersons() {
    return em.createQuery( "select p from Person p" ).getResultList();
}

But how do you then update the search list in the session if a new person was added in the same session? Welcome to JEE 6 build in Event Model.

public void onPersonListChanged(
    @Observes( notifyObserver = Reception.IF_EXISTS )
     final Person person ) {
	getPersons();
}

See here to understand what @Reception means.

[Slashdot] [Digg] [Reddit] [del.icio.us] [Facebook] [Technorati] [Google] [StumbleUpon]

Understanding the uses of JEE6 @Decorator vs @Interceptor with an example

Let’s look at an Interceptor first.

Interceptor definition: AuditTime — wraps a simple debug around a method invocation with time stamps.

import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.*;
import java.lang.annotation.*;
import javax.interceptor.*;

@Inherited
@InterceptorBinding
@Target({TYPE, METHOD})
@Retention(RUNTIME)
public @interface AuditTime {
}

Interceptor implementation.

import javax.inject.*;
import javax.interceptor.*;
import org.jboss.logging.*;

@AuditTime
@Interceptor
public class AuditTimeInterceptor implements Serializable {

	private static final long serialVersionUID = 8205679619877467367L;

	@Inject
	Logger log;

	@AroundInvoke
	public Object computeTimestamp(InvocationContext ctx ) throws Exception {

		log.trace( String.format(
			"Starting %s.%s",
			ctx.getMethod().getDeclaringClass().getSimpleName(),
			ctx.getMethod().getName() ) );

		long start = System.currentTimeMillis();

		Object object = ctx.proceed();

		long stop = System.currentTimeMillis();

		log.trace( String.format(
			"Invocation time for %s.%s is %s",
			ctx.getMethod().getDeclaringClass().getSimpleName(),
			ctx.getMethod().getName(),
			String.valueOf( stop - start ) ) );

		return object;
	}
}

Example Usage.

@AuditTime
public void foo(String bar) {
 // do something
}

The above is pretty straight forward. Adding an @AuditTime to any method will provide timestamps. An interceptor as you know adds cross-cutting concerns across methods, across code infratructure, maybe design. But it may not directly influence business decision.

A Decorator on the other hand, is a fine grained interceptor if you want to put it that way. Lets jump straight into an example.

An example User Registration Service

public interface UserRegistrationService {
	String register();
	String update();
	Member getUser();
	public String selectUser(String id );
}

Now, let’s say we want to filter all registrations that has a user email ending with “.ru.”

import javax.decorator.*;
import javax.inject.Inject;
import javax.persistence.*;
import org.jboss.logging.Logger;

import xxx.Service.UserRegistrationService;

@Decorator
public abstract class RegistrationEmailDecorator implements UserRegistration, Serializable {

	private static final long serialVersionUID = 7780160635139112007L;

	@Inject
	private Logger log;

	@PersistenceContext
	EntityManager em;

        // Note: A Decorator is exactly like the decorator pattern. It "is" and "has a" UserRegistration. In JEE6, the "has a" relationship, ie., composition, is explicitly qualified as @Delegate
	@Inject
	@Delegate
	UserRegistrationService service;

	public String register() {
		User u = service.getUser();

		if ( u.getEmail().endsWith( ".ru" ) ) {
			log.info( "Someone with russian domain has registered. Probably a spam, not registering." );

			// do not proceed original call
			return "users";
		}
                          // else, proceed the call.
		return service.register();
	}
}

This is obviously a dumb example but you get the picture. A decorator is different from an interceptor because an interceptor just intercepts any method call (before/after) but doesn’t know the behaviour inside the call. Since a Decorator (Decorator Pattern) implements the decorating class interface and composes it, it can modify the behavior based on business rules.

Thus, decorators provide business rule concerns (sort of “fine grained” interceptors) whereas an interceptor provides system wide, cross-cutting concerns (not related to business). Using both smartly in your JEE6 project can improve readability, and code maintenance.

Of course, don’t go crazy with Decortors or Interceptors making the actual Service calls useless :) . Nothing should override the most important design concern — OO.

[Slashdot] [Digg] [Reddit] [del.icio.us] [Facebook] [Technorati] [Google] [StumbleUpon]

Ivy file for a JEE6 / Seam 3-beta / Primefaces project

Most examples online use Maven for build files. I’m sure some of you are still on ant or Ivy. Here’s an ivy file for a starter JEE6 project with Seam-3-beta (at this time of writing), Primefaces, Prettyfaces and other misc jars (testng) that you might need.


<?xml version="1.0" encoding="ISO-8859-1"?>
<ivy-module version="2.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="http://ant.apache.org/ivy/schemas/ivy.xsd">  

    <configurations>
        <conf name="provided" visibility="public"
            description="this is much like compile, but indicates you expect the JDK or a container to provide it. It is only available on the compilation classpath, and is not transitive." />
        <conf name="compile" visibility="public"
            description="this is the compile scope. Compile dependencies are available in all classpaths." />
        <conf name="test" visibility="public"
            description="this scope indicates that the dependency is not required for normal use of the application, and is only available for the test compilation and execution phases." />
        <conf name="tools" visibility="public"
            description="this scope indicates that the dependency is not required for normal use of the application, and is only available for the build phases (ant builds)." />
    </configurations> 

    <dependencies>

        <!-- PROVIDED              -->

        <!-- JEE 6 -->
        <dependency org="javax" name="javaee-api"
            rev="6.0" conf="provided->default" />
        <dependency org="org.jboss.spec" name="jboss-javaee6-specs-bom"
            rev="1.0.1.Final" conf="provided->default" />

        <!-- Hibernate -->
        <dependency org="org.hibernate" name="hibernate-core" rev="3.5.6-Final"
            conf="provided->default" />
        <dependency org="org.hibernate" name="hibernate-annotations"
            rev="3.5.6-Final" conf="provided->default" />
        <dependency org="org.hibernate" name="hibernate-entitymanager"
            rev="3.5.6-Final" conf="provided->default" />
        <dependency org="org.hibernate" name="hibernate-validator"
            rev="4.0.0.GA" conf="provided->default" />

        <!-- Misc -->
        <dependency org="log4j" name="log4j" rev="1.2.14"
            conf="provided->default" />

        <!-- COMPILE      -->

       <!-- Seam -->
        <dependency org="org.jboss.seam.persistence" name="seam-persistence"
            rev="3.0.0.Beta3" conf="compile->default" transitive="false" />
        <dependency org="org.jboss.seam.faces" name="seam-faces"
            rev="3.0.0.Beta2" conf="compile->default" transitive="false" />
        <dependency org="org.jboss.seam.solder" name="seam-solder"
            rev="3.0.0.Beta3" conf="compile->default" transitive="false" />
        <!--
          Don't use it unless this issue is resolved: https://issues.jboss.org/browse/SEAMCATCH-42
        <dependency org="org.jboss.seam.servlet" name="seam-servlet"
            rev="3.0.0.Beta1" conf="compile->default" transitive="false" />
        <dependency org="org.jboss.seam.catch" name="seam-catch"
            rev="3.0.0.Beta1" conf="compile->default" transitive="false" />
        -->

        <!-- Primefaces  -->
        <dependency org="org.primefaces" name="primefaces" rev="2.2"
            conf="compile->default" transitive="false"/>

        <!-- Prettyfaces  (URL Rewriter)-->
        <dependency org="com.ocpsoft" name="prettyfaces-jsf2" rev="3.2.0"
            conf="compile->default" />

        <!--Envers/Ehcache-->
        <dependency org="org.hibernate" name="hibernate-envers"
            rev="3.5.6-Final" conf="compile->default" transitive="false"/>
        <dependency org="net.sf.ehcache" name="ehcache" rev="1.5.0"
            conf="compile->default" transitive="false"/>

        <!-- Misc -->
        <dependency org="joda-time" name="joda-time" rev="1.6"
            conf="compile->default" transitive="false"/>
        <dependency org="backport-util-concurrent" name="backport-util-concurrent" rev="3.1"
            conf="compile->default" transitive="false" />
        <dependency org="org.apache.poi" name="poi" rev="3.2-FINAL"
            conf="compile->default" transitive="false" />
        <dependency org="com.lowagie" name="itext" rev="2.1.7"
            conf="compile->default" transitive="false" />
        <dependency org="org.slf4j" name="slf4j-api" rev="1.5.10"
            conf="tools->default" />
        <dependency org="org.slf4j" name="slf4j-log4j12" rev="1.6.0"
            conf="tools->default" />

        <!-- TESTING -->
        <dependency org="junit" name="junit" rev="4.8.2" conf="test->default" />
        <dependency org="org.jboss.arquillian" name="arquillian-junit"
            rev="1.0.0.Alpha4" conf="test->default" />
        <dependency org="org.jboss.arquillian.container" name="arquillian-glassfish-embedded-3"
            rev="1.0.0.Alpha4" conf="test->default" />
        <dependency org="org.glassfish.extras" name="glassfish-embedded-all"
            rev="3.0.1-b20" conf="test->default" />
    </dependencies>
</ivy-module>

And the ivy resolvers in settings file would be something like this:


<resolvers>
		<chain name="default" returnFirst="true" dual="true">

			<!-- Local Filesystem -->
			<filesystem name="repos">
				<ivy pattern="${dest.repo.dir}/[organisation]/[module]/ivys/ivy-[revision].xml"/>
				<artifact
						pattern="${dest.repo.dir}/[organisation]/[module]/[type]s/[artifact]-[revision].[ext]"/>
			</filesystem>

			<ibiblio name="maven-fixes" m2compatible="true"
					root="file://${basedir}/maven-fixes/"
					pattern="[organisation]/[module]/[revision]/[artifact]-[revision](-[classifier]).[ext]" />

			<ibiblio name="java.net" m2compatible="true"
					root="http://download.java.net/maven/2/" />

			<!-- JBoss -->
			<ibiblio name="jboss-nexus" m2compatible="true"
					 root="https://repository.jboss.org/nexus/content/groups/developer/"
					 pattern="[organisation]/[module]/[revision]/[artifact]-[revision](-[classifier]).[ext]"/>
		</chain>
[Slashdot] [Digg] [Reddit] [del.icio.us] [Facebook] [Technorati] [Google] [StumbleUpon]

Example of RESTful Webservices in JEE6 with Exception mapper to route HTTP status codes

JEE6 provides a specification for Webservices (SOAP AND REST) and JAX-RS is the default Reference implementation. A lot of cookie-cutter code is eliminated for implementing webservices. Unlike Restlet which doesn’t provide much functionality for integrating restful webservices into a web application (exception mapping and custom annotations to process http params, or DI), JEE6 webservices combine the power of JSR299 along with several utlity methods. For example, an exception mapping provider maps an exception to a Response. If this exception is thrown, the JAX-RS implementation will catch it and invoke the corresponding exception mapping provider. An exception mapping provider is an implementation of ExceptionMapper, annotated with @Provider.

In this example code, let’s walk through a simple usecase where we need to retrieve a list of users via GET using the path: /users/{email}

First, you need to add a JAXRs Activator class. A class extending {@link Application} and annotated with @ApplicationPath is the Java EE 6 “no XML” approach to activating JAX RS.

@ApplicationPath( "/rest" )
public class JaxRsActivator
	extends Application {
	/* class body intentionally left blank */
}

Then, add a RESTful Service class with the correct Path

@Path( "/users" )
@Produces( { "application/xml", "application/json" } )
@RequestScoped
public class UserRESTService {

	@PersistenceContext
	private EntityManager em;

	@Context
	private UriInfo uriInfo;

	@GET
	public List< User> listAllUser() {
	    return em.createNamedQuery( "UserfindAll", User.class ).getResultList();
	}

	@GET
	@Path( "/{email}" )
	public UserlookupUserByEmail(@PathParam( "email" ) String email ) {
		// Note that if NoResultException is thrown by below, NoResultMapper automactically translates to a 404
		Member member = null;
		return em.createNamedQuery( "User.findByEmail", User.class ).setParameter( "email", email ).getSingleResult();			}
}

Finally, write an Exception Translator(s)

@Provider
public class NoResultMapper implements ExceptionMapper< NoResultException > {
    public Response toResponse( NoResultException ex ) {
	return Response.status( 404 ).entity( ex.getMessage() ).type( MediaType.TEXT_PLAIN ).build();
    }
}

As you can see, there are no xml configurations. No surprises. It just works in any standard JEE6 container. Note that webservices are not a part of Web Profile, so you would need a fully certified JEE6 container (glassfish or JBoss).

For other features like mapping http params to method params, DI or other exception handling, watch out for Seam 3 Rest support (currently in beta) which have custom bean validation integrated into http requests, seam-catch exception handling, and other cdi extensions.

[Slashdot] [Digg] [Reddit] [del.icio.us] [Facebook] [Technorati] [Google] [StumbleUpon]

Twitter Mode for Emacs – With OAuth

Twitter’s recent removal of basic authentication eliminated the ability to use quick and dirty methods of posting tweets and viewing timelines, such as via the command-line with cURL. There is one twitter mode, twitel.el, that I had already been using. Supposedly it can handle OAuth through the emacs-oauth package, with some minor custom tweaks to the oauth.el file. Unfortunately, I was unable to get this to work.

Then I found twittering-mode.el.

This is a cakewalk to install and use!

You simply need to follow the few basic instructions from the wiki here: http://www.emacswiki.org/emacs/TwitteringMode

When you run twittering-mode for the first time, you will be prompted to login to the twmode twitter app (via a browser). Enter your credentials and you will receive a pin, which you will then enter into the next prompt from the mode. The OAuth authentication requirements are satisfied by use of the twmode twitter app.

Easy peasy, as some of you would probably say.

UPDATE

To avoid repeatedly retrieving and entering a pin, you can store the encrypted tokens in a local file by enabling:
(setq twittering-use-master-password t)

At this time, you need to download the latest .el file (from the HEAD branch) in order to get this to work:
http://github.com/hayamiz/twittering-mode/raw/master/twittering-mode.el

Enter the mode and follow the prompts to set the master password.

Then, instead of needing to get and enter pins from the twmode twitter app, you simply enter the master password.

For more info on this, see http://github.com/hayamiz/twittering-mode/blob/master/NEWS.

Cheers!

[Slashdot] [Digg] [Reddit] [del.icio.us] [Facebook] [Technorati] [Google] [StumbleUpon]

Gaelyk Chat Bot, Step By Step

Google App Engine’s support for chat is nice, and Gaelyk makes it really groovy. After reading the information about it on the Gaelyk tutorial I thought something must be missing – it seemed like it should be more complicated than it was!

Here is what I did, step by step, to get a chat bot going on my GAE site using gaelyk:

First I created a class to manage my chatting. It contains static references to GAE’s xmpp and datastore objects:

Next I created a simple form to manage invites, complete with backend to initiate the invitations. Keep in mind before you can send and receive messages you need to accept an invitation!:

Form:

Groovy:

Next, I enabled the inbound services on the appengine-web.xml, and the XmppServlet’s on the web.xml. This is described on the gaelyk tutorial.

Lastly, I created jabber.groovy in WEB-INF to handle incoming messages:

TODO:

  • Uninvite, or block those previously invited
  • Mask appid with a better chat name
[Slashdot] [Digg] [Reddit] [del.icio.us] [Facebook] [Technorati] [Google] [StumbleUpon]

Gnus, Emacs, and Gmail; Getting Started

I’ve wanted to set up gnus for email for quite a while, but each time I look at the documentation I find it irritating. The fact is there is a ton of documentation, but all of what I’ve found requires a lot of background knowledge that I don’t have.

But I finally broke through, setting up gnus in my work cygwin environment.

This is probably not going to be the best tutorial I’ve ever written. But it follows my preferred method for learning- start with a working setup, and then figure out how it works. This is different than much of what I see for gnus documentation- which provides some vague concepts and equally vague configuration details. So this will get you started, but you’re going to have to figure out why it works the way it does, and how to improve this setup, just as I am.

Here are the steps I’ve taken:

Via cygwin, I installed emacs 23.2-1 and gnutls-2.8.6-1

I added this to my emacs config. I saw some instructions that suggested you could put this in gnus.el, but when I did that gnus broke without a useful error message.

Open up emacs, start gnus with M-x gnus

It takes a while to start up. I get an “unable to open server nntp+news, go offline? I respond n

nntp (news) open error: ”. Continue? I respond y

Gnus auto save file exists. Do you want to read it? I respond y

Next I should see some debug output when it goes to get your mail from gmail.

I can see it downloads some mail.

Next gnus displays a set of newsgroups, including some help messages I did not find helpful at all.

To find your mail, enter “B”, this will prompt you for “Which back end:” type nnml. It will prompt for “Address:” hit enter.

You will see a group “mail.misc”, this is your email. Hit enter to view the list of mail downloaded.

typing ‘m’ will prompt you to create an email. Fill out the fields and when you’re finished, type C-c C-c to send. Sending will prompt you for your password.

That’s all for now.

[Slashdot] [Digg] [Reddit] [del.icio.us] [Facebook] [Technorati] [Google] [StumbleUpon]

Spring Security 3 Unit Testing Example with DbUnit

This tutorial extends on the baseline laid by Spring Security Tutorial maven archetype.

I’ve modified the spring security config file and will be unit testing a simple ProfileService (CRUD) on a Profile entity (User object). The tests include login/logout and spring services security unit testing.

application-security.xml

<?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-3.0.xsd

http://www.springframework.org/schema/security

http://www.springframework.org/schema/security/spring-security-3.0.xsd">

	<global-method-security pre-post-annotations="enabled"/>

	<http use-expressions="true">
		<intercept-url pattern="/secure/extreme/**" access="hasRole('ROLE_SUPERVISOR')"/>
		<intercept-url pattern="/secure/**" access="isAuthenticated()" />
		<intercept-url pattern="/**" access="permitAll" />
		<form-login />
		<logout />
		<remember-me />

		<!-- Uncomment to limit the number of sessions a user can have -->
		<session-management invalid-session-url="/timeout.jsp">
			<concurrency-control max-sessions="1" error-if-maximum-exceeded="true" />
		</session-management>
	</http>

	<authentication-manager>
		<authentication-provider>
			<!--  <password-encoder hash="md5"/> -->
			<user-service>
				<user name="admin" password="admin" authorities="ROLE_ADMIN, ROLE_USER" />
				<user name="user" password="user" authorities="ROLE_USER" />
				<user name="reports" password="reports" authorities="ROLE_REPORTS" />
			</user-service>
		</authentication-provider>
	</authentication-manager>	

</beans:beans>

Base DB Unit Test with utils for Spring Security

import java.io.FileInputStream;
import java.sql.Connection;
import javax.inject.Inject;
import javax.sql.DataSource;
import org.apache.log4j.Logger;
import org.dbunit.database.*;
import org.dbunit.operation.DatabaseOperation;
import org.springframework.jdbc.datasource.DataSourceUtils;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.test.context.transaction.*;

/**
 * Base Test that wraps a DbUnit style Test case by inserting a sample testdata
 * on startup. Provides necessary functions to login/logout, add roles, etc
 */
public abstract class BaseSecurityTest {

	private static final Logger logger = Logger
			.getLogger(BaseSecurityTest.class);

	Connection con;
	IDatabaseConnection dbUnitCon;
	IDataSet dataSet;

	@Inject
	private DataSource dataSource;

	protected abstract String getTestClassname();

	@BeforeTransaction
	public void beforeTx() throws Exception {
		logger.debug("Opening Db Connection ... ");
		con = DataSourceUtils.getConnection(dataSource);
		dbUnitCon = new DatabaseConnection(con);
		dataSet = getDataSet(getTestClassname());

		DatabaseOperation.CLEAN_INSERT.execute(dbUnitCon, dataSet);
	}

	@AfterTransaction
	public void afterTx() throws Exception {
		logger.debug("Releasing Db Connection ...");
		DataSourceUtils.releaseConnection(con, dataSource);
	}

	protected IDataSet getDataSet(String name) throws Exception {
		return new FlatXmlDataSetBuilder().build(new FileInputStream(
				"src/test/resources/" + name + ".xml"));
	}

	protected void clearContext() {
		SecurityContextHolder.clearContext();
	}

	protected void login(String username, String password) {
		SecurityContextHolder.getContext().setAuthentication(
				new UsernamePasswordAuthenticationToken(username, password));

		logger.debug("User:" + username + " logged in");
	}

	protected String getLoginDetails() {
		Object principal = SecurityContextHolder.getContext()
				.getAuthentication().getPrincipal();

		if (principal instanceof UserDetails) {
			return ((UserDetails)principal).getUsername();
		}
		else {
			return principal.toString();
		}

	}
}

ProfileServiceTest

import static org.junit.Assert.assertEquals;
import java.util.List;
import javax.inject.Inject;
import org.apache.log4j.Logger;
import xxx.Profile;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.transaction.TransactionConfiguration;
import org.springframework.transaction.annotation.Transactional;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {
		"classpath*:spring/applicationContext-core.xml",
		"classpath*:spring/applicationContext-mail.xml",
		"classpath*:spring/applicationContext-security.xml" })
@TransactionConfiguration
@Transactional
public class ProfileServiceTest extends BaseSecurityTest {

	private static final Logger logger = Logger
			.getLogger(ProfileServiceTest.class);

	@Inject
	private ProfileService profileService;

	@Override
	protected String getTestClassname() {
		return "ProfileServiceTest";
	}

	@Test
	public void testUserLogin() {
		login("admin", "admin");
		String username = getLoginDetails();
		assertEquals(username, "admin");

		login("user", "user");
		String username2 = getLoginDetails();
		assertEquals(username2, "user");

		login("reports", "reports");
		String username3 = getLoginDetails();
		assertEquals(username3, "reports");
	}

	@Test
	public void testRead() {

		// Test with role that has access to the service
		login("user", "user");
		profileService.read("1");

		login("reports", "reports");
		profileService.read("1");

		// Test with role that doesn't have access to the service
		login("admin", "admin");
		try {
			profileService.read("1");
		}
		catch (AccessDeniedException e) {
			// Expected
			assert(true);
			return;
		}

		// it should not reach here
		assert(false);
	}

	@Test
	public void testFindProfiles() {
		List<Profile> list = profileService.FindProfiles();
		assertEquals(4, list.size());
	}

	@Test
	public void testFindProfileById() {
		List<Profile> list = profileService.findProfileById("123");
		assertEquals(1, list.size());
	}

	@Test
	public void testSave() {

		// Test with role that has access to the service
		login("admin", "admin");
		Profile dummy = new Profile();
		profileService.save(dummy);		

		// Test with role that doesn't have access to the service
		login("reports", "reports");
		try {
			profileService.save(dummy);
		}
		catch (AccessDeniedException e) {
			// Expected
			assert(true);
			return;
		}

		// it should not reach here
		assert(false);
	}
}

The Profile Service

public interface ProfileService {

	@PreAuthorize("hasRole('ROLE_USER') or hasRole('ROLE_REPORTS')")
	Profile read(String id);

	List<Profile> findProfiles();

	List<Profile> findProfileById(String Id);

	@PreAuthorize("hasRole('ROLE_ADMIN') or hasRole('ROLE_USER')")
	Profile save(Profile account);

	@PreAuthorize("hasRole('ROLE_ADMIN')")
	void delete();

}
[Slashdot] [Digg] [Reddit] [del.icio.us] [Facebook] [Technorati] [Google] [StumbleUpon]

GIT Commands I Need to Memorize

I work as an application developer. Most of my career has been spent in large corporate environments that have configuration management teams, systems administrators, dbas, etc in addition to software engineers. As such I am a version control user, and not an administrator or power user.

During my daily routine I commit to a remote repo, and I update my existing repo. I regularly compare my local changes with existing ones, and I regularly look at commit history.

I rarely branch code, I rarely check out branches or commit to branches other than the trunk.

I’ve done this with CVS (which still remains my preferred vcs), Visual Source Safe, SVN, and StarTeam (which happens to be my least favorite vcs).

When I first learned about GIT a couple of years ago, I was interested to hear that it was somehow different than these other systems.

I’ve been using GIT very irregularly for the last couple of years, I have a small github account. But I haven’t used it enough to commit the standard commands (listed above) to memory. So this then is my meager attempt at doing so:
*** This assumes you’ve installed git and have configured the global settings.

  • Creating a repo:

    mkdir project
    (create some code in the directory)
    cd project
    git init
    

    But wait there’s more…
    This is deceptively easy. In fact you’re more likely to want to create a local and remote repository, a la github style for example.
    In that case, you’re going to want to do this:

    1. Create a remote repo
    2. Generate your ssh-keys
    3. Git init, like above
    4. git add file_to_commit
      git commit -m 'first commit of all files added'
      git remote add origin git@github.com:user/git-repo.git
      
  • Check out an existing repo:
    This is pretty straightforward, but assumes you’ve set up your ssh-keys.

     git clone [url] 
  • Commit local changes:
    Once you start working, a benefit of having a local repository is that you can commit a lot, without having to worry about breaking a continuous integration environment in the process.
    This is pretty much the same as with other vcs.
    First add:

     git add somefile.txt 

    Then commit:

     commit -m 'my message' 

    Caveat:

    • It’s probably useful to add a couple of files at once, rather than one at a time:
       git add one.txt two.txt 

      or

       git add 'documentation/*.screen' 

      will recursively add all new files ending with .screen from the documentation directory

    •  git status -s 

      will tell you what has been added, and what has been changed since the add. (-s is for short format)

    • Commit changes to remote repo
       git push origin master 
  • Remove stuff:

     git rm file 

    will remove the file from the staging area entirely and also off your disk.

     git rm -r dir 

    recursive delete

  • Check what’s been committed:
    This is different than status because I want to know what’s different between my remote repo and my local one.

     git diff --stat master...origin

    Git will automatically figure out what the common commit of the two commit is and do the diff off of that.

Hat tips:
Git Reference – my favorite site I’ve found explaining git. It’s practical, provides examples, and the authors don’t go out of their way to make simple concepts seem complex. I’ve paraphrased a few of their examples here.

[Slashdot] [Digg] [Reddit] [del.icio.us] [Facebook] [Technorati] [Google] [StumbleUpon]

Subversion, JavaHL, and Eclipse on Linux

I normally use emacs and command line svn when working at home on Linux. Eclipse to me, in principle, is a necessary evil of programming with larger groups. But a recent volunteer project I’ve been working on for the Philippine Scholars of Minnesota is forcing me out of this habit.

And with this change, I’ve suddenly been introduced to the world of JavaHL. So what is JavaHL? Per the previous link, it’s the Java language binding for the Subversion API. On Windows the subclipse project is able to package JavaHL, but not on other operating systems. So that’s why I’ve never had to deal with it before.

Fortunately, after finding out what JavaHL actually is, it’s pretty easy to install on Ubuntu, as you might expect:

sudo apt-get install libsvn-java

This will install JavaHL to /usr/lib/jni as a standard install, and this is where eclipse will look for it by default. If you’ve installed it in a non-standard way, you might want to look at this link regarding overwriting the java.library.path with an eclipserc file.

[Slashdot] [Digg] [Reddit] [del.icio.us] [Facebook] [Technorati] [Google] [StumbleUpon]