Jetty 9 WebSocket Server Max Message Size on Session - websocket

I ran into this issue and had some difficulty finding answers for this anywhere so I thought I would enter it here for future programmers.
In Jetty 9, if you try to set the maximum message size on a session object to handle large data packets, it will not work. You will still get disconnected if your client tries to send large data. I'm talking about setMaximimumMessageSize on this object: http://download.eclipse.org/jetty/stable-9/apidocs/org/eclipse/jetty/websocket/api/Session.html
Instead, what you have to do is set the max message size on the policy object acquired from the WebSocketServletFactory.
public final class MyWebSocketServlet extends WebSocketServlet
{
private static final long MAX_MESSAGE_SIZE = 1000000;
#Override
public void configure(WebSocketServletFactory factory)
{
factory.getPolicy().setMaxMessageSize(MAX_MESSAGE_SIZE);
factory.setCreator(new MyWebSocketCreator());
}
}
This will work as intended and your server will be able to handle large messages up to the maximum size you set.

The way you are setting the maximum message, in the WebSocketServlet is correct.
The Session.setMaximumMessageSize(long) as you pointed out in the javadoc is an unfortunately leaking of an early draft of JSR-356 (javax.websocket API) effort.
That method on the Jetty side API should not be there, and has been removed in Jetty 9.1
Bug has been filed: https://bugs.eclipse.org/bugs/show_bug.cgi?id=412439
Note: Jetty 9.1 will have the JSR-356 (javax.websocket API) support in it. Where the javax.websocket.Session has 2 methods of similar behavior.
javax.websocket.Session.setMaxBinaryMessageBufferSize(int)
javax.websocket.Session.setMaxTextMessageBufferSize(int)

I had this problem when sending files (binary data) with more than 64KB. I was using the javax.websocket-example from the Embedded Jetty WebSocket Examples.
Finally the only thing I need to do was to setMaxBinaryMessageBufferSize in the Session argument from the #OnOpen annotated method.
#ClientEndpoint
#ServerEndpoint(value = "/ws")
public class EventSocket {
#OnOpen
public void onWebSocketConnect(Session sess) {
sess.setMaxBinaryMessageBufferSize(1 * 1024 * 1024); // 1MB
}
#OnMessage
public void processUpload(byte[] b, boolean last, Session session) {
...
}
}

