You are on page 1of 21

T 2 4 C o m p o n e n ti s a ti o n

R E STf ul W S
R20
T 2 4 C o m p o n e n ti s a ti o n R E STf ul
WS

Amendment History:

Revisio
Date Amended Name Description
n

1 21st June 2019 T. Aubert Initial version

2 1st July 2019 T. Aubert Support of PUT, POST, DELETE and Security

2 26th March 2020 H. Aubert R20 AMR Review

Page 2
T 2 4 C o m p o n e n ti s a ti o n R E STf ul
WS

Copyri g h t
Copyright © Temenos Headquarters SA 2009-2020.
All rights reserved.
This document contains proprietary information that is protected by copyright. No part of this document may
be reproduced, transmitted, or made available directly or indirectly to a third party without the express
written agreement of TEMENOS UK Limited. Receipt of this material directly TEMENOS UK Limited
constitutes its express permission to copy. Permission to use or copy this document expressly excludes
modifying it for any purpose, or using it to create a derivative therefrom.

Errat a and Com m e n t s


If you have any comments regarding this manual or wish to report any errors in the
documentation, please document them and send them to the address below:
Technology Department

Temenos Headquarters SA
2 Rue de l’Ecole-de-Chimie,
CH - 1205 Geneva,
Switzerland

Tel SB: +41 (0) 22 708 1150


Fax: +41 (0) 22 708 1160

Please include your name, company, address, and telephone and fax numbers, and email
address if applicable. TAFJdev@temenos.com

Page 3
T 2 4 C o m p o n e n ti s a ti o n R E STf ul
WS

Table of Contents
Copyright................................................................................................................................................ 3
Introduction............................................................................................................................................. 5
The target audience................................................................................................................................ 5
Get ready................................................................................................................................................ 5
The first RESTful webservice................................................................................................................. 7
The URI of the services.......................................................................................................................... 8
The structure of the response................................................................................................................. 9
@Response(…) annotation................................................................................................... 9

Changing the default behaviours.......................................................................................................... 10


@Path(…) annotation (component level)............................................................................ 10

@Path(…) annotation (method level).................................................................................. 10

@QueryParam(…) annotation............................................................................................ 12

Return value (FUNCTIONs).................................................................................................................. 15


Returning complex structures.............................................................................................. 18

PUT, POST and DELETE..................................................................................................................... 22


Security................................................................................................................................................ 22

Page 4
T 2 4 C o m p o n e n ti s a ti o n R E STf ul
WS

Intro d u c t i o n

This document describe how to create RESTful webservices using the T24 Component
Framework. This never been easier to generate such services. In fact, this can be done in a
second. All the complexities are handled by the component framework and its new
functionality: the annotations.

The targ e t audi e n c e

The reader of this document should already be familiar with the JBC language and the
component framework (*.component and *.complex). We will go through examples and will
concentrate on the RESTful webservices generation. Also, we will use “postman“ to use our
service.

Get ready

First, we will create a new component with a simple method.

Component name : MY.FirstRest

Method : getEmployee(FirstName, LastName)

component MY.FirstRest
/* return employee lastName */
private method getEmployee(
/* The first name */
IN firstName string,
/* The lastName */
OUT lastName string
)
{
jBC: GET.EMPLOYEE
}

Page 5
T 2 4 C o m p o n e n ti s a ti o n R E STf ul
WS

and implement the method GET.EMPLOYEE :

$PACKAGE MY.FirstRest
*
* Implementation of MY.FirstRest.getEmployee
*
* firstName(IN) :
* lastName(OUT) :
*
SUBROUTINE GET.EMPLOYEE(firstName, lastName)
IF firstName = "Tony" THEN
lastName = "Curtis"
END ELSE
lastName = "Unknown"
END
RETURN

By saving, the component is automatically compiled, packaged and you can find a file
MY_FirstRest.jar in the directory <tafj_home>/data/<projectName>/jars.

Let’s assume you have a jboss app server, then deploy this file (in module) and update your
module.xml :

