Showing posts with label spring. Show all posts
Showing posts with label spring. Show all posts

Saturday, March 27, 2010

Registering custom property editors with Spring MVC

Recently I've been able to concentrate much more on more normal coding tasks rather than just figuring out how to configure my application. I got to the point where I wanted to receive data entered and use that to automatically fill in property values for a business object. Fortunately Spring does have support for this. You just add a parameter of the type of your desired object and Spring will setup the properties based on their names from the encoded form values.

Spring has built-in support for conversion from Strings to a large variety of types. But if your business objects has a property of an unsupported type you need to register your own custom property editor that converts a String to that unsupported type. It took me a few tries to get it right but I seem to have gotten my custom editor set up properly now.

The mistakes I made were the following:

First I was trying to set up a CustomEditorConfigurer bean in my application context and use its customEditors property to map my class to an editor. Then I noticed that the customEditors property was deprecated in Spring 3. So I changed my setup to use a PropertyEditorRegistrar instead to register my custom property editor. This still didn't work. Then I figured out that if you just add these as beans in the application context they are probably only available for converting Strings inside that application context. If you want your property editors to be available for binding web requests to objects you need to use Spring's Controller's initBinder method to register your editor with a binder. And if you are using annotation-based controller you additionally need to use the @InitBinder annotation on that method.

Thursday, March 18, 2010

Finally got my whole Java EE stack completed

Ok just a quick update. Adding spring declarative transaction did the trick. I was now able to add a new user account through the a web form -> Spring Controller -> EntityManager and it shows up in my user list for testing purposes. I'm still gonna finish reading the Spring Transaction chapter and then I think I can finally start working on my domain model and then move on to the Controllers and views.

By the way. Annotation-based Spring MVC seems pretty good. There is a great deal of flexibility both in terms of what types of input your controller methods can take and what output they can return. Spring basically reads your thoughts and figures out what you wanted to do. Well not really, but it's very flexible. It almost feels a bit un-Java-like. Spring MVC with annotations basically fulfills the requirements that made me search for a rest-framework without the rest parts that I don't really care too much about when making a human-facing web application (such as content negotiation regarding different input and output formats, like json and xml.)

Settled on Spring MVC

Ok it wasn't as bad as I briefly anticipated to set up a url redirection scheme for getting nice URLs with Spring MVC. I found this nice answer on stackoverflow that actually linked to a sample MVC project in spring's repository that shows a really easy to use example of how to use the Tuckey url rewriting filter.

Firsty you simply map all your Spring MVC classes under a path like /controllers. Then you set up explicit redirects to all your subdirectories that contain static files like /javascript, /css and so on and anything that doesn't match that gets mapped to a url where the path starts with /controllers. After doing this I almost (but not quite yet) have figured out all the parts to be used in a simple web app. I was able to get my Spring-managed EntityManager injected and managed to get it to run some queries. But I still have to read the Spring manual chapter on transactions because I still don't feel like I know that well how they work yet. I could just follow a tutorial and just use the <tx:annotation-driven> element and annotate my classes and methods with @Transactional and everything would probably work. But like with all other technologies I've been learning for Java EE recently, I don't like using stuff without understanding how they work.

Monday, March 15, 2010

Frustration with java web frameworks

I've been delayed in doing any actual work on my first java EE web app because of web framework problems. I gave up on trying to get a definite answer on how @PersistenceContext works and thought I'd just try to see if I could get Jersey Resource backed by an EntityManager to work and output some hello world stuff. After correcting a few configuration mistakes I got some weird exceptions. I found some mailing list discussion that indicated that I was mixing different versions of spring modules. I was a bit surprised because I remember picking the 3.0.X version on all my modules. However it turned out that my jersey-spring integration library depended on a module called spring which was at version 2.5.6. Unfortunately Jersey doesn't have an IRC channel so I wasn't really able to verify if this was causing the problem.