If anybody wants configurable alternative, setting servlet parameter maxTextMessageSize in web.xml also works -
<servlet>
<servlet-name>MyWebSocketServlet</servlet-name>
<servlet-class>test.MyWebSocketServlet</servlet-class>
<init-param>
<param-name>maxTextMessageSize</param-name>
<param-value>1048576</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>MyWebSocketServlet</servlet-name>
<url-pattern>/MyWebSocket/*</url-pattern>
</servlet-mapping>

Related

Spring Boot with CXF Client Race Condition/Connection Timeout

I have a CXF client configured in my Spring Boot app like so:
#Bean
public ConsumerSupportService consumerSupportService() {
JaxWsProxyFactoryBean jaxWsProxyFactoryBean = new JaxWsProxyFactoryBean();
jaxWsProxyFactoryBean.setServiceClass(ConsumerSupportService.class);
jaxWsProxyFactoryBean.setAddress("https://www.someservice.com/service?wsdl");
jaxWsProxyFactoryBean.setBindingId(SOAPBinding.SOAP12HTTP_BINDING);
WSAddressingFeature wsAddressingFeature = new WSAddressingFeature();
wsAddressingFeature.setAddressingRequired(true);
jaxWsProxyFactoryBean.getFeatures().add(wsAddressingFeature);
ConsumerSupportService service = (ConsumerSupportService) jaxWsProxyFactoryBean.create();
Client client = ClientProxy.getClient(service);
AddressingProperties addressingProperties = new AddressingProperties();
AttributedURIType to = new AttributedURIType();
to.setValue(applicationProperties.getWex().getServices().getConsumersupport().getTo());
addressingProperties.setTo(to);
AttributedURIType action = new AttributedURIType();
action.setValue("http://serviceaction/SearchConsumer");
addressingProperties.setAction(action);
client.getRequestContext().put("javax.xml.ws.addressing.context", addressingProperties);
setClientTimeout(client);
return service;
}
private void setClientTimeout(Client client) {
HTTPConduit conduit = (HTTPConduit) client.getConduit();
HTTPClientPolicy policy = new HTTPClientPolicy();
policy.setConnectionTimeout(applicationProperties.getWex().getServices().getClient().getConnectionTimeout());
policy.setReceiveTimeout(applicationProperties.getWex().getServices().getClient().getReceiveTimeout());
conduit.setClient(policy);
}
This same service bean is accessed by two different threads in the same application sequence. If I execute this particular sequence 10 times in a row, I will get a connection timeout from the service call at least 3 times. What I'm seeing is:
Caused by: java.io.IOException: Timed out waiting for response to operation {http://theservice.com}SearchConsumer.
at org.apache.cxf.endpoint.ClientImpl.waitResponse(ClientImpl.java:685) ~[cxf-core-3.2.0.jar:3.2.0]
at org.apache.cxf.endpoint.ClientImpl.processResult(ClientImpl.java:608) ~[cxf-core-3.2.0.jar:3.2.0]
If I change the sequence such that one of the threads does not call this service, then the error goes away. So, it seems like there's some sort of a race condition happening here. If I look at the logs in our proxy manager for this service, I can see that both of the service calls do return a response very quickly, but the second service call seems to get stuck somewhere in the code and never actually lets go of the connection until the timeout value is reached. I've been trying to track down the cause of this for quite a while, but have been unsuccessful.
I've read some mixed opinions as to whether or not CXF client proxies are thread-safe, but I was under the impression that they were. If this actually not the case, and I should be creating a new client proxy for each invocation, or use a pool of proxies?
Turns out that it is an issue with the proxy not being thread-safe. What I wound up doing was leveraging a solution kind of like one posted at the bottom of this post: Is this JAX-WS client call thread safe? - I created a pool for the proxies and I use that to access proxies from multiple threads in a thread-safe manner. This seems to work out pretty well.
public class JaxWSServiceProxyPool<T> extends GenericObjectPool<T> {
JaxWSServiceProxyPool(Supplier<T> factory, GenericObjectPoolConfig poolConfig) {
super(new BasePooledObjectFactory<T>() {
#Override
public T create() throws Exception {
return factory.get();
}
#Override
public PooledObject<T> wrap(T t) {
return new DefaultPooledObject<>(t);
}
}, poolConfig != null ? poolConfig : new GenericObjectPoolConfig());
}
}
I then created a simple "registry" class to keep references to various pools.
#Component
public class JaxWSServiceProxyPoolRegistry {
private static final Map<Class, JaxWSServiceProxyPool> registry = new HashMap<>();
public synchronized <T> void register(Class<T> serviceTypeClass, Supplier<T> factory, GenericObjectPoolConfig poolConfig) {
Assert.notNull(serviceTypeClass);
Assert.notNull(factory);
if (!registry.containsKey(serviceTypeClass)) {
registry.put(serviceTypeClass, new JaxWSServiceProxyPool<>(factory, poolConfig));
}
}
public <T> void register(Class<T> serviceTypeClass, Supplier<T> factory) {
register(serviceTypeClass, factory, null);
}
#SuppressWarnings("unchecked")
public <T> JaxWSServiceProxyPool<T> getServiceProxyPool(Class<T> serviceTypeClass) {
Assert.notNull(serviceTypeClass);
return registry.get(serviceTypeClass);
}
}
To use it, I did:
JaxWSServiceProxyPoolRegistry jaxWSServiceProxyPoolRegistry = new JaxWSServiceProxyPoolRegistry();
jaxWSServiceProxyPoolRegistry.register(ConsumerSupportService.class,
this::buildConsumerSupportServiceClient,
getConsumerSupportServicePoolConfig());
Where buildConsumerSupportServiceClient uses a JaxWsProxyFactoryBean to build up the client.
To retrieve an instance from the pool I inject my registry class and then do:
JaxWSServiceProxyPool<ConsumerSupportService> consumerSupportServiceJaxWSServiceProxyPool = jaxWSServiceProxyPoolRegistry.getServiceProxyPool(ConsumerSupportService.class);
And then borrow/return the object from/to the pool as necessary.
This seems to work well so far. I've executed some fairly heavy load tests against it and it's held up.

Jetty websocket class loading issue

I have implemented a basic websocket server in Jetty(Standalone mode).
MyWebSocketServlet.java
public class MyWebSocketServlet extends WebSocketServlet {
#Override
public void configure(WebSocketServletFactory webSocketServletFactory){
webSocketServletFactory.getPolicy().setIdleTimeout(1000 * 10 * 60);
webSocketServletFactory.setCreator(new MyWebSocketFactory());
}
}
MyWebSocketFactory.java
public class MyWebSocketFactory implements WebSocketCreator {
public Object createWebSocket(
ServletUpgradeRequest servletUpgradeRequest
, ServletUpgradeResponse servletUpgradeResponse) {
return new MyWebSocketListener();
}
}
MyWebSocketListener.java
public class MyWebSocketListener implements WebSocketListener {
private Session sessionInstance;
public void onWebSocketBinary(byte[] bytes, int i, int i1) {
ByteBuffer data = ByteBuffer.wrap(bytes, i, i1);
try {
sessionInstance.getRemote().sendBytes(data);
} catch (IOException e) {
e.printStackTrace();
}
}
public void onWebSocketClose(int i, String s) {
}
public void onWebSocketConnect(Session session) {
sessionInstance = session;
}
public void onWebSocketError(Throwable throwable) {
throwable.printStackTrace(System.err);
}
public void onWebSocketText(String s) {
try {
sessionInstance.getRemote().sendString(s);
} catch (IOException e) {
e.printStackTrace();
}
}
}
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
metadata-complete="false"
version="3.1">
<servlet>
<servlet-name>WsEcho</servlet-name>
<servlet-class>org.test.sanket.MyWebSocketServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>WsEcho</servlet-name>
<url-pattern>/echo/*</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>HttpEcho</servlet-name>
<servlet-class>org.test.sanket.MyHttpServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HttpEcho</servlet-name>
<url-pattern>/httpecho/*</url-pattern>
</servlet-mapping>
</web-app>
Instead of using a Standalone Jetty if I use embedded jetty and programatically configure the server and add the Servlets then this sample runs fine.
But if I am packaging the same as a war, and then deploying the same in a standalone jetty instance I am having the following observation:
I am able to hit the HttpServlet , i.e. MyHttpServlet and receive a response
But when I try to hit the websocket servlet, i.e. MyWebSocketServlet, I am seeing the following error:
exception
java.lang.ClassCastException: org.eclipse.jetty.server.HttpConnection cannot be cast to org.eclipse.jetty.server.HttpConnection
at org.eclipse.jetty.websocket.server.WebSocketServerFactory.acceptWebSocket(WebSocketServerFactory.java:175)
at org.eclipse.jetty.websocket.server.WebSocketServerFactory.acceptWebSocket(WebSocketServerFactory.java:148)
at org.eclipse.jetty.websocket.servlet.WebSocketServlet.service(WebSocketServlet.java:151)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:751)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:566)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:578)
at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:221)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1111)
I did come across the following link:
Jetty - stand alone WebSocket server
From the above link it seems to be a class loading issue, because jetty websocket package is treated as system class package and shouldn't be loaded by the WebApp if already loaded by the system.
So as referenced in the above link, I looked into the details suggested at:
http://www.eclipse.org/jetty/documentation/9.2.10.v20150310/jetty-classloading.html
From this link, one of the ways to get around this issue is to call the org.eclipse.jetty.webapp.WebAppContext.setSystemClasses(String Array) or org.eclipse.jetty.webapp.WebAppContext.addSystemClass(String) to allow fine control over which classes are considered System classes.
So for being able to do that, I should be able to get an Instance of WebAppContext, when Jetty is initializing and add the WebSocket classes as system classes.
I tried searching for how one would be able to achieve the same but no luck so far ? Can anybody kindly point me to a reference implementation as to how this can be achieved ?
Java Version: OpenJDK 7(latest)
Jetty: 9.2.10.v20150310
Operating System: Ubuntu 14.04
Thanks in advance!
If you have followed this link to setup the Jetty Standalone Instance, then you might have run the following command:
[/opt/web/mybase]# java -jar /opt/jetty/jetty-distribution-9.2.10.v20150310/start.jar --add-to-start=deploy,http,logging
If so, then when you try to hit the websocket servlet you will see the exception that you are noticing.
All you need to do is, instead of that command, you as well need to initialize the websocket module as shown below:
[/opt/web/mybase]# java -jar /opt/jetty/jetty-distribution-9.2.10.v20150310/start.jar --add-to-start=deploy,http,logging,websocket
Hope this helps!
Don't include the org.eclipse.jetty.* classes in your war's WEB-INF/lib or WEB-INF/classes directories.

Accessing ServletContext object in Action class in Struts 1.2

I have been given a use-case, to come up with a solution to allow configured number of users per user id to be logged in to my application at any given time.
For example : userid 'parentuser' can be used to log in to the application for a max of 10 times at any time.After this limit, the user will not allowed to log in as max number of users are accessing the application for that user.
Now, To implement this, I have created a context listener which will instantiate an attribute which I'll keep updating as the user logs in the application in the Action class.
My Context Listener is as under :
public class ApplicationContextListener implements ServletContextListener {
private Map<String, List<ApplicationContextBean>> userMap;
#Override
public void contextDestroyed(ServletContextEvent arg0) {
userMap = null;
}
#Override
public void contextInitialized(ServletContextEvent event) {
userMap = new HashMap<String, List<ApplicationContextBean>>();
}
public Map<String, List<ApplicationContextBean>> getUserMap() {
return userMap;
}
public void setUserMap(Map<String, List<ApplicationContextBean>> userMap) {
this.userMap = userMap;
}
}
web.xml is as under
<listener>
<listener-class>com.pcs.bpems.portal.listener.ApplicationContextListener</listener-class>
</listener>
Question : How can I now access this context object 'userMap' from my action class? If anyone has any other approach different than this also, kindly post the same.
Thanks
The answer is in the title of your question: store the Map (or an object wrapping the map and providing useful methods) into an attribute of the servlet context (accessible from the event), and retrieve it from wherever you want: the HttpServletRequest provides access to the servlet context.
A better solution, which would also work in case your application is clustered, would be to use the database.
Also, don't forget to decrement the counter when the session expires.
This can be stored in the Servlet Context as under :
#Override
public void contextInitialized(ServletContextEvent event) {
userMap = new HashMap<String, Map<String,List<ApplicationContextBean>>>();
event.getServletContext().setAttribute(ApplicationConstants.LOGGED_IN_USERS, userMap);
}
The stored parameters can be then fetched from the HttpSession Object as under :
currentSession.getServletContext().getAttribute(LOGGED_IN_USERS)

How to increase output buffer for spring sockjs websocket server implementation

I have used spring implementation of sockjs websocket server and unable to transmit message over 8KB, following is the error
2014-02-12 19:36:29,990 - org.springframework.web.socket.sockjs.transport.session.WebSocketServerSockJsSession - DEBUG - SockJS session id=35n41xel was closed, CloseStatus [code=1009, reason=The decoded text message was too big for the output buffer and the endpoint does not support partial messages]
Any Idea how can I increase the buffer size
I used following factory as spring sockjs leverages tomcat container (App is deployed in tomcat and I also debugged to confirm that it indeed uses tomcat lib)
#Bean
public WebSocketContainerFactoryBean createWebSocketContainer() {
WebSocketContainerFactoryBean container = new WebSocketContainerFactoryBean();
container.setMaxTextMessageBufferSize(16384);
container.setMaxBinaryMessageBufferSize(8192);
return container;
}
And then my URL mapping looks
#Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
registry.addHandler(coBrowseSockJsCustomerHandler(), "/sockjs/cobrowse/customer/").withSockJS();}
Do I need to set this bean with sockjs somewhere? how does sockjs knows that it has to use this facory?
Solved it by using clue from http://docs.spring.io/spring/docs/4.0.1.RELEASE/javadoc-api/index.html?org/springframework/web/socket/sockjs/SockJsService.html -got hold of ServletServerContainerFactoryBean and set the properties, this worked
#Bean
public ServletServerContainerFactoryBean createServletServerContainerFactoryBean() {
ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean();
container.setMaxTextMessageBufferSize(32768);
container.setMaxBinaryMessageBufferSize(32768);
logger.info("Websocket factory returned");
return container;
}
for client side:
#Bean
public static WebSocketStompClient getClient() {
List<Transport> transports = new ArrayList<>();
WebSocketContainer container = ContainerProvider.getWebSocketContainer();
container.setDefaultMaxBinaryMessageBufferSize(1024 * 1024);
container.setDefaultMaxTextMessageBufferSize(1024 * 1024);
transports.add(new WebSocketTransport(new StandardWebSocketClient(container)));
WebSocketClient webSocketClient = new SockJsClient(transports);
WebSocketStompClient stompClient = new WebSocketStompClient(webSocketClient);
stompClient.setInboundMessageSizeLimit(Integer.MAX_VALUE);
stompClient.setMessageConverter(new MappingJackson2MessageConverter());
return stompClient;
}
for server side:
#Bean
public ServletServerContainerFactoryBean createServletServerContainerFactoryBean() {
ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean();
container.setMaxTextMessageBufferSize(32768);
container.setMaxBinaryMessageBufferSize(32768);
logger.info("Websocket factory returned");
return container;
}
You can configure the websocket engine and increase the buffer size.
Watch out, depending on the actual size you'd like to use, remember that those messages will be buffered entirely in memory!
You may want to consider using partial messages if your client supports it.
Before you start the spring app you can set the property
System.setProperty("org.apache.tomcat.websocket.DEFAULT_BUFFER_SIZE", (1024*1024).toString()).
I've tried multiple bean configurations that didn't work but this property seems to be read in multiple places when I looked at the code. I'm sure there is some bean configuration that would have worked but if you don't want to bother trying many different ones until one works you can just set this parameter.
Setting this in my web.xml file worked for me:
<context-param>
<param-name>org.apache.tomcat.websocket.textBufferSize</param-name>
<param-value>65536</param-value>
</context-param>
<context-param>
<param-name>org.apache.tomcat.websocket.binaryBufferSize</param-name>
<param-value>65536</param-value>
</context-param>

GWT RequestFactory STRANGE behavior : No error reporting

I do have a problem, and I can't figure out what it happens...
GWT beginner, working on a personal project.
Environment:
maven project with two modules
one module is the 'model', and has Hibernate, HSQLDB and Spring dependencies. HSQLDB runs embedded, in memory, configured from spring applicationContext.xml
the other module is the 'web' and has all GWT dependencies
The application is built using some Spring Roo generated code as basis, later modified and extended.
The issue is that, when editing some entity fields and pressing save, nothing happens. No problem when creating a new entity instance, only on edit changing some field and pressing 'save' basically overrides the new values.
So I started to thoroughly debug the client code, enabled hibernate and Spring detailed logging, but still ... nothing.
Then I made a surprising (for me) discovery.
Inspecting the GWT response payload, I have seen this:
{"S":[false],"O": [{"T":"663_uruC_g7F5h5IXBGvTP3BBKM=","V":"MS4w","S":"IjMi","O":"UPDATE"}],"I":[{"F":true,"M":"Server Error: org.hibernate.PersistentObjectException: detached entity passed to persist: com.myvdm.server.domain.Document; nested exception is javax.persistence.PersistenceException: org.hibernate.PersistentObjectException: detached entity passed to persist: com.myvdm.server.domain.Document"}]}
Aha, detached entity passed to persist !!!
Please note that the gwt client code uses this snippet to call the service:
requestContext.persist().using(proxy);
Arguably this could trigger the exception, and calling merge() could solve the problem, however, read on, to question 3...
Three question arise now:
Why isn't this somehow sent to the client as an error/exception?
Why isn't this logged by Hibernate?
How come the Spring Roo generated code (as I said, used as basis) works without manifesting this problem?
Thanks a lot,
Avaiting for some opinions/suggestions.
EDITED AFTER T. BROYER's RESPONSE::
Hi Thomas, thanks for the response.
I have a custom class that implements RequestTransport and implements send(). This is how I collected the response payload. Implementation follows::
public void send(String payload, final TransportReceiver receiver) {
TransportReceiver myReceiver = new TransportReceiver() {
#Override
public void onTransportSuccess(String payload) {
try {
receiver.onTransportSuccess(payload);
} finally {
eventBus.fireEvent(new RequestEvent(RequestEvent.State.RECEIVED));
}
}
#Override
public void onTransportFailure(ServerFailure failure) {
try {
receiver.onTransportFailure(failure);
} finally {
eventBus.fireEvent(new RequestEvent(RequestEvent.State.RECEIVED));
}
}
};
try {
wrapped.send(payload, myReceiver);
} finally {
eventBus.fireEvent(new RequestEvent(RequestEvent.State.SENT));
}
}
Here's the code that is executed when 'save' button is clicked in edit mode:
RequestContext requestContext = editorDriver.flush();
if (editorDriver.hasErrors()) {
return;
}
requestContext.fire(new Receiver<Void>() {
#Override
public void onFailure(ServerFailure error) {
if (editorDriver != null) {
setWaiting(false);
super.onFailure(error);
}
}
#Override
public void onSuccess(Void ignore) {
if (editorDriver != null) {
editorDriver = null;
exit(true);
}
}
#Override
public void onConstraintViolation(Set<ConstraintViolation<?>> errors) {
if (editorDriver != null) {
setWaiting(false);
editorDriver.setConstraintViolations(errors);
}
}
});
Based on what you said, onSuccess() should be called, and it's called
So how do I isolate exactly the code that creates the problem? I have this method that creates a fresh request context in order to persist the object
#Override
protected RequestContext createSaveRequestContextFor(DocumentProxy proxy) {
DocumentRequestContext request = requests.documentRequestContext();
request.persist().using(proxy);
return request;
}
and this is how it is called::
editorDriver.edit(getProxy(), createSaveRequestContextFor(getProxy()));
As for the Spring problem, you are saying that, between two subsequent requests, the find() and persist(), the JPA entityManager should not be closed. I am still investigating this, but after I press the edit button, I see the message 'org.springframework.orm.jpa.EntityManagerFactoryUtils - Closing JPA EntityManager' and that is not right, maybe the #Transactional annotation is not applied...
Why isn't this somehow sent to the client as an error/exception?
It is. The "S": [false] indicates the first (and only) method invocation (remember, a RequestContext is a batch!) has failed. The onFailure method of the invocation's Receiver will be called.
The "F": true of the ServerFailure then says it's a fatal error, so the default implementation of Receiver#onFailure would throw a RuntimeException. However, as you do not use a Receiver at all, nothing happens and the error is silently ignored.
Note that the batch request in itself has succeeded, so the global Receiver (the one you'd pass to RequestContext#fire) would have its onSuccess method called.
Also note that Request#fire(Receiver) is a shorthand for Request#to(Receiver) followed by RequestContext#fire() (with no argument).
Why isn't this logged by Hibernate?
This I don't know, sorry.
How come the Spring Roo generated code (as I said, used as basis) works without manifesting this problem?
OK, let's explore the underlying reason of the exception: the entity is loaded by your Locator (or the entity class's findXxx static method) and then the persist method is called on the instance. If you do not use the same JPA EntityManager / Hibernate session in the find and persist methods, then you'll have the issue.
Request Factory expects you to use the open session in view pattern to overcome this. I unfortunately do not know what kind of code Spring Roo generates.
Regarding the open session in view pattern Thomas mentioned, just add this filter definitions to your web.xml to turn on the pattern in your Spring application:
<filter>
<filter-name>
Spring OpenEntityManagerInViewFilter
</filter-name>
<filter-class>
org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>Spring OpenEntityManagerInViewFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

Resources