<module xmlns="urn:jboss:module:1.0" name="com.temenos.t24">


<resources>
<!-- Insert resources here -->
<resource-root path="./services/MY_FirstRest.jar" />

Then restart your app server. This is needed since this is a module, not a service (yet).

Page 6
T 2 4 C o m p o n e n ti s a ti o n R E STf ul
WS

The first RESTf ul web s e r v i c e

In order to create a webservice from your method, only one operation is needed :

add the “@GET” annotation to your method like this and save your .component.

component MY.FirstRest
/* return employee lastName */
@GET
private method getEmployee(
/* The first name */
IN firstName string,
/* The lastName */
OUT lastName string
)
{
jBC: GET.EMPLOYEE
}

!! This is it, congratulation, you created your first RESTful


webservice !!!
If you look in your jars directory, you now have a new file : my-firstrest.war. There is a kind
of convention in the web services : The URI should be lower case, and the underscore
should be replaced by “-”. This is what we are doing here. To deploy it, just copy this file in
your app server (<jboss_home>/standalone/deployments). You don’t need to restart your
app server, it will detect and load automatically your service.

Test it with postman :

Page 7
T 2 4 C o m p o n e n ti s a ti o n R E STf ul
WS

The URI of th e servi c e s

The URI is the part after the <protocol>://<host>:<port>. In our case : “/my-
firstrest/employee/Tony”

is composed of :

1) /my-firstrest : the root_path (the name of the war file inherited from the name of your
.component)

2) /employee : The Service name (the name of your method in lowercase without the “get”)

3) The “IN” / “INOUT” parameters of your method

We will see later in this document how we can modify them.

Note that all services created with the T24 component Framework have one method
(services) which will show you all the URIs :

So you this URI : /my-firstrest/services will list all the available URIs like this (html output) :

Page 8
T 2 4 C o m p o n e n ti s a ti o n R E STf ul
WS

The stru c t u r e of th e res p o n s e


The response will always have the JSON format.

The default response structure is :

{
"root": {
"<OUT / INOUT parameters>": "<value>"
"response": <return value of the jBC Function>
}
}

In our first example, since the method was a SUBROUTINE (not a FUNCTION), there is
nothing to show in the “response”.

@Re s p o n s e ( … ) an n o t a t i o n

The above structure of the response can be modified by using the @Response annotation.
To describe it, edit your component like this :

component MY.FirstRest

/* return employee lastName */


@GET
@Response("my.new.response.structure")
private method getEmployee(
...
}
URL : http://localhost:9089/my-firstrest/employee/Tony

{
"my": {
"new": {
"response": {
"lastName": "Curtis"
}
}
}
}

Page 9
T 2 4 C o m p o n e n ti s a ti o n R E STf ul
WS

Chan g i n g th e def a u l t be h a v i o u r s .
Appart changing the root path (the name of the war file) mostly everything can be modified
using annotations. In this chapter we will see how.

@Pat h (…) ann o t a t i o n (co m p o n e n t leve l )


The component can be annotated with a @Path. The default value is “/”

Example :

@Path("/training/rest")
component MY.FirstRest

/* return employee lastName */


@GET
@Response("my.new.response.structure")
private method getEmployee(
/* The first name */
IN firstName string,
/* The lastName */
OUT lastName string
)
{
jBC: GET.EMPLOYEE
}
Changes the URI to : /my-firstrest/training/rest/employee/{firstName}

@Pat h (…) ann o t a t i o n (m e t h o d lev e l )


Each methods can also have the @Path annotation. The default is

/<methodName_without_get>/{all IN/INOUT parameters}

In our case, “/employee/{firstName}”

If the method had been

private method getEmployee(


IN country string,
IN city string,
IN firstName string,
OUT lastName string
)

Page 10
T 2 4 C o m p o n e n ti s a ti o n R E STf ul
WS

The URI would have been “/employee/{country}/{city}/{firstname}”

You can change the default with the @Path annotation for the method. At that point there is
a lot of validation being done at the component framework level.

