Web

JSP Tag Pooling Memory Leaks

JSP custom tags were once widely used, but even still nowadays they find their way into projects. Not to mention the masses of production code using them. And almost all projects I have looked at using custom tags had the same issue. When writing JSP custom tags you have to remember the lifecycle model of a custom tag, because the container will typically pool tag instances. This is allowed and recommended by the specification, but can create lots of trouble when the tag is incorrectly written. Storing big objects in the tag instance will create a memory leak that can make your server go boom (or nothing happens because your tag pool is small and the instance is almost al time in use).Typically this sneaks by unnoticed in development environment.

The code causing this problem looks typically like this one here:

public class MyTag extends TagSupport {
  public Object leak;
  public int doStartTag(){
    leak = new BigObject();
  }
}

This is a problem, because the lifecycle of a pooled tag looks like this:

  1. load class
  2. create instance
  3. invoke setPageContext()
  4. invoke setters
  5. call doStartTag
  6. call possibly other tag methods depending on the tag type and return values
  7. call doEndTag()
  8. put instance in pool

when the same tag is re-requested it may start at step 3. If in the above example this tag is pooled lets say with 10 instances and 10 simultaneous requests, 10 instances are created in the pool. But after that only a few requests come in. But still 10 instances of the tag are in the pool and contain reference to the BigObject. This is a memory leak.

To avoid this always null out “transient” instance variables of the class and reload them either in setPageContext() or doStartTag(). Also note that the code inside the constructor might only be run once per tag, even when the tag is used on hundreds of pages. The amount of tag instances created (and thus also the amount of constructors invoked) depends on the container and pool settings and on the serverload.

public class MyTag extends TagSupport {
  public Object noLeak;
 
  public void setPageContext(PageContext pc){
    noLeak = new BigObject();
  }
 
  public int doStartTag(){
  }
 
  public void doEndTag(){
    noLeak = null;
  }
}

Other alternatives are to improve code design and make variables as local as possible.
A relates problem is that you might find values in your tag that you don’t expect. Lets say a property is set when a certain parameter has a specific value. Now that condition was true, so the property holds an object that is not nulled out. The next usage of that tag will find the object even though the condition on the parameter is not set. This can really mess up your logic.

Fabian Lange

 

Multiple select with Spring MVC

During our coding night (there’s be a separate blog for it), we committed ourselves to use only Spring technologies. But a simple requirement had a rather dramatic effect.

How do you create a multiple select box with Spring MVC? You should be able to select multiple elements, which then get added to a collection of the backing bean.

We are implementing a simple time tracking application. The domain model contains projects, which can have staff members assigned. Projects have tasks, which also have staff members assigned to. So in the task creation view we need a select box that contains all available employees.

Model

Here are the most important extracts from Tasks and Staff members:

Task

@Entity
public class Task implements Serializable {
	@Id
	@GeneratedValue
	private long id;
 
	@ManyToMany
	private Set<Staff> staffs = new HashSet<Staff>(0);
 
	//...
}

Staff

@NamedQuery(name = "staff.activeStaff", query = "select s from Staff s where s.disabled = false")
@Entity
@DiscriminatorValue("STAFF")
public class Staff extends Person {
 
	//...
}

Person

@NamedQuery(name = "person.findByUsername", query = "from Person p where p.login.username = :username")
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "type", discriminatorType = DiscriminatorType.STRING)
public abstract class Person implements Serializable {
 
	@Id
	@GeneratedValue
	private long id;
 
	//...
}

View

In the task creation view, we need a select box that shows all available employees. The selected employees shall then be assigned to the task when the form is submitted.

@Controller
@SessionAttributes("project")
public class ProjectController {
	@RequestMapping(method = RequestMethod.GET, value = "/project/createTask.action")
	public void createTaskView(@ModelAttribute Task task, Model model) {
		List<Staff> activeStaff = timetrackingService.getActiveStaff();
		model.addAttribute("activeStaff", activeStaff);
	}
 
