Download

Get Loom

Concurrency

If you only plan to write Actions and business classes, you can safely skip this section. If, on the contrary, you plan to write Decorators, Validators or locale-aware Converters, keep reading.

As a general rule of thumb, any class mentioned here will be thread-safe if it does not have any property that depends on the current user request: locale, parameter values, action properties, etc. If the class contains only configuration attributes that do not depend on anything request-dependant (specially the Locale) everything will be fine.

Classes that MUST be thread-safe

Converters

Converter instances are kept as singleton instances inside the ConverterFactory class. This is not a problem for the majority of classes, but some Converters need access to the current Locale (think Dates and currencies, for example) and the Format class cannot be cached as a property.

Validators and Interceptors

Validator and Interceptor instances are kept as ActionMapping atributes, which means they must be unique per action and event. They may hold attributes relative to the validated property, action and event but nothing else (again, nothing relative to request parameters or locale).

This is not a problem for Validators because they are not bound to the user locale, but may become a problem for Interceptors.

Decorators

Decorator instances are singletons which means that they cannot cache anything that depends on the current request:

public class MyDecorator extends AbstractLoomDecoratorImpl {

	// BAD IDEA!!
	private boolean cleanup = false;

	public boolean beforeDoTag(T tag, WriterWrapper wrapper) throws IOException, JspException {
		cleanup = tag.getRequest().getParam("something") != null;
		if (cleanup){
			// ...
		}
	}

	public void afterDoTag(T tag, WriterWrapper wrapper) throws IOException, JspException {
		if (cleanup) {
			// ...
		}
	}

}

Consider adding attributes to the request with addAttribute() instead:

	public boolean beforeDoTag(T tag, WriterWrapper wrapper) throws IOException, JspException {
		Boolean cleanup = tag.getRequest().getParam("something") != null;
		if (cleanup){
			// ...
		}
		tag.getRequest().addAttribute("cleanup", cleanup);
	}

	public void afterDoTag(T tag, WriterWrapper wrapper) throws IOException, JspException {
		boolean cleanup = tag.getRequest().getAttribute("cleanup");
		if (cleanup) {
			// ...
		}
	}

MessagesRepository

There is a different MessagesRepository instance for each Locale, but the same MessagesRepository instance may be used by two concurrent requests with the same Locale. Since MessagesRepository instances are mostly read-only, this should seldom raise any issue.

Classes that are NOT required to be thread-safe

Action and ActionContext classes, LoomServletRequest and ServletRequestParams, and all JSP tags get instantiated once per use so they do not have any special considerations.