First, let’s change it like this :

@Path("/training/rest")
component MY.FirstRest

/* return employee lastName */


@GET
@Response("my.new.response.structure")
@Path("/temenos/person/{firstName}/name")
private method getEmployee(
...
}

So the URI is now : my-firstrest/training/rest/temenos/person/Tony/name

Validation (rules) for the @Path annotation :

1) All IN, INOUT, MEMBER variables, if not annotated as @QueryParam must be in the
Path.

2) All {…} variables must exists in the definition of the method

3) If a variable is annotated with @QueryParam, it cannot be in the @Path.

Before going in examples, let’s describe the @QueryParam …

Page 11
T 2 4 C o m p o n e n ti s a ti o n R E STf ul
WS

@Qu ery P a r a m ( … ) an n o t a t i o n
Each (not OUT) variable can be annotated by the @QueryParam annotation. The
@QueryParam annotation indicates that the parameter is not part of the URI anymore, but
instead in the html query parameter.Example :

@Path("/training/rest")
component MY.FirstRest
/* return employee lastName */
@GET
@Response("my.new.response.structure")
@Path("/temenos/person")
private method getEmployee(
/* The first name */
@QueryParam
IN firstName string,
. . .
}
Makes that the http request is now :

http://localhost:9089/my-firstrest/training/rest/temenos/person?firstName=Tony

Multiple QueryParams are separated by “&”. eg : … ?firstName=Tony&country=UK ….

A QueryParam can have an alias. Example : @QueryParam(“name”) will make the request :

http://localhost:9089/my-firstrest/training/rest/temenos/person?name=Tony

Let’s resume the @Path & @QueryParam like this.

Component definition http://localhost:9089/my-firstrest ….

private method getEmployee( .../employee/{country}/{city}/{firstName}


IN country string,
IN city string,
IN firstName string,
OUT lastName string
)
@Path("/{country}/{city}") Compilation error :
private method getEmployee(
IN country string, MY.FirstRest.component, The variable
IN city string, firstName must be either in the @Path
IN firstName string, annotation or must be annotated as
'@QueryParam'
OUT lastName string
)

Page 12
T 2 4 C o m p o n e n ti s a ti o n R E STf ul
WS

@Path("/xxx/{country}/{city}") .../xxx/{country}/{city}?name= ….
private method getEmployee(
IN country string,
IN city string,
@QueryParam("name")
IN firstName string,
OUT lastName string
)

@Path("/{country}/{city}") Compilation error :


private method getEmployee(
MY.FirstRest.component, The variable
IN country string,
city cannot be a @QueryParam as it is
@QueryParam("town")
already in the @Path : '/{country}/
IN city string,
{city}'
@QueryParam("name")
IN firstName string,
OUT lastName string
)

@Path("/{country}/{lastName}") Compilation error :


private method getEmployee(
MY.FirstRest.component, The variable
IN country string,
lastName cannot be in the @Path as it is
@QueryParam("town")
a 'OUT' variable.
IN city string,
@QueryParam("name")
IN firstName string,
OUT lastName string
)

@Path("/{country}") Compilation error :


private method getEmployee(
MY.FirstRest.component, The variable
IN country string,
lastName cannot be a @QueryParam as it
@QueryParam("town")
is a 'OUT' variable.
IN city string,
@QueryParam("name")
IN firstName string,
@QueryParam("familly")
OUT lastName string
)

Page 13
T 2 4 C o m p o n e n ti s a ti o n R E STf ul
WS

@Path("/{country}") .../{country}?town= ….&name=...


private method getEmployee(
IN country string,
@QueryParam("town")
IN city string,
@QueryParam("name")
IN firstName string,
OUT lastName string
)
private method getEmployee( .../{city}?country= ….&name=…
@QueryParam("country")
IN country string, Note : If no @Path specified, all variable not
IN city string, having the QueryParam will be in the URI
@QueryParam("name")
IN firstName string,
OUT lastName string
)