	//...

The JSP that belongs to the controller contains this snippet for the select box:

<td><label for="staffs">Chose Staff: </label></td>
<td><form:select path="staffs" multiple="true" items="${activeStaff}" itemLabel="fullName" itemValue="id"/></td>
<td><form:errors path="staffs" /></td>

The problem is, as soon as you submit the form, you will get a ServletRequestBindingException, because Spring has no idea how to map a String (or String[] when multiple staff members have been selected) to a Set.

org.springframework.web.bind.ServletRequestBindingException: Errors binding onto object 'task'; nested exception is org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 errors
Field error in object 'task' on field 'staffs': rejected value [3]; codes [typeMismatch.task.staffs,typeMismatch.staffs,typeMismatch.java.util.Set,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [task.staffs,staffs]; arguments []; default message [staffs]]; default message [Failed to convert property value of type [java.lang.String] to required type [java.util.Set] for property 'staffs'; nested exception is java.lang.IllegalArgumentException: Cannot convert value of type [java.lang.String] to required type [de.codecentric.timetracking.model.Staff] for property 'staffs[0]': no matching editors or conversion strategy found]

Additionally, the generated HTML is missing the ID for staff members!

<select id="staffs" multiple="multiple" name="staffs">
<option value="">firstname lastname</option>
<option value="">aaaa aaaa</option>
<option value="">firstname lastName</option>
<option value="">firstname aaaa</option>
<option value="">firstname lastname</option>
</select>
<input type="hidden" value="1" name="_staffs"/>

Id as String

In order to have the staff member ID in the value attribute of the option element, we can create a new getter in the Person class that returns the id as String, and then use that in the JSP:

public abstract class Person implements Serializable {
	//...
	public String getIdAsString() {
		return new Long(id).toString();
	}
}
<form:select path="staffs" itemValue="idAsString" multiple="true" items="${activeStaff}" itemLabel="fullName"/>

InitBinder

The solution to the binding problem is more difficult. We need a PropertyEditor for the attribute ’staffs’. Spring contains a number of PropertyEditors, so we can use the CustomCollectionEditor. It is expected that the property editor can map the string from options value back to the element, so we need to store that mapping somewhere, in a map for example.

public class ProjectController {
 
private Map<String, Staff> staffCache;
 
@RequestMapping(method = RequestMethod.GET, value = "/project/createTask.action")
public void createTaskView(@ModelAttribute Task task, Model model) {
	List<Staff> activeStaff = timetrackingService.getActiveStaff();
	staffCache = new HashMap<String, Staff>();
	for (Staff staff : activeStaff) {
		staffCache.put(staff.getIdAsString(), staff);
	}
	model.addAttribute("activeStaff", activeStaff);
}
 
@InitBinder
protected void initBinder(WebDataBinder binder) throws Exception {
	binder.registerCustomEditor(Set.class, "staffs", new CustomCollectionEditor(Set.class) {
		protected Object convertElement(Object element) {
			if (element instanceof Staff) {
				System.out.println("Converting from Staff to Staff: " + element);
				return element;
			}
			if (element instanceof String) {
				Staff staff = staffCache.get(element);
				System.out.println("Looking up staff for id " + element + ": " + staff);
				return staff;
			}
			System.out.println("Don't know what to do with: " + element);
			return null;
		}
	});
}

The code still contains some debug output to System.out, which has to be removed. But it shows that the method is called very frequently. Only for showing the select box with 5 employees, the method is caller 15 times. 10 times the id is passed in as a String, and 5 times the object is passed in. I have found no good documentation what exact behaviour is expected from that PropertyEditor, this is the best working solution I could come up with.

Looking up staff for id 1: Staff(firstname lastname)
Looking up staff for id 1: Staff(firstname lastname)
Converting from Staff to Staff: Staff(firstname lastname)
Looking up staff for id 2: Staff(aaaa aaaa)
Looking up staff for id 2: Staff(aaaa aaaa)
Converting from Staff to Staff: Staff(aaaa aaaa)
Looking up staff for id 3: Staff(firstname lastName)
Looking up staff for id 3: Staff(firstname lastName)
Converting from Staff to Staff: Staff(firstname lastName)
Looking up staff for id 4: Staff(firstname aaaa)
Looking up staff for id 4: Staff(firstname aaaa)
Converting from Staff to Staff: Staff(firstname aaaa)
Looking up staff for id 5: Staff(firstname lastname)
Looking up staff for id 5: Staff(firstname lastname)
Converting from Staff to Staff: Staff(firstname lastname)

After selecting an employee and submitting the form, expectedly there’s only one line in the log, converting the id back to the staff member.:

Looking up staff for id 3: Staff(firstname lastName)

Conclusion

With the massive amount of web frameworks around, I find it surprisingly complicated to achieve something as simple as a multiple select box in Spring MVC. But, I just leard Spring MVC yesterday, so I might not know all details yet. So if there’s a more elegant and simpler solution to achieve the same as described above, I very much welcome your feedback.

Andreas Ebbert-Karroum

 

Java Framework Marketing

First impression is important, because it sets many of our expectations. When looking for a certain framework or technology to use, reference customers or case studies are highly appreciated because they build already some trust into the technology. Following the decisions of big companies might be questionable, but of course be a  much safer alternative than being the first to use a technology or framework. But not only case studies, but also community pages (more than just a dead forum or wiki) with feeds, buzz and blog, or screen casts, should be state of the art nowadays, showing active development of and support for the framework. Of course the presentation of your framework should be pleasant to view and be a prime example of how to use it, especially for a web framework.

But how do big Java Web Frameworks handle this first impression?

