|
[
Permalink
| « Hide
]
Eric Dalquist added a comment - 18/May/06 10:56 AM
I authored the JSR-168 extension for the displaytag library. There is no JSR-168 spec compliant way to do the export since it is not content rendered inside of the portlet UI. To get export working with your portlet container you will likely need to extend the JSR-168 support to make it specific to your portal.
The export functionality is currently useless in the context of a portlet.
And the solution proposed is that anyone who needs that feature must do his own custom extension to the container? I think it would be better to have export work within a portlet. Let the individuals who are designing a portlet decide for themselves whether the feature or total JSR 168 compliance is more important to them. What I was trying to say is there is no way to implement exporting that will work in more than one portal container. I could get export working in uPortal, using custom extensions to the portlet specification that uPortal has implemented. This export functionality would be tied to uPortal and not work in another portal unless it provided the same extensions. Liferay likely has some extentions to the spec as well and export could be implmented to work in that portal but again, it would be specific to that portal.
I was not implying there is a portal agnostic way to do it but we shouldn't implement it because the spec doesn't support it. I'm implying there is no way to implement export of binary content from a portlet that will work on every portal container at this point in time. This is a shortcoming of the JSR-168 specification that will hopefully be addressed in version 2 of the spec which is in progress. That being said if you are interested uPortal's method of allowing binary content to be rendered may be doable in liferay as well. uPortal has a custom WindowState called Exclusive in which a portlet has complete control of the output stream and can set any content type for the result. If this sounds interesting I could probably give some direction in implementing export functionality to use this feature for the displaytag library. Actually after looking over the spec again there may be a spec compliant way to implement this. Unfortunatly I believe it will only work using the latest versions of Tomcat 5.5 as the servlet container.
The portlet spec provides the requirement that a portlet and a servlet that share a web application context should also share the HttpSession that backs the PortletSession. With Tomcat this was only supported in 5.5 by the way of an empty session path configuration option. The implementation would be to generate export links as URLs to the portlet export servlet. The portlet side export code would need to ensure the needed objects were accessible by the servlet via the Application scope of the PortletSession. The export Servlet would use the information on the URL and in the HttpSession to provide the view. This should work in any truely spec compliant environment. I unfortunatly don't have the cycles to implement this right now but I can provide insight and review if needed. Just wondering if there has been any additional work done in this area as it has been a few months since the last post. If not, I would like to take a shot at Eric's approach. Eric, could you possibly provide me a high level list of steps?
Here's the approach we use locally, ymmv. It's really pretty simple. (Pegboard is our portal server.)
1) We have the export filter running against all portal requests. 2) All portlet urls are rewritten to be render urls by a RequestHelper 3) If an export is run, our local table tag will remove the export flag from the render parameters after the export has been written public class MyTableTag extends TableTag { protected void writeExport(ExportView exportView) throws IOException, JspException { super.writeExport(exportView); HttpServletRequest httpRequest = (HttpServletRequest) pageContext.getRequest(); PegboardWindow pegboardWindow = (PegboardWindow)httpRequest.getAttribute(PegboardWindow.CURRENT_WINDOW); if ( pegboardWindow == null ){ return; } Map params = pegboardWindow.getRenderParameters(); ParamEncoder encoder = new ParamEncoder( getId() ); params.remove( encoder.encodeParameterName(TableTagParameters.PARAMETER_EXPORTTYPE) ); pegboardWindow.setRenderParameters( params ); } } Here is a high level overview of what I was thinking as far as an external servlet goes, with some background. If any of it needs clarification feel free to ask.
The servlet spec states that a portlet and a servlet in the same web-application share a session object. Data put into the session in the application scope by a portlet should be readily readable by a servlet in the same web-app being accessed by the same user. Data put into the session in the portlet scope by the portlet will be accessible but will likely have a name-spaced name, this makes portlet scoped session attributes hard to use. The down side of a user accessing this external servlet is you don't have any information about the user accessing the servlet like you do inside of the portlet. This is why the session sharing is important, the portlet will need to put some useful bit of data in the session so the servlet has some context for what is expected to do. With those two notes the approach I would take follows (at a very high level). The export URL rendered by displaytag points to this servlet that is mapped in the portlet's web application. Every time displaytag renders it uses some standard portlet session attribute (probably with some configurable key in the name so multiple tables can be on one page) to put a bit of requisite info for the servlet into the session. The URL to the export servlet includes this configurable key so the servlet knows which session attribute to get its requisite export info from. When the user clicks on the link the servlet looks in the session with the specified key for the info it needs to export the data. This will slightly pollute the session since there is no way for the portlet to know when the data can be removed from the session and the data must always be in the session since the portlet won't know when the user clicks on the export link. When I was doing the work to get display tag JSR-168 compliant I didn't look at the export code at all since that wasn't one of my needs. This high level overview may need some refining to work with the way displaytag does exports. If you need more information please feel free to ask. Andy,
That is an interesting suggestion. One issue is according to the portlet spec you don't know what format the URLs will end up being. It is perfectly valid to add twenty parameters to the URL and it to look like http://my.portal.com/portal/12712367AF23 where the end bit is just a key to some internal map the portal keeps. I'm not saying it isn't a valid solution but it will not likely work on all portals because of the URL format restrictions. Eric,
Well I ran into some problems with Vignette. It seems that when placing data into the session from a portlet (application scope) they actually use undocumented wrapper classes for the attributes stored making it impossible for me to pull this data out from a web-app servlet. This obviously is not adhering to the spec so I am going to open a ticket with Vignette. What I am doing in the meantime... - Created a web-app servlet that re-queries for the same data set as portlet. New servlet forwards to a new JSP that includes the same display:table tag as was used in the original portlet jsp (but wouldn't necessarily have to.) - In the html for the original portlet JSP, i include custom export links for the user that pass the necessary request parameters to cause the new servlet+jsp to respond directly with the pdf or excel version. - Set up the ResponseOverrideFilter for the new servlet. - Had to modify PortletRequestHelperFactory.java - Since when processing directly from the web-app, PortletRequestHelper is expecting to find the javax.portlet attributes, which are not present. So I had to put in a check in the Factory to fall back to the regular RequestHelper in this case. Can't set the Factory property from within the tag, so can't switch it based on the context I'm in. Things are working fine at present. I'll keep you posted... Kelly Kelly,
me too trying display tag export within JSR168 portlet with Vignette7.2. Can you please provide the solution? Many Thanks, Abhay Nilakhe Hi,
I need the export to work on WebSphere Portal with JSR-168 Struts portlets. The sorting and pagination works fine. Only the export doesn't work. There is the error about the filter : Exception: [.TableTag] Unable to reset response before returning exported data. You are not using an export filter. Be sure that no other jsp tags are used before display:table or refer to the displaytag documentation on how to configure the export filter (requires j2ee 1.3). Is there a solution to this ? Thanks, Narcis |
|||||||||||||||||||||||||||||||||||||||||||||