Portlet web.xml requirements?

So I’m taking the dive into v7 portlets… I’m building a test using 7.0.2, in case it matters…

I’ve got a simple portlet w/ a simple UI to show a message and two buttons. portlet.xml (2.0) file is properly set up to use the VaadinPortlet class and UI is defined, but web.xml is empty.

The problem is that after the portlet renders itself (just fine, btw), I get an exception of the form:

java.io.FileNotFoundException: The requested resource (/vaadin-test-portlet/vaadin-test/invoke) is not available followed by a big nasty stack trace from catalina, liferay, etc., but nothing from Vaadin.

Okay, so it looks like the Vaadin side is trying to talk to a servlet, which I didn’t have. So in my web.xml file I added a servlet definition, pretty much duplicating what I have in portlet.xml except I use the servlet variety.

Deploy this guy, portlet renders, but then I get a new stack trace of the form:

java.lang.IllegalStateException: Cannot obtain OutputStream because Writer is already in use. Relevant Vaadin stack elements are:
VaadinServletResponse.getOutputStream(VaadinServletResponse.java:31)
BootstrapHandler.writeBootstrapPage(BootstrapHandler.java:220)
BootstrapHandler.handleRequest(BootstrapHandler.java:154)
AbstractCommunicationManager.handleOtherRequest(AbstractCommunicationManager.java:2344)
VaadinServlet.service(VaadinServlet:330)
VaadinServlet.service(VaadinServlet:201)

So on one hand, it looks like my portlet requires a servlet to function. But on the other hand, the servlet has issues.

So the question is, what do I need to put into the web.xml that will lead to a happy servlet/portlet combination?

And seriously? Going through the code for the new V7 control panel for Liferay, it doesn’t jive w/ what is in the Book of Vaadin. One or both are wrong, but I don’t know which…

And anyway, why all of a sudden do we need servlets to support portlets anyway? V6 never needed a servlet for portlets…

Further details…

The portlet seems to work. Interface elements respond to clicks, etc.

However, repeatedly in the logs (over and over again) I get the same IllegalStateException because the BootstrapHandler is trying to write the bootstrap page (BootstrapHandler.java line 220 from 7.0.0).

So it looks like the servlet is necessary for a happy portlet, but the servlet is erroneously trying to inject the bootstrap every time…

The errors you are seeing are probably related to
#10707
(whitespace in portlet name on Liferay).

I haven’t tried this now, but a servlet should not be necessary with Portlet 2.0 for basic features as long as all resources (themes, …) are served statically either from the portal-wide directory or using Liferay’s own mechanisms for sharing them from the portlet (might be a bit more tricky to set up).

Note also that some portals do require the existence of a web.xml, although they do not need to have a servlet configured.

I don’t think so, I never use spaces in the portlet name. Display name, sure, but never the portlet name…

I’m trying some v7 portlets this week, trying to hammer out the issues, and will report on any issues. I’ll also add jira tickets for those things that are truly bugs…

Actually, Henri, the whitespace has nothing to do with the issue. The issue is how Liferay expects a servlet to be the entry point for a portlet in 6.1.1 CE GA2 (at least, not sure what version the OP opened the bug on).

When the session is extended in the browser, Liferay’s session.js invokes the /html/portal/extend_session.jsp page which in turn tries to call the /portlet name/invoke path on all portlets; this will have each servlet extend it’s own servlet session along w/ the portal servlet’s session.

Since pure Vaadin portlets will not have a servlet entry in web.xml, the exception is thrown and a small message added to the log about not being able to extend the portlet’s session.