  • Tapestry, is a very nice framework having handy generators, with its site having no marketing section, the maximum you can get is a downloadable badge, which you can put on your site to claim being tapestry powered. The documentation pages look static and the wiki a bit chaotic, but reveals after some searching a page that lists references. At least the site is clean and doesn’t look outdated.
  • Struts, in Version 2, the successor of perhaps the most often used Java Web framework. Aged and sometimes outdated information – Not at all an appealing site. Unless you know what you are searching for you cannot find anything and the wiki suffers from duplication (perhaps due to the merge of WebWork and Struts2) and outdated pages.
  • Java Server Faces, represented by the biggest “Community Player”: MyFaces, also has poor marketing. MyFaces recently revamped their website, but still no facts and figures about customers, and no demo. Quite a lot Technology information, but no page aiming at convincing the user that MyFaces is the right choice.
  • Spring MVC or Web Flow doesn’t have a marketing oriented site as well. Excellent Documentation and Forums help Developers, but might not convince decision makers.
  • Wicket, being the Java Web Framework outlaw, seems to be positioned more to the marketing side. Blogs, Aggregated feeds, live demos and a Buzz page paint a vivid picture about the state of the framework.

Now have a look at the outlaws: the scripters and dynamic web languages. Lets pick one each:

  • The PHP “symfony framework” talks about its success: large installations at dailymotion, Yahoo! Answers, Bookmarks and Delicious. Blog, Forum, Wiki (which however could deserve a cleanup), Screencasts, plenty of user contributed Documentation and team written documentation are available. Of course the site itself is made with symfony. The recently launched standalone components have an even more appealing website.
  • Ruby on Rails has even an application gallery, where it showcases big sites like twitter, basecamp or the yellow pages. High quality screen casts User contributes How-tos and Blog keep the Community connected, informed and involved. “Get Excited” is the title of the first and most prominent section on their page – hard time resisting to click it.
  • Django, the python based web framework, has a complete site dedicated to list applications powered by django, even though it doesn’t list “big ones”, a blog and a large community wiki with clear rules for ticket creation. Although the layout is not optimal and the site is heavy on text, you can find what you are looking for quite easily.

So with the exception of Wicket, I must conclude that Java Web frameworks neglect the PR side of the project. I am not sure if that is really the case but from my observations it is like that.
Some ideas why this is the case:

  • Java is placed in business sector, no interest in mass market web.
  • Java is developed by eggheads, great examples and docs, but no marketing affinity.
  • Java doesn’t scale the way the mass market web scales. Is a shared nothing architecture better for that than a clustered architecture?
  • There are too much big players in Java. In other languages the big players are easier to identify.
  • Java developers like to produce quality code instead of writing case studies
  • Java frameworks websites either use java.net, apache.org or maven-site style which is structured, but not appealing at all.

As a fan of many Java libs and frameworks this makes me a bit sad. What I would like to ask for:

  • Do good and talk about it. No need to exagerate, but show what you can.
  • Your framework is good. Use it to power your site. It takes time but is the best showcase for you.
  • Use state of the art tools like a blog and wiki (yes web 2.0 should finally arrive)
  • Be transparent – Use a bugtracker which is fast and easy to use, goodbye bugzilla.
  • Make a simple design.  There are even free ones on the net. Keep in mind that you are presenting yourself.
Fabian Lange

 

Struts2 Interface and EJB issues

Today I want to write about an issue that occurred to me with Struts2, but it is also valid for other scenarios. Ill first give an example:

Elections in the States are coming close, so we are going to make a favorite poll.

First implement a service that has three methods:

public interface ElectionFavorite {
  public List getFavs(int userId);
  public List getChoices();
  public void setFavs(int userId, List);
}

Looks pretty straightforward. Our choices are a list of top candidates, including Homer Simpson, Dilbert and Captain Kirk for possible presidents.

To make our poll we write a small Struts2 based application and use the CheckboxList to display the choices. We use the two getters from the an EJB implementation of this interface to obtain the possible choices and the made selections in case the guest is changing its vote.

The application works fine, we make our choice and save.

NoClassDefFoundException: com.opensymphony.xwork.util.XWorkList not found

How come? Well Struts2 does some conversion magic. It converts the returned selections from the page, which are HTML arrays, into this type, for whatever reason they think it is appropriate. But when we passing this List instance to the EJB that List implementation is most likely not on the classpath. Depending on your classloading setup when trying this, it might work, but when the EAR the EJB is in has no access to struts/xwork jars from the Web Application you will be getting this error.

To fix this there are some options on the client side. One might be to implement a proxy that converts the List:

setFavs(List favs){
  this.favs = new ArrayList();
  this.favs.addAll(favs);
}

And now the general learning from this exercise: Using interfaces in APIs is great, because it allows the usage of different implementations. But when the chosen implementation is not found on the receiver’s classpath bad things can happen. There are three options to resolve this:

