Application Specific Module 3.4.3

stockingssoyaInternet και Εφαρμογές Web

7 Δεκ 2013 (πριν από 3 χρόνια και 6 μήνες)

171 εμφανίσεις





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>