I opened a bug for Liferay (http://issues.liferay.com/browse/LPS-33794) as I think that the best solution is for extend_session.jsp to check the portlet’s class and not try to invoke the servlet if the portlet is Vaadin-based, but this may actually result in session timeouts for the servlet containing the Vaadin portlet so I’m not sure it is absolutely the best solution…

Hi David,

I’m curious as to whether you’ve made any further progress on this issue? We’re trying to migrate V6 portlets to V7 as well and it seems that we’re getting this same exception. What has been your experience thus far migrating portlets to V7? Any advice / information would be appreciated.

Best,

Mark

It’s a Liferay issue…

When you click on the “Extend” button in the browser, this in turn ends up invoking /html/portal/extend_session.jsp on the server. This jsp page in turn tries to call /portlet-name/invoke as a regular servlet call. Normal LiferayMVC portlets actually will have a corresponding servlet added to web.xml during deployment, an instance of com.liferay.portal.kernel.servlet.PortletServlet.

The service() method in this class has java code to check if the incoming request is to have the session extended, and will do so when invoked via extend_session.jsp.

The problem is that a pure Vaadin portlet does not have a servlet added to the web.xml file.

The stack trace you see is merely a report that there is no such servlet in the war file and the session cannot get extended. Since the servlet does not exist, the risk is that the session attached to the war file may expire prematurely even though the user wanted to extend it.

As a temporary solution, you can add a servlet to each war file that mimics the Liferay stuff.

The class I created and use is the following:

[code]
public class LiferaySessionServlet extends HttpServlet {
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
if (request.getAttribute(WebKeys.EXTEND_SESSION) != null) {
request.removeAttribute(WebKeys.EXTEND_SESSION);

  HttpSession session = request.getSession(false);

  if (session != null) {
    session.setAttribute(WebKeys.EXTEND_SESSION, Boolean.TRUE);
    session.removeAttribute(WebKeys.EXTEND_SESSION);
  }
  return;
}
super.service(request,response);

}
}
[/code]In your web.xml, you then need to add the following:

<servlet> <servlet-name>my-portlet-name</servlet-name> <servlet-class>LiferaySessionServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>my-portlet-name</servlet-name> <url-pattern>/my-portlet-name/*</url-pattern> </servlet-mapping> Repeat for each portlet that you have defined in the portlet.xml file. Where I have “my-portlet-name”, use the value that you have in the tag in portlet.xml.

This will remove the exception from the log and will also extend the session for the servlet, thus protecting the session for the war containing the portlet(s).

Hi Dave,

in case you are still struggling with this I have found a way to get it working. Henri was actually right in that sense that it is portlet name causing the problem however in your case it is not whitespace but it is dash (-) characters. For some reason portlet names having dashes or whitespace (probably there are more of these characters) causes session extend problems in Liferay. So you can easily get rid of the problem by using only letters and numbers in portlet name (I am not sure what other characters work). You can try to update your portlet name to vaadinTestPortlet in portlet.xml and liferay-portlet.xml and that should work just fine. Also no need to have any servlet definitions in web.xml. This might be better solution than to define custom servlet for each of the portlets.

Regards,
Marius

Dashes, spaces, etc. have nothing to do with it…

It is a Liferay bug. Liferay inserts a servlet into web.xml at deployment time w/ a different name than what is defined in portlet.xml. The Liferay servlet that gets inserted into web.xml uses no spaces/dashes in the name.

Taking all of the dashes and spaces out of your portlet name is a hack to make your portlet name align with the servlet Liferay inserts into web.xml.

Trust me, this is a problem Liferay has with portlets across the board, including any JSR-286 standard portlet (where dashes/spaces are allowed in the portlet name).

Well actually dashes and spaces has everything to do with it as having them in your portlet name causes the exceptions. I don’t say that it is supposed to be working like that and I am not denying that it is Liferay bug. But I think it is better workaround than to define custom servlet for every of your portlets. If you feel like doing it, it is your choice to do this until new Liferay release (if you are using CE and if it is going to fixed in next release).

Regards,
Marius

Replacing the extend_session.jsp in our 6.1.1 CE GA2 Liferay with the revised one referenced in this Liferay bug report ==> http://issues.liferay.com/browse/LPS-33794 resolved this problem for us. The reference to the revised jsp is in the comment near the bottom with this header: Torsten Werner added a comment - 30/Apr/13 4:58 AM[b]

[/b]