  1. Make sure that all client classes are available on the service classpath
  2. Make a project convention that only JDK implementations are passed
  3. Don’t use Interfaces in Service APIs

Neither one is an easy pick, I must admit. Feel free to post better ideas into the comments.

(Option 3 doesnt work in Struts2 due the magic involved when converting request parameters)

Fabian Lange

 

Peter Roßbachs Tomcat 6 Talk at RheinJUG

Peter Roßbach, core developer at the Tomcat project, held a talk at RheinJUG in Düsseldorf on Thursday. It was very delightful mixture on Tomcat architecture, best practices, Open Source community as well as current and future developments, rather than a dry technical talk.

Tuning Tomcat Performance

Regarding performance, he mentioned that the main negative factor is to use development mode for production environments. Well have a look at a few parameters and which do affect Tomcat performance.

As of tomcat 6 there is the improved protocol handler available:

<Connector port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol"
 connectionTimeout="20000" />

additionally Java NIO powers a new improved file download option. Servlets just have to set sendfile request parameters and not output any more data. That file will then be pushed by tomcat to the user:

 org.apache.tomcat.sendfile.filename: Canonical filename of the file which will be sent as a String
 org.apache.tomcat.sendfile.start: Start offset as a Long
 org.apache.tomcat.sendfile.end: End offset as a Long

production servers should not deploy automatically:

<Host name="localhost" autoDeploy="false" deployOnStartup="false" deployXML="false">

The Jasper JSP compiler should be tuned as well:

<servlet>
  <servlet-name>jsp</servlet-name>
  <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
  <init-param>
<param-name>development</param-name>
<param-value>false</param-value>
  </init-param>
  <init-param>
<param-name>genStringAsCharArray</param-name>
<param-value>true</param-value>
  </init-param>
  <init-param>
<param-name>trimSpaces</param-name>
<param-value>true</param-value>
  </init-param>
</servlet>

Using mod_jk for loadbalancing

As a second main topic of his talk, he presented the module “mod_jk”, which in connection with a Apache Httpd and the Tomcat AJP protocol enables distributing java applications on multiple Tomcat servers.

He explained the different loadbalancing setups and that it might make even sense to user a Tomcat server per application, as this allows better memory management and improves overall high-availibility.

Tomcat Configuration:

<Connector port="8009" protocol="AJP/1.3"/>
<Engine name="Catalina" defaultHost="localhost" jvmRoute="node01">

mod_jk Configuration inside Httpd:

<IfModule !mod_jk.c>
  LoadModule jk_module "modules/mod_jk.so"
</IfModule>
JkShmFile "logs/mod_jk.shm"
 
JKWorkerProperty worker.list=loadbalancer
JKWorkerProperty worker.node01.port=8009
JKWorkerProperty worker.node01.host=localhost
JKWorkerProperty worker.node01.type=ajp13
JKWorkerProperty worker.loadbalancer.type=lb
JKWorkerProperty worker.loadbalancer.connection_pool_minsize=0
JKWorkerProperty worker.loadbalancer.connect_timeout=30000
JKWorkerProperty worker.loadbalancer.prepost_timeout=10000
JKWorkerProperty worker.loadbalancer.balance_workers=node01
JKWorkerProperty worker.loadbalancer.method=Request
JKWorkerProperty worker.loadbalancer.retries=2
JKWorkerProperty worker.loadbalancer.recovery_options=7
JKMount /myapps* loadbalancer

Further documentation on mod_jk worker can be found here:

http://tomcat.apache.org/connectors-doc/reference/workers.html

In total a very interesting talk, with lots of stuff to learn from, let it be the Tomcat project or the Tomcat architecture, or how Open Source “lives” and what one as developer or architect should consider when developing a Java web application.

Fabian Lange

 

Internet Explorer 8 will contain new AJAX functionality

A blog entry at MSDN reports that Internet Explorer 8 will contain an important new feature: it will be possible to control the navigation history by JavaScript.

Up to today, it was problematic for the user to navigate back and forth through an AJAX-based web application. After the page has been loaded completely, the state of the HTML document might be modified by AJAX-based interactions, for example dynamic loading of texts or data. If the user clicks the “Back” button in his browser, the browser will go back to the previously loaded page, losing the entire (potentially modified) state of the application.

The new implementation in Internet Explorer 8, which is adopted from HTML 5, is supposed to solve this problem. It will be possible to add AJAX-related changes of state to the navigation history, enabling the user to navigate back and forth through the application, based on a history that contains all dynamically changed states. This would solve a huge usability problem of AJAX-based web applications.

The new feature is presented here as a video.

Up to now, no estimate can be made about the adoption of the new functionality by other browser vendors. Time will show which decisions will be made by them.

Robert Spielmann

 

next page »