I wonder why
serveResource
method was left out while
providing annotated methods in JSR 286.
It is a frequent requirement now-a-days to implement
multiple AJAX calls while developing JSR 286 based portlets.
There are many different design patterns through which this can be achieved, but still thought of giving a try to annotate
There are many different design patterns through which this can be achieved, but still thought of giving a try to annotate
serveResource
method.
What I did was creating a base portlet class which will be
extended by the other portlet classes, but this is not required and can be
directly done in the requisite portlet class.
Firstly, created an annotation interface
ResourceMapping
, this defines the
annotation of @ResourceMapping
with name
as a variable.
Then in
BasePortlet
class added a private method to cache
the annotated resource methods during the portlet initialization.
Then in the overridden
serveResource
method checked value of
parameter javax.portlet.serveResource
which should denote the name
of the
annotated methods name parameter.package in.blogspot.wpwizard.portlets; import java.io.IOException; import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; import javax.portlet.GenericPortlet; import javax.portlet.PortletException; import javax.portlet.RenderRequest; import javax.portlet.RenderResponse; import javax.portlet.ResourceRequest; import javax.portlet.ResourceResponse; public abstract class BasePortlet extends GenericPortlet { private transient Map<String, Method> serveResourceHandlingMethodsMap = new HashMap<String, Method>(); @Override public void init() throws PortletException { super.init(); try { cacheAnnotatedResourceMethods(); //cache annotated resource serving methods on init } catch (Exception e) { e.printStackTrace(); } } @Override public void destroy() { super.destroy(); } /** * In order to annotate the serveResource use <code>@ResourceMapping</code> * and provide the variable name of parameter <code>javax.portlet.resource</code> in <code>resourceURL</code> * */ public void serveResource(ResourceRequest request, ResourceResponse response) throws PortletException, IOException { try { String resource = request.getParameter("javax.portlet.serveResource"); Method resourceMethod = serveResourceHandlingMethodsMap.get(resource); if (resourceMethod != null) { resourceMethod.invoke(this, request, response); return; } } catch (Exception e) { throw new PortletException(e); } } @Override protected void doView(RenderRequest request, RenderResponse response) throws PortletException, IOException { } private void cacheAnnotatedResourceMethods() { // cache all annotated resource serving methods for (Method method : this.getClass().getMethods()) { Annotation[] annotations = method.getAnnotations(); if (annotations != null) { for (Annotation annotation : annotations) { Class<? extends Annotation> annotationType = annotation.annotationType(); if (ResourceMapping.class.equals(annotationType)) { String name = ((ResourceMapping) annotation).name(); if (name != null && name.length() > 0) serveResourceHandlingMethodsMap.put(name, method); } } } } } }
In the individual portlet class of
MyPortlet
added the
annotated methods for serving resource.package in.blogspot.wpwizard.portlets; import java.io.IOException; import java.io.PrintWriter; import javax.portlet.PortletException; import javax.portlet.PortletRequestDispatcher; import javax.portlet.RenderRequest; import javax.portlet.RenderResponse; import javax.portlet.ResourceRequest; import javax.portlet.ResourceResponse; public class MyPortlet extends BasePortlet { public void init() throws PortletException{ super.init(); } public void doView(RenderRequest request, RenderResponse response) throws PortletException, IOException { response.setContentType(request.getResponseContentType()); PortletRequestDispatcher rd = getPortletContext().getRequestDispatcher("/jsp/view.jsp"); rd.include(request,response); } @ResourceMapping(name="getCountry") public void getCountry(ResourceRequest request, ResourceResponse response)throws PortletException, IOException{ System.out.println("entered getCountry"); PrintWriter out = response.getWriter(); out.print("return country list"); } @ResourceMapping(name="getState") public void getState(ResourceRequest request, ResourceResponse response)throws PortletException, IOException{ System.out.println("entered getState"); PrintWriter out = response.getWriter(); out.print("return state list"); } }
In the JSP added the following tags to form an URL to these annotated method. The value passed in the param with name
javax.portlet.serveResource
should match the annotation name variable of the method. (As we do in the
processAction annotation)<portlet:resourceURL var="getCountryURL"> <portlet:param name="javax.portlet.serveResource" value="getCountry" /> </portlet:resourceURL> <portlet:resourceURL var="getStateURL"> <portlet:param name="javax.portlet.serveResource" value="getState" /> </portlet:resourceURL>
Voila it works !!
Super SIR..............
ReplyDelete