Application Specific
Module 3.4.3
Manual and Developer Tutorial
by Ákos Balaskó
11/01/2012
2
Contents
Introduction
________________________________
_______________________________
3
User groups and scenario
________________________________
_____________________
5
User
groups
________________________________
________________________________
____
5
Scenario
________________________________
________________________________
______
5
Structures
________________________________
________________________________
_
6
Diagrams
________________________________
________________________________
______
8
Set NetBeans project
for ASM
-
based portlet
________________________________
_____
13
The first ASM
-
based project
________________________________
______________________
13
Introduction into portlet programming
________________________________
_________
19
Developing ASM
-
based Portlets
________________________________
_______________
21
Designing Interface that fits for end
-
users’ needs
________________________________
_____
22
Deploying and Adjusting ASM
-
based portlet into gUSE components
__________________
33
Deploying the compiled web
-
archive
________________________________
_______________
33
Adjusting ASM
-
based portlet
________________________________
_____________________
34
Appendix
________________________________
________________________________
_
37
Sample web.xml file
________________________________
____________________________
37
Componen
t descriptors
________________________________
_________________________
40
Portal.wsdd
________________________________
________________________________
__________
40
Remote.wsdd
________________________________
________________________________
_________
40
Storage.wsdd
________________________________
________________________________
_________
40
Submitter.wsdd
________________________________
________________________________
_______
41
Tool.wsdd
________________________________
________________________________
____________
41
wfi.wsdd
________________________________
________________________________
_____________
41
3
Introduction
Developers and scientist
s
would like to serve their user community by creating a
scientific gateway to let the users to execute scientific applications in a distributed
system. Although gUSE provides a general portal solution extended by a powerful
workflow interp
reter and
managem
ent system, there is a great claim to customize,
modify or extend general portals to create a portal that can be useful and easy
-
to
-
use for
potential user groups and communities.
g
USE is implemented as a set of Web services that bind together in flexible
ways on
demand to deliver user services in Grid and/or Web services environments. User
interfaces for gUSE services are provided by the WS
-
PGRADE Web application. WS
-
PGRADE is a Web portal hosted in a standard portal framework. WS
-
PGRADE uses the
client AP
Is of gUSE services to turn user requests into sequences of gUSE specific Web
service calls. WS
-
PGRADE hides the communication protocols and sequences behind
JSR168 compliant portlets. End users can access WS
-
PGRADE via Web browsers. A
graph editor compone
nt can be downloaded from WS
-
PGRADE via the browser to the
user machine. The editor can be used to define the static skeleton of workflows, while
the HTML pages of WS
-
PGRADE provide interfaces to add content to graphs, to generate
complete Grid/Web service
applications.
gUSE services can be hosted on a single host or can be distributed over several server
machines to optimize resource usage or increase performance. gUSE services provide
data services (user database, proxy credential database, application code database,
wo
rkflow database, application history and change log database, etc.) and control
services (e.g. job submission, workflow enactment, etc.). gUSE services discover each
other using a central gUSE service, the information system.
The main idea of
customizati
on is to develop own portlets that fit to the users needs,
and connect them to gUSE system using an API provided the official system. Therefore
the portlets can be partitioned in this kind of aspect, one aggregation contains the
general portlets (they're c
alled WS
-
PGRADE), and other contains the portlets developed
Figure
1
:
Services
in
the gUSE architecture
4
by communities (or developers serving communities' needs) using an API. The API,
called
Applicatio
n Specific Module (ASM
)
, provides the most of the functionalities of
gUSE programmatically, some o
thers cannot be provided because they don't fit to the
supported user scenario described in
the next section
.
5
S
cenario
description
One of the most common
claims
from the user communities is to hide as much as it can
be from the complexity of the underlaying system and infrastructure; member of the
communities would like to focus on their own scientific area. They don't have any
experience in developing distribut
ed applications (or graphs) and adapt it to a DCI,
would like just to use the common applications with own adjustments, execution
settings or own input files and get results as fast as possible.
The user scenario followed by the idea of ASM is based on th
is.
User groups
In case of usage, three different user
roles can be identified.
1.
Firs, the greatest set is the
End Users
, it covers scientists of the community, who
would like to use distributed infrastructures without any learning. All complexity
of the inner solutions, the infrastructure,
and the
used middleware must be
hidden from them.
2.
The second
smaller group of users
is called
Workflow Developers
, who have
interest and/or qualification to adapt scientific applications to DCI and manage
them on it.
3.
The last
smallest group is the set of
User Interface Developers
, who have web
-
programmer skills, and able to develop user
-
friendly web
-
application customized
for a specified scientific application created by Workflow Developers.
End users will execute and manage scientific applications adapted to DCI via these
customized User Interfaces.
This document aims
User Interface De
velopers
to impor
t and manage workflows
without
knowledge about the inner logic of gUSE, introducing an API called ASM.
Scenario
First, the
Workflow Developers
adapt
the specified sc
ientific application onto gUSE
s
ystem by creating a workflo
w structure in
the original way.
When it's created and
tested correctly,
Workflow Developers
must export it to the local
Repository
provided
originally by gUSE. (To check how to do this, please see online or offline
gUSE help.)
Then
User Interface Developers
develop
an
easy
-
to
-
use interface according to the
needs of the End Users. To be able to get access to gUSE
-
related components such as the
Repository, where the scientific application (represented by a workflow in gUSE) is
stored (and shared), or the Workflow Interpre
ter, which can execute the
Workflow
and
send the sub
-
components of it to a specified DCI, and so on, the most sophisticated way
is to use the ASM.
Finally
, end u
sers can „use” the developed scientific application with their own
adjustments and get the results.
Technically it means that
End Users
imports the
scientific application from the
Repository
to their user
-
space, and adjust/execute this
instead of the origi
nal one.
6
Structures
All
the
functionalities
, which are
detailed
in
Use Case D
iagram
in Figure 2
,
can be
accessed via methods of
ASMService
s
ingleton
class
.
Figure
2
: Use Case Diagram
ASMService
class diagram
shows the public (and private) methods provided by
ASMService
. Many of them can be easily associated to expected use case by the following
table.
7
Funct
ionality
Method
Return Type
Description
getDeveloperList
getWorkflowDevelopers
String[]
G
et a
string
list of applivation Developer IDs
that have exported at least one application
to the local repository
according to the
necessary requirements (see
ApplicationType object)
ListImported
getASMWorkflows
List<ASMWorkflow>
Returns a list of ASMWorkflow
objects that
represent the available applications for the
user
Import
ImportWorkflow
Void
Imports an application from the local
shared repository to the user space
DownloadOutput
getFiletoPortalServer
Void
Downloads the needed file to the portal
server
DownloadOutput
getFileStream
Stream
Returns the file in a stream
Upload
uploadFiletoPortalServer
Void
Uploads a file to the portal server
PlaceInWorkflow
placeUploadedFile
Void
Place a file that has been already uploaded
to portal server
, in a workflow
as an input
file
Get Remote Input
getRemoteInputPath
String
Returns the actual remote input path
associaged to a specified job/port
Set Remote Input
setRemoteInputPath
Void
Sets the remote input path according to
the string added as parameter
Get Remote
Output
getRemoteOutputPath
String
Returns the actual remote input path
associaged to a specified job/port
Set Remote
Output
setRemoteOutputPath
Void
Sets the remote input path according to
the string added as parameter
Get Command
line
argument
getCommandLineArg
String
Returns the actual command line argument
that is set for a specified job
Set Command
line argument
setCommandLineArg
Void
Sets the command line argument for a
specified job
Get resource
getResource
ASMResourceBean
Returns the actual resource where the job
will be submitted to.
Set resource
setResource
Void
Sets a resourc
e
Get Nodenumber
getNodeNumber
String
Returns the value of the required number
of processes if the given job is an MPI job,
otherwise it throws
NotMPIJobException
Set nodeNumber
setNodenumber
Void
Sets the number of the required nodes to
the given value
Submit
submit
Void
Submits an imported application
(overloaded function: it can be used to set
notification in different status changes)
getStatus
getWorkflows
-
> Overall
status statistics in
JobStatistics bean
List<ASMWorkflow>
Gets general status statistics about the
workflow that is being executed
getStatus
getDetails
WorkflowInstanceBean
R
eturns detailed status codes about every
job
that is being submitted according to the
application (it returns)
Rescue
rescue
ASMService
Rescues an application
Abort
abort
ASMService
Aborts an application
8
Table 1:
Use Case func
tionalities
and methods
Diagrams
Thereinafter,
all classes of a
pplica
tion s
pecific
module are shown with all inter
class
dependencies that can help for better understanding of the connection of each
component.
Figure
3
:
ASMService
Class Diagram
Figure
4
:
ASM Service
Class Diagram
9
Figure
5
: ASMWorkflow Dependency Diagram
Figure
6
:
ASMWorkflow
Class
Figure
7
:
WorkflowInstanceStatusBean
Class
10
Figure
8
:
JobStatisticsBean
Class
Figure
9
: Detailed Statusbeans Dependency Diagram
Figure
10
:
WorkflowInstanceBean
Class
11
Figure
11
:
RunningJobDetailsBean
Class
Figure
12
:
ASMJobInstanceBean
Class
Figure
13
:
JobStatisticsBean
Class
12
Figure
14
:
OverviewJobStatusBean
Class
13
Figure
15
:
ASMResourceBean
Class
Set
an A
SM
based p
ortlet
in
NetBeans
6.5.1
To make
the new customized interface (
a portlet
or a set of portlets) to communicate
with gUSE components, it must meet several conditi
ons.
There must contain
:
1.
Libraries for
w
eb
s
ervice
based communication (Axis, listed in
the
Appendix
at
the end of this
guide
)
.
2.
Client libraries of
w
eb
w
ervice
based gUSE components
.
3.
C
ommon Apache libraries to use portlet technology
.
4.
W
eb.xml
file
must contain default initialization and SOAP servlets
(fron
tendbase.jar contains it), init parameterization (place
of the component
-
descriptor WSDD
files) (sample web.xml is shown in Appendix)
.
The first ASM
based project
Once you initialize your NetBeans tool
with the necessary requirements above
, follow
the ste
ps as the screenshots show below.
14
Figure
16
: New project window
Figure
17
:
Name the project
15
Figure
18
: Select
a
web
server
Click Finish
at the end of the New Web Application process, and then follow the next
steps:
1.
Create new folder called „lib” in WEB
-
INF and
c
opy
WSDD
files into it.
2.
Open Configuration Files folder and edit web.xml file by clicking on it and then
selecting XML in
the upp
er menu. Copy the example web.xml content into this
file.
3.
Add the following external java libraries to your project by right
-
clicking the
name of your project and selecting Pr
operties
and Libraries then.
Note: In case of setting source of gUSE in Net
B
eans, we suggest to organize external
libraries in folders according to the name of the folder where they are placed
under_libs folder.
This or
ganization is shown in Figure 19
.
a.
Application Specific Module:
asm_api.jar
b.
gUSE/WS
-
PGRADE communication libraries
:
frontendbase.jar;
information_cli.jar;logging_cli.jar; portal_cli.jar; repository_cli.jar;
storage_cli.jar; wfi_cli.jar; wfs_cli.jar
c.
AXIS:
axis
-
ant.jar; axis.jar
d.
Common Library
: commons fileupload
-
1.2.1.jar; commons
-
discovery
-
0.2.jar; commons
-
logging
-
1
.0.4.jar; jaxrc.jar; log4j
-
1.2.8.jar; saaj.jar;
wsdl4
-
1.5.1.jar; commons
-
cli.1.2.jar; commons
-
codec
-
1.3.jar;
commons
-
io
-
1.4.jar; commons
-
logging
-
1.1.1.jar; apache
-
mime4j
-
0.6.jar; httpclient
-
4.0.1.jar; httpcore
-
4.0.jar; httpcore
-
nio
-
4.0.jar;
httpmime
-
5.0.1.
jar;cos.jar; standard.jar; jstl.jar
e.
Liferay
-
depended Library:
portlet.jar
(just for compiling, please check
the
Package
checkbox out in properties/libraries panel!)
JSR Standard
libraries:
portlet
-
api
-
2.0.jar; portlettaglib.jar
(just for compiling, please
c
heck the „Package” checkbox out in pro
perties/libraries panel!)
16
f.
JAX
-
WS 2.1 libraries: If web
services plugin is installed in
to
Net
B
eans, JAX
-
WS library must be available within
Global Libraries
folder
.
Figure
19
:
The
list of
necessary libraries
4.
Create new file under Web Pages/WEB
-
INF namely
portlet.xml
and copy
there
the sample
XML
file
.
Note that
you must type exactly the same package hierarchy
in portlet
class tag whereas you created your portlet
.
5.
Create new folder under Web Pages namely
JSP
. This folder will contain the JSP
webpage sourcecodes.
6.
Create new
J
ava class in
Source Packages
folder
a.
Class Name
:
asmsample
b.
Project:
MyFirstASMInterface
c.
Package:
hu.sztaki.lpds.asmsample
17
Figure
20
: Create
a
new class for event handling
7.
Once you
clic
k
the
Finish
button, you see the following:
Figure
21
:
A c
lass created
8.
To provide proxy certificates for job submission
via DCI
-
Bridge
, a new
web
service
needs to
be created
for each ASM
-
based web application. First, click to
the web
app’s name in the
Projects
panel by
clicking the
right mouse button, then
click
New
, finally
select
a
web service.
18
9.
Fill
the text fields with the following
values
(see Figure 22
):
Web Service Name
:
CredentialProvider
Package:
hu.sztaki.lpds.pgportal.services.credential
Figure
22
: New web
service to provide proxy credentials
10.
Finally
,
create a new web
method
in the
CredentialProvider
class:
19
Figure
23
: Create
a
new class for
event handling
Introduction into
p
ortlet
p
rogramming
The two portlet programming consists of two main processes
1.
A
rgument and parameter passing
,
2.
M
ethod execution
or function calls.
As both processes
are depending to each other, we show them in one example. As it's
shown in the next figure, in the first step we create a textbox by writing the code of it.
(
Please note that to be able to communicate the JSP code with the server, all
par
ameteres that should be sent within a request must be covered by a form tag!
)
In this sample we have a simple textbox named textBoxA, and with a value „30%”
as
well as
one hidden parameter that contains the name of the event
-
handler method in
the server s
ide (
name=”action”, value=”getValueOfTextBox”
). According to JSR
-
268 standard, the parameters in the form will be sent to the pre
-
set actionURL of the
server.
20
Figure
24
: Portlet programming process
In the server side, within the portlet class there is a default method called
„processAction” to handle the main events such as make decision of the executions
according to the calling type (simple or multipart) and call real event
-
handler methods.
In this
method we can get the value
of the hidden parameter called
action
by
request.getParameter(„action”)
method. Then we can call this method by
method.invoke function and pass all request and response object as parameters.
Then the exact event handler method
will be executed. Inside of it we can get the
value of the textbox, set the next JSP page, and send information to the rendering phase.
In the last step a default method called doView will be executed in any cases to
render the JSP page, get/set informatio
n necessarry to the visualization, and to render
the page.Within this method we can get parameters that are set in the event handler
function and make decisions according to them, and we can set parameter to be sent to
the JSP page. Please note that in thi
s case the name of the parameter available in the
client side (the name and the id of the „input” tag in the JSP page) must be the same as
the first argument in the setAttribute function.
21
Develop
ASM based p
ortlet
s
In
this secti
on we’re focusing on development
of a portlet that fits to the user’s
needs
and the appli
cation’s requirements
,
threfore we retrieve a well
-
tested and
well
-
functioning
application. To show the main features of ASM, we will create a sample
portlet
for the application show in Figure
2
5
.
22
Figure
25
: Sample application
As the application’s structure is static in our portlet’s development phase, all the
structure information (e.q. which port is associated to input file and w
hich is the output)
can be used or hard
-
coded in the portlet’s source.
Note: In the following
section
the source
code will be shown in a box, the newly
inserted and discussed lines are
bold
. Every method should be owned by the class
created in the first step. The ASM
-
specific methods are
red
and
bold
.
Design user friendly i
nterface
Figure
26
: Sample interface
A clear and step
-
by
-
step sample interface is to be
introduced to show methods provided
by ASM.
F
igure
2
6shows them on a high level
.
Figure
27
: List of shared applications according to application developer ID
23
Figure
28
: List of current imported appl
ication
Figure
29
: Interface to upload input file
Figure
30
: Interface to download output file
Initialization:
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ 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:resource
URL var="ajaxURL" />
<script>
<portlet:defineObjects/>
<portlet:actionURL var="pURL" portletMode="VIEW" />
Interface for se
lecting workflow developers’ id:
Figure
31
: List of application developer IDs
<div id="div_getworkflows
rep">
<form id="confform" method="post" action="${pURL}" >
<input type="hidden" name="action" id="action"
value="doGetWorkflowsFromRepository">
<table>
<tr>
<td>Get workflows from :</td>
<td>
<select id="owner" name="owner"
>
<c:forEach var="
own
" items="${
owners
}">
<option>
24
${
own
}
</option>
</c:forEach>
</select>
</td>
<td><input type="submit" value="List Workflows from repository"
class="por
tlet
-
form
-
button">
</td>
</tr>
</table>
</form>
</div>
<hr/>
Create an i
nterface to import workflow
from a list responsed by the server according to
the selected workflow developer
.
<div id="div_import">
<form method="post" action="${pURL}" >
<input type="hidden" name="action" id="action" value="doImportWorkflow">
<input type="hidden" name="rep_owner" id="rep_owner" value="${rep_owner}">
Selected
Owner is
: ${
rep_owner
}
<table width="100%">
<tr>
<td>
<strong><i>Select
</i></strong>
</td>
<td>
<strong><i>Workflow Name</i></strong>
</td>
<td>
<strong><i>Workflow Type</i></strong>
</td>
</tr>
<c:forEach var="
wf
" items="${
WorkflowList
}">
<tr>
<td>
<
input type="radio" name="impItemId" value="${
wf.id
}" />
</td>
<td>
${
wf.itemID
}
</td>
<td>
${
wf.exportType
}
</td>
</tr>
</c:forEach>
<tr>
<td>
<
input type="submit" value="Import selected workflow" class="portlet
-
form
-
button">
</td>
</tr>
</table>
</form>
</div>
List the available imported applications
:
<table width="100%">
<tr>
25
<td>
<strong><i>Workflow Name</i></strong>
</td>
<td>
<strong><i>Workflow Status</i></strong>
</td>
<td colspan="4">
<strong><i>Actions</i></strong>
</td>
</tr>
<c:forEach var="
workflows
" items="${
asm_instances
}">
<tr>
<td>
${
workflows.workflowName
}
</td>
<td bgcolor="${
workflows.statusbean.color
}">
${
workflows.statusbean.status
}
</td>
Create a table cell for a button to get inputs (and a form to send as a request):
<td><
div id="div_getinput">
<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="doGetInput">
<input type="submit" value="Get input text!" class="portlet
-
form
-
button">
</form>
</div>
</td>
Create a table cell for a button to submit (and a form to send as a request):
<td>
<div id="div_submit">
<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="doSubmit">
<input type="submit" value="Submit" class="portlet
-
form
-
button">
</form>
</div>
</td>
Create a table cell for a textfield and for a button to sh
ow and set command line
parameters (and a form to send as a request):
<td>
<form method="post" action="${pURL}" >
<c:choose>
<c:when test="${
act_workflowID
eq
workflows.workflowName
}">
<input type="text" id="cmd_line" name="cmd_line"
value="${
command_line_text
}"/>
</c:when>
<c:otherwise>
<input type="text" id="cmd_line" name="cmd_line"
value=""/>
</c:otherwise>
</c:choose>
<input type="hidden" id="user_selected_instance"
name="user_selected_instance" value="${
workflows.workflowName
}"/>
<
input type="hidden" name="action" id="action" value="doSetInput">
26
<input type="submit" value="Set Input" class="portlet
-
form
-
button">
</form>
</td>
Create a table cell for a button to handle file upload (it contains only a
simple javascript
funct
ion
-
calling to show a div that covers the form and the necessary inputs)
:
<td>
<input type="button" value="Upload" class="portlet
-
form
-
button"
onClick="javascript:document.getElementById('instance_upload_${workflows
.work
flowName}').value='${
workflows.workflowName
}';
document.getElementById('div_upload_${
workflows.workflowName
}').style.display
='block';
"/>
</td>
Create a table cell for a button to handle file download (it contains only a simple
javascript function
-
calling to show a div that covers the form and the necessary inputs):
<td>
<input type="button" value="Download" class="portlet
-
form
-
button"
onClick="javascript:document.getElementById('instance_download_${
workflows.wo
rkflowName
}').value='${
workflows.workflowName
}';
document.getElementById('div_download_${
workflows.workflowName
}').style.displ
ay='block';
"/>
</td
>
Create a table cell for a textfield and for a button to delete instance (and a form to send
as a request):
<td><div id="div_delete">
<form method="post" action="${pURL}" >
<input type="hidden" id="user_selected_insta
nce"
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>
Close the table
and
close
the
for
cycle:
</tr>
</c:forEach>
</table>
<hr/>
Define as many divs as many instances we have to create pop
-
up windows for handling
file
-
upload method:
<c:forEach var="
inst
"
items="${
asm_instances
}">
<div class="draggable" id="div_upload_${
inst.workflowName
}">
<form method="post" action="${pURL}" enctype="multipart/form
-
data">
<input type="hidden" name="action" id="action" value="doUpload">
<
input type="hidden" id="instance_upload_${
inst.workflowName
}"
name="instance_upload_${
inst.workflowName
}"/>
<table>
<tr>
<td>
Select job and port:
</td>
27
<td>
<select id="where2upload" name="
where2
upload
">
<c:forEach var="jobs" items="${
inst.jobs
}">
<c:forEach var="ports"
items="${
jobs.value.input_ports
}">
<option
value="$
{
jobs.key
}@${
ports.key
}@${
ports.value
}">
${jobs.key} job's ${
ports.key
}'s port
(
${
ports.value
}
)
</option>
</c:forEach>
</c:forEach>
</select>
</td>
</tr>
<tr>
<td>
<input type="file" name="input_2788_file" id="input_2788_file"/>
<input type="submit" value="Upload!" />
<
input type="button" value="Cancel" class="portlet
-
form
-
button"
onClick="javascript:
document.getElementById('div_upload_${
inst.workflowName
}').style.display='non
e';"/>
</td>
</tr>
</table>
</form>
</div>
</c:forEach>
Create a new
J
ava clas
s for the portlet
event
-
handler
:
public class ASM_SamplePortlet extends GenericPortlet {
}
Create a variable that stores the default page,
and
ASMService
o
bject to communicate
with ASM:
public class ASM_SamplePortlet extends GenericPortlet {
private String DISPLAY_PAGE = "/jsp/asm_sample/asmsample.jsp";
ASMService asm_service = null;
}
Create a
constructor method for the
portlet
class, and get an instance from our
ASMService Singleton
:
public class ASM_SamplePortlet extends GenericPortlet {
//
...
public ASM_SamplePortlet() {
asm_service = ASMService.getInstance();
}
}
Create a function (called
processAction
) that is responsible for executing the
event
handler
method clicked by the user, and/or managing the execution of different types of
calling such as normal clien
t
-
server calls
or multipart uploading process.
28
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 fr
om „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);
}
}
Create
doUpload
me
thod to handle uploading process.
public void doUpload(ActionRequest request, ActionResponse response) throws
PortletException {
try {
// getting the file and the parameters passed in ActionRequest object using
standard java solutions
String jobport = "";
String selected_wf= "";
ActionRequest temp_req =request;
DiskFileItemFactory factory = new DiskFileItemFactory();
PortletFileUpload pfu = new PortletFileUpload(factory);
29
List fileItems = pfu.parseRequest(temp_req);
Iterator iter = fileItems.iterator();
FileItem file2upload = null;
// iterating through the items (they can be fileItem or formField)
while (iter.hasNext())
{
FileItem item = (FileItem)iter.next();
System.out.println("Items in the request (first iteration): " +
item.getFieldName());
// retrieve hidden parameters if item is a form field
if
(item.isFormField())
{
// getting form fields
if (item.getFieldName().equals(new String ("where2upload"))){
jobport = item.getString();
}
if (item.getFieldN
ame().startsWith(new String
("instance_upload"))){
selected_wf = item.getString();
}
}
else {
// getting fileItem
file2upload = item;
}
}
// format of the passed as a value of where2upload parameter is the following (just
in this sample, it's not required!): <nameOfTheJob>@<numberOfThePort>, therefore
this string should be splitted
String[] splitted = jobport.split(
"@");
String selected_job = splitted[0];
String selected_port = splitted[1];
//getting ID of the user
String userId = request.getRemoteUser();
// ASM API Calling : upload the file to the portal server (where the interf
ace is
deployed, as gUSE is a distributed system, the UI and the exact place of the
workflows and the input files can be different)
File uploadedFile =
asm_service.uploadFiletoPortalServer(file2upload,userId,file2upload.getName());
// To upload
the input file to the exact place (under the specified
port/job/workflow), the following method should be called:
asm_service.placeUploadedFile(request.getRemoteUser(), uploadedFile, selected_wf,
selected_job, selected_port);
// finally
catch and handle possible exceptions
30
} catch (Exception ex) {
ex.printStackTrace();
Logger.getLogger(ASM_SamplePortlet.class.getName()).log(Level.SEVERE,
null, ex);
}
}
Crea
t
e
a
default renderin
g method that will
be executed
every
e
vent
to send information
and
b
eans
back to the JSP interface.
According to the standard solution of JSR
-
268, the information cannot be passed back
to the interface but some types can be sent from the
event
handling
phase to the
rend
er
ing
phase.
public void doView(RenderRequest req, RenderResponse res) throws
PortletException {
try {
// getting the ID of the user
String userID = req.getRemoteUser();
try {
// setting the value of the attribute called „own
ers” with the result of the second
parameter, the ASM API Calling which returns a list of string of the users, who
have already exported an application to the repository (the parameter of this
method specifies the type of the exported entity, it can be sel
ected from
RepositoryItemTypeConstants class )
req.setAttribute("
owners
",
asm_service.getWorkflowDevelopers(RepositoryItemTypeConstants.Application)
);
// getting the „owner”
parameter arrived from the user, and if it's not null, then
it
will get the workflow list exported by this user and will pass it back as
„WorkflowList” attribute
if (req.getParameter("owner") != null) {
req.setAttribute("
WorkflowList
",
asm_service.getWorkflowsFromRepository(
owner
,
RepositoryItemTypeCo
nstants.Application)
);
// passing the value of „owner” parameter back as an attribute called ”rep_owner”
.
req.setAttribute("
rep_owner
", req.getParameter("owner"));
}
// passing arguments back, list of workflow that are
already imported using
getASMWorkflows(String userID) method
req.setAttribute("
asm_instances
",
asm_service.getASMWorkflows(userID)
);
req.setAttribute("portalID", asm_service.PORTAL);
req.setAttribute("userID", userID);
req.setAttribute("storageurl", asm_service.STORAGE);
// if parameter called „command_line” is not null, it will pass the value of it to
the JSP
if (req.getParameter("comma
nd_line") != null) {
req.setAttribute("
command_line_text
",
req.getParameter("command_line"));
}
31
// if
parameter storing the name of the actual workflow called „act_workflowID” is
not null, it will pass the value of it t
o the JSP
if (req.getParameter("act_workflowID") != null) {
req.setAttribute("
act_workflowID
",
req.getParameter("act_workflowID"));
}
} catch (Exception e) {
e.printStackTrace();
}
// Setting next page
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.g
etName()).log(Level.SEVERE,
null, ex);
}
}
Create an
event handler
method to get the list of the exported workflows exported by a
specifie
d user. This user is stored in
owner
parameter and set by the user. As this list can
be get
ting
by one ASM
API calling, here we just set
render
p
arameter
called
„owner”
,
and then
this parameter will be checked in the
doView
method
(
if it's not null, the list of
the workflows will be get there
)
.
public void doGetWorkflowsFromRepository(ActionRequest request, Ac
tionResponse
response) throws PortletException {
//Getting the owner set by the user
String owner = request.getParameter("owner").toString();
//Setting a parameter called „owner” for the rendering phase to get the list there
response.setRen
derParameter("owner", owner);
}
E
vent handler
to import workflows:
public void doImportWorkflow(ActionRequest request, ActionResponse response) throws
PortletException {
try {
// type of workflow to be imported must be set,
RepositoryItemTypeConstants class
contains the possible types
String impWfType = RepositoryItemTypeConstants.Application;
// get the id of the workflow to be imported
String impItemId = request.getParameter("impItemId");
// get the
id of the user, who has exported the item
32
String owner = request.getParameter("rep_owner").toString();
// generating a new unique id
Calendar cal = Calendar.getInstance();
SimpleDateFormat udf = new SimpleDateFormat("yyy
yMMddHHmmssSSS");
String projectName = impItemId + "_"+ udf.format(cal.getTime());
// ASM
-
related function, import a workflow
asm_service.ImportWorkflow(request.getRemoteUser(),projectName, owner,
impWfType, impItemId);
// catching
and handling exceptions
} catch (Exception ex) {
Logger.getLogger(ASM_SamplePortlet.class.getName()).log(Level.SEVERE,
null, ex);
}
}
E
vent handler
to go back
:
public void doGoBack(ActionRequest request,ActionResponse
response) throws
PortletException{
// it just sets the „nextJSP” paramter to the default page. This variable will be
checked and handled in doView method
response.setRenderParameter("nextJSP", DISPLAY_PAGE);
}
E
vent handler
to
d
elete a workflow
:
publi
c void doDelete(ActionRequest request, ActionResponse response) throws
PortletException {
// getting the userID, and the value of „user_selected_instance”
String userID = (String) request.getRemoteUser();
String selected_wf = request.getPar
ameter("user_selected_instance");
//ASM function to delete workflow
asm_service.DeleteWorkflow(userID, selected_wf);
}
E
vent handler
to get value of
command l
ine argument
:
public void doGetInput(ActionRequest request, ActionResponse response) throws
PortletException {
String userID = (String) request.getRemoteUser();
String selected_wf = request.getParameter("user_selected_instance");
String selected_job = "add_1";
String actual_command_line = asm_service.getCommandLineArg(userID,
selected_wf, selected_job);
response.setRenderParameter("command_line", actual_command_line);
response.setRenderParameter("act
_workflowID", selected_wf);
}
E
vent handler
to
s
ubmit a workflow
:
public void doSubmit(ActionRequest request, ActionResponse response) throws
PortletException {
try {
33
//getting ID of the user, and the ID of the selected workflow
String userID = (String) request.getRemoteUser();
String selected_wf = request.getParameter("user_selected_instance");
// ASM method to submit
asm_service.submit(userID, selected_wf);
// exception handling
} catc
h (ClassNotFoundException ex) {
Logger.getLogger(ASM_SamplePortlet.class.getName()).log(Level.SEVERE,
null, ex);
} catch (InstantiationException ex) {
Logger.getLogger(ASM_SamplePortlet.class.getName()).log(Level.SEVERE,
nul
l, ex);
} catch (IllegalAccessException ex) {
Logger.getLogger(ASM_SamplePortlet.class.getName()).log(Level.SEVERE,
null, ex);
}
}
E
vent handler
to
set
c
ommand line
parameter
:
public void doSetInput(ActionRequest
request, ActionResponse response) throws
PortletException {
//getting ID of the user, and the ID of the selected workflow
String userID = (String) request.getRemoteUser();
String selected_wf = request.getParameter("user_selected_instance");
String actual_command_line = request.getParameter("cmd_line");
String selected_job = "add_1";
// ASM method to set command line argument for a specified workflow and job
asm_service.setCommandLineArg(userID, selected_wf, selected_job,
actual_command_line);
}
Deploy
portlet into gUSE component
Deploy
a
compiled WAR file
1
?
1.
Sign in as a user with a
dmin rights
(default username is
:
test@liferay.com
,
password is:
test
)
.
1
Name of it is
MyFirstASMInterface.war
in
/dist folder of the project folder.
34
Figure
32
: Login
2.
Navigate to
Plugin Installer
panel by clicking
Manage
-
>
Control Panel
.
3.
Select
Plugins Installation
in the left panel menu.
4.
Click
Mor
e
Portlets
and upload
File
link.
Figure
33
: Deploy a compiled web application
Adjust
ASM
based portlet
1.
As admin, go to
Settings
menu and select
Internal Services
option
.
35
Figure
34
: Interface for
Internal Services
2.
Click
New
.
3.
T
ype the
text
fields
:
Type of Component:
portal
Service group:
gUSE
URL of Component:
http://localhost:8080/MyFirstASMInterface
URL to initialize Component:
http://localhost:8080/MyFirstASMInterface/init
Public URL of Component:
http://localhost:8080/MyFirstASMInterface
State:
active
4.
Click
S
ave
.
5.
Select
Properties
tab
.
Set
http://localhost:8080/wspgrade
as
Source component
and
http://localhost:8080/MyFirstASMInterface
as
Destination
one.
6.
C
lick
C
opy
.
E
36
Figure
35
: Copy existing portal parameters
7.
Stop the portal.
8.
Adjust CATALINA_HOME environment variable to tomcat’s root folder.
9.
Run install.sh (It’s placed in root folder of package and source of ASM).
10.
Start the
portal.
11.
Finally
,
initialize
again
the whole portal by calling
http://localhost:8080/information/init.jsp
(sometimes
portal restart
is
required.)
37
Appendix
Sample web.xml file
<?xml
version="1.0" encoding="UTF
-
8"?>
<web
-
app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema
-
instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web
-
app_2_4.xsd">
<display
-
name>WS
-
Pgrade in Liferay</display
-
name>
<servlet>
<servlet
-
name>InitServices</servlet
-
name>
<servlet
-
class>hu.sztaki.lpds.information.local.InitAxisServices</servlet
-
class>
<init
-
param>
<param
-
name>baseurl</param
-
name>
<param
-
value>http://localhost:8080/ASM_Sample/servlet/AxisServlet</param
-
value>
</init
-
param>
<init
-
param>
<param
-
name>install
-
4</param
-
name>
<param
-
value>webapps/ASM_Sample/WEB
-
INF/lib/wfi.wsdd</param
-
value>
</init
-
param>
<
init
-
param>
<param
-
name>install
-
1</param
-
name>
<param
-
value>webapps/ASM_Sample/WEB
-
INF/lib/storage.wsdd</param
-
value>
</init
-
param>
<init
-
param>
<param
-
name>install
-
2</param
-
name>
<param
-
value>webapps/ASM_Sample/WEB
-
IN
F/lib/submitter.wsdd</param
-
value>
</init
-
param>
<init
-
param>
<param
-
name>install
-
3</param
-
name>
<param
-
value>webapps/ASM_Sample/WEB
-
INF/lib/remote.wsdd</param
-
value>
</init
-
param>
<init
-
param>
<param
-
name>run
-
0</param
-
name>
<param
-
value>hu.sztaki.lpds.information.local.PropertyInitCommandImpl
</param
-
value>
</init
-
param>
</servlet>
<servlet
-
mapping>
<servlet
-
name>InitServices</servlet
-
name>
<url
-
pattern>/init</url
-
pattern>
<
/servlet
-
mapping>
<servlet>
<servlet
-
name>InitServlet</servlet
-
name>
38
<servlet
-
class>hu.sztaki.lpds.pgportal.servlet.InitServlet</servlet
-
class>
</servlet>
<servlet
-
mapping>
<servlet
-
name>InitServlet</servlet
-
name>
<url
-
patter
n>/initservlet</url
-
pattern>
</servlet
-
mapping>
<servlet>
<servlet
-
name>ajax</servlet
-
name>
<servlet
-
class>hu.sztaki.lpds.pgportal.servlet.ajax</servlet
-
class>
</servlet>
<servlet
-
mapping>
<servlet
-
name>ajax</servlet
-
name>
<url
-
pattern>/ajax</url
-
pattern>
</servlet
-
mapping>
<servlet>
<servlet
-
name>lg</servlet
-
name>
<servlet
-
class>hu.sztaki.lpds.pgportal.servlet.LoggServlet</servlet
-
class>
</servlet>
<servlet
-
mapping>
<servlet
-
name>lg</servlet
-
name>
<url
-
pa
ttern>/logg</url
-
pattern>
</servlet
-
mapping>
<servlet>
<servlet
-
name>tce</servlet
-
name>
<servlet
-
class>hu.sztaki.lpds.pgportal.servlet.TinyMCEList</servlet
-
class>
</servlet>
<servlet
-
mapping>
<servlet
-
name>tce</servlet
-
name>
<
url
-
pattern>/tce</url
-
pattern>
</servlet
-
mapping>
<servlet>
<servlet
-
name>AxisServlet</servlet
-
name>
<display
-
name>Apache
-
Axis Servlet</display
-
name>
<servlet
-
class>
org.apache.axis.transport.http.AxisServlet
</servlet
-
class>
</servlet>
<servlet>
<servlet
-
name>AdminServlet</servlet
-
name>
<display
-
name>Axis Admin Servlet</display
-
name>
<servlet
-
class>
org.apache.axis.transport.http.AdminServlet
</servlet
-
class>
<load
-
on
-
startup>100</load
-
on
-
startup>
</servlet>
39
<servlet>
<servlet
-
name>SOAPMonitorService</servlet
-
name>
<display
-
name>SOAPMonitorService</display
-
name>
<servlet
-
class>
org.apache.axis.monitor.SOAPMonitorService
</servlet
-
class>
<init
-
param>
<param
-
name
>SOAPMonitorPort</param
-
name>
<param
-
value>5001</param
-
value>
</init
-
param>
<load
-
on
-
startup>100</load
-
on
-
startup>
</servlet>
<servlet
-
mapping>
<servlet
-
name>AxisServlet</servlet
-
name>
<url
-
pattern>/servlet/AxisServlet</url
-
patter
n>
</servlet
-
mapping>
<servlet
-
mapping>
<servlet
-
name>AxisServlet</servlet
-
name>
<url
-
pattern>/services/*</url
-
pattern>
</servlet
-
mapping>
<servlet
-
mapping>
<servlet
-
name>SOAPMonitorService</servlet
-
name>
<url
-
pattern>/SOAPMonitor<
/url
-
pattern>
</servlet
-
mapping>
<session
-
config>
<session
-
timeout>
30
</session
-
timeout>
</session
-
config>
<welcome
-
file
-
list>
<welcome
-
file>index.jsp</welcome
-
file>
</welcome
-
file
-
list>
</web
-
app>
40
Component descriptors
Portal.wsdd
<deployment xmlns="http://xml.apache.org/axis/wsdd/"
xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
<service name="urn:loggservice" provider="java:RPC">
<parameter name="className"
value="hu.sztak
i.lpds.logging.net.wsaxis13.LogServiceImpl"/>
<parameter name="allowedMethods" value="sendLog"/>
<parameter name="scope" value="request"/>
<beanMapping qname="lpdsNS:LogInfoBean" xmlns:lpdsNS="urn:BeanService"
languageSpecificType="
java:hu.sztaki.lpds.logging.com.LogInfoBean"/>
</service>
</deployment>
Remote.wsdd
<deployment xmlns="http://xml.apache.org/axis/wsdd/"
xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
<service name="urn:remotesubmit" provider="java:RP
C">
<parameter name="className"
value="hu.sztaki.lpds.portal.net.wsaxis13.RemoteSubmitImpl"/>
<parameter name="allowedMethods" value="submit"/>
<parameter name="scope" value="request"/>
</service>
</deployment>
Storage.wsdd
<
deployment xmlns="http://xml.apache.org/axis/wsdd/"
xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
<service name="urn:portalstorageservice" provider="java:RPC">
<
parameter name="className"
value="hu.sztaki.lpds.portal.net.wsaxis13.PortalStorageServiceImpl"/>
<parameter name="allowedMethods" value="newOccupied newWorkflowNames
checkWorkflowNames"/>
<parameter name="scope" value="request"/>
<b
eanMapping qname="lpdsNS:ComDataBean" xmlns:lpdsNS="urn:BeanService"
languageSpecificType="java:hu.sztaki.lpds.wfs.com.ComDataBean"/>
<beanMapping qname="lpdsNS:StoragePortalWorkflowNamesBean"
xmlns:lpdsNS="urn:BeanService"
languageSpecificType="ja
va:hu.sztaki.lpds.portal.com.StoragePortalWorkflowNamesBean"/>
<typeMapping
xmlns:ns="http://soapinterop.org/"
qname="ns1:AxisHashtable"
type="java:java.util.Hashtable[]"
serializer="org.apache.axis.encoding.ser.Arra
ySerializerFactory"
deserializer="org.apache.axis.encoding.ser.ArrayDeserializerFactory"
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
/>
</service>
41
</deployment>
Submitter.wsdd
<deployment xmlns="http://xml.apache.org
/axis/wsdd/"
xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
<service name="urn:portalsubmitterservice" provider="java:RPC">
<parameter name="className"
value="hu.sztaki.lpds.portal.net.wsaxis13.PortalSubmitterServiceImpl"/>
<parameter name="allowedMethods" value="getProxy getActiveProxys"/>
<parameter name="scope" value="request"/>
<operation name="getActiveProxys" returnQName="returnqname"
returnType="ns1:AxisVector" >
<parameter name="dh" type="ns1:Axis
Vector"/>
</operation>
<typeMapping deserializer="org.apache.axis.encoding.ser.VectorDeserializerFactory"
languageSpecificType="java:java.util.Vector" qname="ns1:AxisVector"
serializer="org.apache.axis.encoding.ser.VectorSerializerFactory"
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</service>
</deployment>
Tool.wsdd
<deployment xmlns="http://xml.apache.org/axis/wsdd/"
xmlns:java="http://xml.apa
che.org/axis/wsdd/providers/java">
<service name="urn:portaltoolservice" provider="java:RPC">
<parameter name="className"
value="hu.sztaki.lpds.portal.net.wsaxis13.PortalToolServiceImpl"/>
<
parameter name="allowedMethods" value="uploadUserProxy uploadUserProxyStr
submittWorkflow submittWorkflowStr"/>
<parameter name="scope" value="request"/>
<beanMapping qname="lpdsNS:ToolComDataBean" xmlns:lpdsNS="urn:BeanService"
languageSpe
cificType="java:hu.sztaki.lpds.portal.com.ToolComDataBean"/>
</service>
</deployment>
wfi.wsdd
<deployment xmlns="http://xml.apache.org/axis/wsdd/"
xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
<service name="urn:portalwfsservice" pr
ovider="java:RPC">
<parameter name="className"
value="hu.sztaki.lpds.portal.net.wsaxis13.PortalWfiServiceImpl"/>
<parameter name="allowedMethods" value="setStatus setCollectionStatus"/>
<parameter name="scope" value="request"/>
<beanMapping qname="lpdsNS:JobStatusBean" xmlns:lpdsNS="urn:BeanService"
languageSpecificType="java:hu.sztaki.lpds.wfs.com.JobStatusBean"/>
<typeMapping
type="java:java.util.Vector" qname="ns1:AxisVector"
42
deserializer="org.apache.axis.encoding.ser.VectorDeserializerFactory"
serializer="org.apache.axis.encoding.ser.VectorSerializerFactory"
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</service>
</deployment>
Enter the password to open this PDF file:
File name:
-
File size:
-
Title:
-
Author:
-
Subject:
-
Keywords:
-
Creation Date:
-
Modification Date:
-
Creator:
-
PDF Producer:
-
PDF Version:
-
Page Count:
-
Preparing document for printing…
0%
Σχόλια 0
Συνδεθείτε για να κοινοποιήσετε σχόλιο