So I did what I was trying to avoid doing. I tried switching to Spring MVC. I had understood it had support for "restful" URLs. After a while though I noticed that you are not supposed to use /* as the url-pattern for Spring's DispatcherServlet because the views are resolved through the DispatcherServlet. This means that if you try to redirect to /WEB-INF/jsp/myresource_show.jsp for example, DispatcherServlet will try to match that URL to a Controller. Since you probably haven't defined this as the mapping for a Controller you will get a No mapping found error. This also means that the DispatcherServlet will attempt to map all static files (images, css, javascript) to Controllers. This is probably because Spring isn't that different from Struts as I had hoped for, and it wants you to suffix actions with something silly like ".do". But I don't want to do that. Another solution is putting your resources in a special resources subdir and putting that as your url-pattern for DispatcherServlet. Alternatively you should be able to do create some sort of elaborate url-rewriting scheme. Uuugh. Why couldn't just jersey-spring play nicely?

Friday, March 12, 2010

Integrating a Spring application context with a web application

I think I finally figured it out last night. Most of the tutorials and documentation on using Spring's DI container seemed to only show to programmatically create an ApplicationContext by instantiating a subclass of it in a main method. So I was trying to figure out where you were supposed to do this in a web application. I had forgotten that you could use a ContextLoaderListener that would create an ApplicationContext (known as the root app context) from the xml files listed in an init-param in the web app context. But even when I rediscovered that, I had trouble figuring out if my Jersey Controllers were supposed to manually get beans from this root app context somehow.

So I spent a while browsing through various tutorials and the Spring documentation, and asked a lot of questions in the #spring IRC channel. At one point it eventually clicked and I figured out that most web frameworks need to provide some way of integrating with Spring, as opposed to this being completely standardized from Spring's side. The thing that made me figure this out was that I looked at how Spring MVC integrates with Spring beans and how Jersey integrates with Spring beans.

- Spring MVC has a DispatcherServlet that retrieves beans which extend Controller from an application context on the classpath that is named servletname-servlet.xml
- Jersey retrieves classes annotated with @Component from the root web app context
- Struts uses a Spring plugin that defines the application context file where the required Struts Actions are wired

And when I realized this, I noticed why I had been going about it the wrong way earlier when I was trying to figure out how to get the root web app context to manually get my beans from there. Although I also learned about Spring's WebApplicationContextUtils which would allow me to do that if needed.

Wednesday, March 10, 2010

Much progress with hibernate and JNDI with Jetty

Today I've been reading a lot about Hibernate and setting up JNDI objects in Jetty. I was trying to find out more about how to solve the problem of loading the same sample data set into an hsqld database every time I start Jetty.

At first I had planned to create a servletContextListener that would use DbUnit to import the data when the context is initialized. But since I am using Hibernate's hbm2ddl.auto option for automatically creating the database tables, I wanted to make sure the tables had been created by the time the servletContextListener is supposed to import the data into them.

The first step was to figure out how worked in servlet containers and specifically how to configure Jetty to create them. I set up an hsqld.DataSource and stored it in the InitialContext so it can be retrieved using JNDI. I also noticed you can get objects from JNDI Contexts in Spring's DI container.

Then I moved on to finding out what causes Hibernate to create the tables. First Persistence.createEntityManager(nameOfPersistenceContext) is called, which in turn causes a Hibernate SessionFactory to be created. This automatically exports schema DDL to the database when hbm2ddl.auto is true. Well I took a long break here and noticed that I have to continue with this tomorrow. I have to see if you are supposed to create some webapp-global objects in the servlet container itself or if Spring has some way to create beans that would be global for the servlet container.

Tuesday, March 9, 2010

Filling a database with some test data

I think I've got a decent understanding of Spring security now and would like to test that everything works. I need to figure out a way to put up a new database when running Jetty and put some rows into a user table. I am using hsqldb for the few small persistence tests I've written so far. I thought I would also use hsqldb for manually testing my application when it runs in Jetty. The Java EE-book I've read mentioned that you can use DbUnit to import data into a database from an XML file. But I think the main problem at the moment is that I have an inadequate understanding of hsqldb, so I'll have to start by learning more about that.

Friday, March 5, 2010

Learning about authentication

So now I have my Hibernate EntityManager working and a simple User entity that works. Jersey also seems to be working. The next step was thinking about user authentication. I've rolled my own user authentication earlier with PHP where I just had a simple salt and stored the password's hash, then when a user logs in his/her authorization-related details are stored in the session data. I could probably have translated this to Java but decided to look at some standard ways of doing it instead. So I did some internet detective work. The java EE-book I had been using mentioned Wicket's WASP (or maybe it was SWARM) system for authenticating users. WASP/SWARM also seemed to rely on acegi security so I googled for that and found out that it's now part of the Spring Framework as Spring Security. Then I watched a very nice introductory presentation video about Spring Security. It seems both easy to use and seems to be very flexible so I think I'm gonna go with Spring Security.