Application Specific Module
TutorialAkos Balasko
02/07/2012
1
OutlineTechnical Session:
Sample web-interface (JSP)Implement event-handler classDeploy it to Liferay-based gUSE Adjusting as a new component in gUSE
2
OverviewSample application:
3
Input file(inputval.txt)
Output(internal file name: outputval.txt)
Shell-script:Read and count numbers from input file and command line
Command-line
OverviewButton to create
new Query
List of created queriesEach row is identified by the
application id
StatusDate of creation
Action Buttons
4
Information Transfer: ServerClient
CLIENT CODE
<select id=„devs" name=„devs"><c:forEach var=„dev„ items="${developers}"> <option>
${dev} </option></c:forEach></select>
SERVER CODE
public void doView(RenderRequest req, RenderResponse res) throws PortletException {ArrayList<String> developers = new ArrayList<String>();
developers.add(„10168");
developers.add(„10169");
req.setAttribute(„developers",developers);
PortletRequestDispatcher dispatcher;
dispatcher = getPortletContext().getRequestDispatcher(nextJSP);
dispatcher.include(req, res);
}
CLIENT BROWSER
(developers=[„10168” ; „10169”] )
5
Information Transfer : ClientServerCLIENT CODE
<portlet:actionURL var="pURL" portletMode="VIEW" />
<form id="confform" method="post" action="${pURL}">
<input type="hidden" name="action" id="action„ value="doHandleEvent"> <select id=„devs" name=„devs"> <c:forEach var=„dev" items="${developers}"> <option>
${dev} </option> </c:forEach> </select> <input type="submit" value="List Workflows from repository„ class="portlet-form-button"></form>
SERVER CODEpublic void processAction(ActionRequest request, ActionResponse response) throws PortletException { String action = "";if ((request.getParameter("action") != null) && (!request.getParameter("action").equals(""))) { action = request.getParameter("action"); } if (action != null) {Method method = this.getClass().getMethod(action, new Class[]{ActionRequest.class, ActionResponse.class}); method.invoke(this, new Object[]{request, response});}
CLIENT BROWSER
(action=„doHandleEvent; devs=„10168”)
Call doHandleEvent6
Information transfer : ActionHandler Rendering
ACTION HANDLER
public void doHandleEvent(ActionRequest request, ActionResponse response) throws PortletException { String selected_dev = request.getParameter(„devs"); //(selected_dev = 10168) response.setRenderParameter(„goahead", selected_dev);}
Call doHandleEvent
RENDER (DOVIEW)
public void doView(RenderRequest req, RenderResponse res) throws PortletException {
if (req.getParameter(„goahead") != null) { String devid = req.getParameter(„goahead"); }
(goahead=„10168”)
7
Create JSP file <%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %><%@ taglib uri="http://java.sun.com/portlet_2_0" prefix="portlet" %> <portlet:resourceURL var="resURL" /><portlet:renderURL var="rURL" /><portlet:actionURL var="uploadURL" /><portlet:resourceURL var="ajaxURL" /><script><portlet:defineObjects/> <portlet:actionURL var="pURL" portletMode="VIEW" />
8
How to make JSR-286 compliant portlet from a class?
1. Extend it from GenericPortlet class2. Create processAction method3. Create doView method4. Create eventhandler methods with
ActionRequest and ActionResponse parameters
9
1. Extend it from GenericPortlet class
Open MyFirstASMInterface.java for editing and extend it from GenericPortlet class:
public class MyFirstASMInterface extends GenericPortlet {}
10
2. Create ProcessAction method
public void processAction(ActionRequest request, ActionResponse response) throws PortletException { String action = "";// Checking if the call contains multipart content boolean isMultipart = PortletFileUpload.isMultipartContent(request); if (!isMultipart) {
// if not, it's a simple calling, let's get the name of the function from „action” parameter and check the reference of it if ((request.getParameter("action") != null) && (!request.getParameter("action").equals(""))) { action = request.getParameter("action"); } if (action != null) { try {// it's not null, invoke this function from the event-handler class and handle the possible exceptions Method method = this.getClass().getMethod(action, new Class[]{ActionRequest.class, ActionResponse.class}); method.invoke(this, new Object[]{request, response}); } catch (NoSuchMethodException e) { System.out.println("-----------------------No such method"); } catch (IllegalAccessException e) { System.out.println("----------------------Illegal access"); } catch (InvocationTargetException e) { System.out.println("-------------------Invocation target Exception"); e.printStackTrace(); } } } else {
// it contains multipart content, call the upload function and handle the next steps there doUpload(request, response); } }
11
3.Create doView methodpublic void doView(RenderRequest req, RenderResponse res) throws PortletException { try { String nextJSP = (String) req.getParameter("nextJSP"); if (nextJSP == null){ nextJSP = DISPLAY_PAGE; }// generating the JSP page PortletRequestDispatcher dispatcher; dispatcher = getPortletContext().getRequestDispatcher(nextJSP); dispatcher.include(req, res); } catch (IOException ex) { Logger.getLogger(ASM_SamplePortlet.class.getName()).log(Level.SEVERE, null,ex); }
12
First step to connect to gUSE
private String DISPLAY_PAGE = "/jsp/asm_sample/asmsample.jsp";
ASMService asm_service = null;
public MyFirstASMInterface() { asm_service = ASMService.getInstance(); }
13
Create new application
<table width="100%"> <tr> <td align="center"> <form id="importform" method="post" action="${pURL}" > <input type="hidden" name="action" id="action" value="doCreateNewWorkflow"> <input type="submit" value="Crete new Counter Query" class="portlet-form-
button"> </form> </td> </tr></table>
public void doCreateNewWorkflow(ActionRequest request, ActionResponse response) throws PortletException { try { String userId = request.getRemoteUser(); // getting workflows for All workflow developers Vector<String> developers = asm_service.getWorkflowDevelopers(RepositoryItemTypeConstants.Application); Vector<ASMRepositoryItemBean> workflows = new Vector<ASMRepositoryItemBean>(); for (String dev: developers){ workflows.addAll(asm_service.getWorkflowsFromRepository(dev, RepositoryItemTypeConstants.Application)); }…..
Create new application
….// Getting the current workflow exported by the workflow developer…. ….latestWorkflow =w.getId().toString();….
Calendar cal = Calendar.getInstance(); SimpleDateFormat udf = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss"); String workflowName = WorkflowPrefix + "_"+ udf.format(cal.getTime()); asm_service.ImportWorkflow(userId,workflowName, workflowDeveloper,
RepositoryItemTypeConstants.Application, latestWorkflow);
} catch (Exception ex) { ex.printStackTrace(); }
}
Create a table for the workflows to be listed
<c:if test="${fn:length(asm_instances) gt 0}"><table width="100%" border="1"> <tr> <td align="center"> <strong><i>Query Creation Date And Time</i></strong> </td> <td align="center"> <strong><i>Status</i></strong> </td> <td colspan="4" align="center"> <strong><i>Actions</i></strong> </td> </tr>
Iterate through the workflows,get name and status
<c:forEach var="workflows" items="${asm_instances}"> <tr> <td align="center"> <c:set var="datetime" value=" ${fn:split(workflows.workflowName,'_')[1]}"/> ${fn:split(datetime,"-")[0]}/${fn:split(datetime,"-")[1]}/${fn:split(datetime,"-")[2]} at ${fn:split(datetime,"-")[3]}:${fn:split(datetime,"-")[4]}:${fn:split(datetime,"-")[5]} </td>
<td bgcolor="${workflows.statusbean.color}"> ${workflows.statusbean.status} </td>
…..</tr>
</c:forEach> </table>
</c:if><hr/>
Iterate through the workflows,get name and status
public void doView(RenderRequest req, RenderResponse res) throws PortletException { try { String userID = req.getRemoteUser(); try {
req.setAttribute("asm_instances", asm_service.getASMWorkflows(userID));
} catch (Exception e) { e.printStackTrace(); // not found notify file }…..
Show imported applications 1/2doView method : …// passing arguments back, list of workflow that are already imported using getASMWorkflows(String userID) method req.setAttribute("asm_instances",
asm_service.getASMWorkflows(userID));
It returns : List< > , where ASMWorkflow is
19
20
Set inputs and Submit
<td align="center"> <input type="button" value="Start" onclick="jQuery.facebox({ div: '#div_settings_${workflows.workflowName}' });"> </td>…<c:forEach var="inst" items="${asm_instances}"> <div style="display:none" id="div_settings_${inst.workflowName}"> <form method="post" action="${pURL}" > <table> <tr><td>Type the first number:</td><td> <input type="text" id="input_numb" name="input_numb" value=""/></td> </tr> <tr><td>Type the second number:</td><td> <input type="text" id="command_line" name="command_line" value=""/></td> </tr> </table> <input type="hidden" id="user_selected_instance" name="user_selected_instance" value="${inst.workflowName}"/> <br> <input type="hidden" name="action" id="action" value="doSubmit"> <br> <input type="submit" value="Set Parameters" class="portlet-form-button"> </form> </div></c:forEach>
Set inputs and Submitpublic void doSubmit(ActionRequest request, ActionResponse response) throws PortletException { try { String userID = (String) request.getRemoteUser(); String selected_wf = request.getParameter("user_selected_instance");
String input_numb = request.getParameter("input_numb"); String actual_command_line = request.getParameter("command_line"); asm_service.setCommandLineArg(userID, selected_wf, "add", actual_command_line); try{ asm_service.setInputText(userID, input_numb ,selected_wf, "add", "0"); }catch(Exception ex){ Logger.getLogger(ASM_SimplePortlet.class.getName()).log(Level.SEVERE, null, ex); } asm_service.submit(userID, selected_wf); } catch (ClassNotFoundException ex) { Logger.getLogger(ASM_SimplePortlet.class.getName()).log(Level.SEVERE, null, ex); } catch (InstantiationException ex) { Logger.getLogger(ASM_SimplePortlet.class.getName()).log(Level.SEVERE, null, ex); } catch (IllegalAccessException ex) { Logger.getLogger(ASM_SimplePortlet.class.getName()).log(Level.SEVERE, null, ex); } }
Download method
<td align="center"> <form method="post" action="${resURL}"> <input type="hidden" id="download_${workflows.workflowName}" name="download_${workflows.workflowName}"/> <input type="submit" value="Download" class="portlet-form-button"> </form></td>
@Override public void serveResource(ResourceRequest request, ResourceResponse response) throws PortletException, IOException { String userID = request.getRemoteUser(); Enumeration paramNames = request.getParameterNames(); String selected_wf = ""; while(paramNames.hasMoreElements()){ String act_param = (String)paramNames.nextElement();
if (act_param.startsWith("download_")){ selected_wf = act_param.substring(9); } }
Download method
try { response.setContentType("application/zip"); response.setProperty("Content-Disposition", "inline;
filename=\"" + selected_wf + "_enduser_outputs.zip\""); asm_service.getFileStream(userID, selected_wf, "add",
"outputval.txt", response);
} catch (Exception e) { e.printStackTrace();
} }
Delete method
<td align="center"> <div id="div_delete"> <form method="post" action="${pURL}" > <input type="hidden" id="user_selected_instance"
name="user_selected_instance" value="${workflows.workflowName}"/> <input type="hidden" name="action" id="action" value="doDelete"> <input type="submit" value="Delete " class="portlet-form-button"> </form> </div> </td>
public void doDelete(ActionRequest request, ActionResponse response) throws PortletException { String userID = (String) request.getRemoteUser(); String selected_wf = request.getParameter("user_selected_instance"); asm_service.DeleteWorkflow(userID, selected_wf); }
Deploy it to Liferay-based gUSE And set it as a new component in gUSE
26
Deploy it to Liferay-based gUSESign in as a user with admin roles (default username is :
[email protected], password is : test )
27
Deploy it to Liferay-based gUSENavigate to Plugin Installer panel by clicking Manage -> Control
Panel, and by selecting Plugins Installation from the menu in the left hand-side, finally clicking install More Portlets button and upload File link.
28
Adjusting it as a new component (just once)
As admin, please go to Settings menu and select Internal Services
29
Adjusting it as a new component (just once)
Click to New button and set the followings:Type of Component: portalService group: gUSEURL of Component: http://localhost:8080/MyFirstASMInterfaceURL to initialize Component: http://localhost:8080/MyFirstASMInterface/initPublic URL of Component: http://localhost:8080/MyFirstASMInterfaceState: active
Then click to Save button!
30
Adjusting it as a new component (just once)
Click to copy component Properties tabSet http://localhost:8080/wspgrade as Source component and
http://localhost:8080/MyFirstASMInterface as Destination one, then click to copy
31
Adjusting it as a new componentFinally initialize the whole portal again by
calling http://localhost:8080/information/init.jsp
(in some cases portal restart required.)
32
Creating new menuitem for it (just once)
33
Adding the portlet under this menu (just once)
Click to „Add” and select „more”The newly developed portlet should be available under undefined group.
Finally click to „add” in the row of the portlet
34
Thank you for your attention!Questions?
35