Page 14
T 2 4 C o m p o n e n ti s a ti o n R E STf ul
WS

Ret ur n valu e (FU NCTIO N s )

Let’s first get back to our favourite component, an modify the getEmployee method like this :

component MY.FirstRest

/* return employee lastName */


@GET
private method getEmployee : string (
/* The first name */
IN firstName string
)
{
jBC: GET.EMPLOYEE
}

And the Implementation :

$PACKAGE MY.FirstRest
*
* Implementation of MY.FirstRest.getEmployee
*
* firstName(IN) :
*
FUNCTION GET.EMPLOYEE(firstName)
IF firstName = "Tony" THEN
RETURN "Curtis"
END ELSE
RETURN "Unknown"
END
RETURN

Remember that you need to restart your app server !

Page 15
T 2 4 C o m p o n e n ti s a ti o n R E STf ul
WS

Page 16
T 2 4 C o m p o n e n ti s a ti o n R E STf ul
WS

Result :

As mentionned earlier, the « default » structure of the response is root.response. Please


refer to the specific chapter if you want to modify it. Unlike the OU / INOUT variables, the
response can be a list<...> a complex type or a list<complex type>.

Let’s first see what happen with lists. Modify you implementation like this :
component MY.FirstRest
/* return employee lastName */
@GET
private method getEmployee : list<string> (
/* The first name */
IN firstName string
)
{
jBC: GET.EMPLOYEE
}

FUNCTION GET.EMPLOYEE(firstName)
$USING TF.List
RET = ""
IF firstName = "Tony" THEN
TF.List.add(RET, "Curtis")
TF.List.add(RET, "Stark")
TF.List.add(RET, "Blair")
TF.List.add(RET, "Parker")
END ELSE
RETURN "Unknown"
END
RETURN RET

Redeploy MY_FirstRest.jar and my-firstrest.war and restart your app server.

Page 17
T 2 4 C o m p o n e n ti s a ti o n R E STf ul
WS

The same query now returns an array :

Ret u r n i n g co m p l e x str u c t u r e s

Here we will (again) modify our component and implementation to return a complex
structure. To do so, create a new Complex and edit it like this :

complex Employee
@Containment byValue
classes {
NameAndAge
{
lastName : string
age : number
}
}

Page 18
T 2 4 C o m p o n e n ti s a ti o n R E STf ul
WS

Then, modify your component like this :

component MY.FirstRest

/* return employee lastName */


@GET
private method getEmployee : list<Employee:NameAndAge> (
/* The first name */
IN firstName string
)
{
jBC: GET.EMPLOYEE
}

And your implementation like this :


$PACKAGE MY.FirstRest
*
* Implementation of MY.FirstRest.getEmployee
*
* firstName(IN) :
*
FUNCTION GET.EMPLOYEE(firstName)
$USING TF.List
RET = ""
IF firstName = "Tony" THEN
TF.List.add(RET, "Curtis" : @FM : 85)
TF.List.add(RET, "Stark" : @FM : 53)
TF.List.add(RET, "Blair" : @FM : 66)
TF.List.add(RET, "Parkers" : @FM : 37)
END ELSE
RETURN "Unknown"
END
RETURN RET

Page 19
T 2 4 C o m p o n e n ti s a ti o n R E STf ul
WS

Redeploy the war and the jar, restart your app server, and redo the same request :

Page 20
T 2 4 C o m p o n e n ti s a ti o n R E STf ul
WS

PUT, POST and DELETE


@PUT, @POST and @DELETE are supported exactely the same way as the @GET
described earlier.

There is however few differences.

- @DELETE follows exactly the same validation rules as @GET

- @PUT & @POST are supporting, in addition to the @QueryParam, the @FormParam. The
validation rules (no duplicates, not in the @Path, …) are exactely the same.

Se c u r i t y
You method can be annotated with the standard following security annotations

RolesAllowed(...)

DeclareRoles(...)

DenyAll

PermitAll

RunAs(...)

Page 21

You might also like