ATG Rest Web Services ATG Rest Web Services Manny Parasirakis Software Architect ATG 6
Document Sample


ATG Rest Web Services
Manny Parasirakis
Software Architect - ATG
6/23/2009
Agenda
What are REST Web Services?
What are ATG REST Web Services?
Security
Filtering and Aliasing
Client Libraries
Q&A
2
What are REST Web Services?
3
What are REST Web Services?
Stands for “Representational State Transfer”
Not a standard
It is an architectural style
4
What are REST Web Services?
Everything on the web is a “resource”
– http://www.boeing.com/aircraft
– http://www.boeing.com/aircraft/747
– http://www.boeing.com/aircraft/747/engine2
HTTP method type determines what operation to
execute on a resource
– GET
– POST
– PUT
– DELETE
5
What are REST Web Services?
http://www.boeing.com/aircraft (GET)
–{
“aircraft”: [
http://www.boeing.com/aircraft/707,
http://www.boeing.com/aircraft/717,
http://www.boeing.com/aircraft/727,
http://www.boeing.com/aircraft/737,
http://www.boeing.com/aircraft/747,
http://www.boeing.com/aircraft/757,
http://www.boeing.com/aircraft/767,
http://www.boeing.com/aircraft/777,
http://www.boeing.com/aircraft/787
]
}
6
What are REST Web Services?
http://www.boeing.com/aircraft/777 (GET)
–{
“name”: “Boeing 777”,
“seats”: 538,
“engines”: 2,
“engine-manufacturer”: “General Electric”,
“engine-specs”:
“http://www.boeing.com/aircraft/777/engine-specs”
}
7
What are REST Web Services?
http://www.boeing.com/aircraft/777/takeoff (POST)
{
“atgResponse”: true
}
8
What are ATG REST Web Services?
9
What are ATG REST Web Services?
Allows access to ATG resources to data and
functionality over http
– Read/Write nucleus component properties
– Execute nucleus component methods
– Execute form handler methods
– Create/Read/Update/Delete repository items and
their properties
Exposes all the fundamental operations and
access to data that is required to build an ATG
application
10
New Paradigm? Maybe…
11
How do you enable ATG REST Web Services
Add the REST module to the list of modules at startup
This will enable access in a RESTful way to all nucleus
components, form handlers, and repositories
– Yes, there is a security layer
If a new component, property, or method is added, the only
change needed to access that resource via REST is to
configure security to allow access
12
Bean/Repository REST Requests
Two types of ATG REST requests
– Bean
– Repository
Bean request is used to call nucleus component
methods, form handler methods, and access
nucleus component properties
Repository request is used to execute repository
operations and access repository data
– Create
– Read
– Update
– Delete
13
What does an ATG REST Request look like?
scheme://server:port/rest/[bean|repository]/
<resource path>
14
What does an ATG REST Request look like?
Bean requests
GET requests (Retrieve nucleus component data)
– http://server:port/rest/bean/atg/dynamo/Configuration
– http://server:port/rest/bean/atg/dynamo/Configuration/httpPort
POST requests (Call a nucleus or form handler method)
– http://server:port/rest/bean/atg/dynamo/Configuration/setHttp
Port
PUT (Set a nucleus component property)
– http://server:port/rest/bean/atg/dynamo/Configuration/httpPort
15
What does an ATG REST Request look like?
Repository requests
GET requests
– http://server:port/rest/repository/atg/commerce/catalog/ProductCatal
og/product
– http://server:port/rest/repository/atg/commerce/catalog/ProductCatal
og/product/abc123
– http://server:port/rest/repository/atg/commerce/catalog/ProductCatal
og/product/abc123/displayName
POST requests
– http://server:port/rest/repository/atg/commerce/catalog/ProductCatal
og/product
– http://server:port/rest/repository/atg/commerce/catalog/ProductCatal
og/product/abc123
PUT
– http://server:port/rest/repository/atg/commerce/catalog/ProductCatal
og/product/abc123/displayName
DELETE
– http://server:port/rest/repository/atg/commerce/catalog/ProductCatal
og/product/abc123
16
What do the responses look like?
Responses can be either JSON or XML
– Default is defined on server
– Client can override per request
{
“httpPort”: 8840
}
<atgResponse>
<httpPort>8840</httpPort>
</atgResponse>
17
More Response Examples (JSON)
{
"allRootCategories": "http://localhost/rest/repository/atg/commerce/catalog/ProductCatalog/catalog/cat123/allRootCategories",
"allRootCategoryIds": "http://localhost/rest/repository/atg/commerce/catalog/ProductCatalog/catalog/cat123/allRootCategoryIds",
"ancestorCatalogsAndSelf":
"http://localhost/rest/repository/atg/commerce/catalog/ProductCatalog/catalog/cat123/ancestorCatalogsAndSelf",
"ancestorCategories": "http://localhost/rest/repository/atg/commerce/catalog/ProductCatalog/catalog/cat123/ancestorCategories",
"directAncestorCatalogsAndSelf":
"http://localhost/rest/repository/atg/commerce/catalog/ProductCatalog/catalog/cat123/directAncestorCatalogsAndSelf",
"directParentCatalogs": "http://localhost/rest/repository/atg/commerce/catalog/ProductCatalog/catalog/cat123/directParentCatalogs",
"displayName": "Tools",
"displayName_de": null,
"displayName_en": "Tools",
"displayName_ja": null,
"id": "cat123",
"index": 0,
"itemAcl": null,
"indirectAncestorCatalogs":
"http://localhost/rest/repository/atg/commerce/catalog/ProductCatalog/catalog/cat123/indirectAncestorCatalogs",
"parentFolders": "http://localhost/rest/repository/atg/commerce/catalog/ProductCatalog/catalog/cat123/parentFolders",
"repositoryId": "cat123",
"rootCategories": "http://localhost/rest/repository/atg/commerce/catalog/ProductCatalog/catalog/cat123/rootCategories",
"rootCategoryIds": "http://localhost/rest/repository/atg/commerce/catalog/ProductCatalog/catalog/cat123/rootCategoryIds",
"rootSubCatalogs": "http://localhost/rest/repository/atg/commerce/catalog/ProductCatalog/catalog/cat123/rootSubCatalogs",
"status": "other",
"subCatalogIds": "http://localhost/rest/repository/atg/commerce/catalog/ProductCatalog/catalog/cat123/subCatalogIds",
"subCatalogs": "http://localhost/rest/repository/atg/commerce/catalog/ProductCatalog/catalog/cat123/subCatalogs",
}
18
More Response Examples (XML)
<atgResponse>
<repositoryId>cat123</repositoryId>
<parentFolders>http://localhost/rest/repository/atg/commerce/catalog/ProductCatalog/catalog/cat123/parentFolders</parentFolders>
<subCatalogIds>http://localhost/rest/repository/atg/commerce/catalog/ProductCatalog/catalog/cat123/subCatalogIds</subCatalogIds>
<rootCategories>http://localhost/rest/repository/atg/commerce/catalog/ProductCatalog/catalog/cat123/rootCategories</rootCategories>
<ancestorCategories>http://localhost/rest/repository/atg/commerce/catalog/ProductCatalog/catalog/cat123/ancestorCategories</ancestorCategories>
<status>other</status>
<indirectAncestorCatalogs>
http://localhost/rest/repository/atg/commerce/catalog/ProductCatalog/catalog/cat123/indirectAncestorCatalogs
</indirectAncestorCatalogs>
<ancestorCatalogsAndSelf>
http://localhost/rest/repository/atg/commerce/catalog/ProductCatalog/catalog/cat123/ancestorCatalogsAndSelf
</ancestorCatalogsAndSelf>
<displayName/>Tools</displayName>
<displayName_en>Tools</displayName_en>
<index>0</index>
<id>cat123</id>
<rootSubCatalogs>http://localhost/rest/repository/atg/commerce/catalog/ProductCatalog/catalog/cat123/rootSubCatalogs</rootSubCatalogs>
<subCatalogs>http://localhost/rest/repository/atg/commerce/catalog/ProductCatalog/catalog/cat123/subCatalogs</subCatalogs>
<allRootCategoryIds>http://localhost/rest/repository/atg/commerce/catalog/ProductCatalog/catalog/cat123/allRootCategoryIds</allRootCategoryIds>
<itemAcl/>
<allRootCategories>http://localhost/rest/repository/atg/commerce/catalog/ProductCatalog/catalog/cat123/allRootCategories</allRootCategories>
<displayName_ja/>
<rootCategoryIds>http://localhost/rest/repository/atg/commerce/catalog/ProductCatalog/catalog/cat123/rootCategoryIds</rootCategoryIds>
<displayName_de/>
<directAncestorCatalogsAndSelf>
http://localhost/rest/repository/atg/commerce/catalog/ProductCatalog/catalog/cat123/directAncestorCatalogsAndSelf
</directAncestorCatalogsAndSelf>
<directParentCatalogs>
http://localhost/rest/repository/atg/commerce/catalog/ProductCatalog/catalog/cat123/directParentCatalogs
</directParentCatalogs>
</atgResponse>
19
Response Codes
200 (OK) - The Request was successful. For a GET request, the response contains an entity
corresponding to the requested resource. In a POST request the response will contain an entity
describing or containing the result of the action.
201 (Created) - Returned only for POST requests that create repository items. The request was
successful and the repository item was created.
400 (Bad Request) - The request could not be completed because the request URL and/or
parameters were improperly formatted.
401 (Unauthorized) - user session does not have the proper security credentials to execute the
method, property, or access the repository for the requested resource.
403 (Forbidden) - user has configured that a specific property is not writable via the filtering
configuration.
404 (Not Found) - The request could not be completed because it was made for a resource which
does not exist.
410 (Gone) - Returned only for DELETE requests that remove repository items. The request was
successful and the repository item was deleted.
500 (Internal server error) - The request could not be completed because an unexpected exception
occurred.
20
ATG REST Security
21
ATG REST Security
Requires client to have a user profile and be logged in
to access functionality by default
– Default can be changed to not require login
Once logged in no access to resources is allowed by
default
Must configure security to access resources
22
ATG REST Security
Uses ATG security system, acls
Security can be placed on any resource
– Nucleus component (read, write)
– Nucleus component property (read, write)
– Nucleus component method (execute)
– Form handler method (execute)
23
ATG REST Security
Repository security is used for securing repository
items
– No special REST security for repository items
exists
Unsecure repositories are not allowed any access
by default
24
ATG REST Security
Security is configured via an XML file in the
configpath
– /atg/rest/security/restSecurityConfiguration.xml
25
ATG REST Security
Set security on all components, their methods and properties
– <rest-security>
<default-acl value="Profile$login$user1:read,write,execute"/>
</rest-security>
Set security on specific methods
– <rest-security>
<resource component="/atg/userprofiling/ProfileServices">
<default-acl value="Profile$login$user1:read,write,execute"/>
<method name="loginUser" secure="false“/>
<method name="logoutUser" secure="false“/>
</resource>
<resource component="/atg/userprofiling/ProfileFormHandler">
<method name="handleLogin" secure="false“/>
<method name="handleLogout" secure="false“/>
</resource>
</rest-security>
Set security on specific component properties
– <rest-security>
<resource component="/atg/rest/Configuration">
<default-acl value="Profile$login$user1:read,write,execute"/>
<property name="defaultOutputCustomizer" secure="false“/>
<property name="defaultInputCustomizer" secure="false“/>
</resource>
</rest-security>
26
ATG REST Security
Set security on all components beginning with a certain path
– <rest-security>
<resource component="/atg/commerce/*">
<default-acl value="Profile$login$user1:read,write,execute"/>
</resource>
</rest-security>
27
Filtering and Aliasing
28
Filtering and Aliasing
Component or repository item properties can be
marked as hidden or not writeable
Configure subset of properties to be returned for
components or repository items
Add additional virtual properties to components or
repository items
Create virtual components which allows for custom
“objects”
29
Filtering and Aliasing
Filtering is configured via an XML file in the
configpath
– /atg/rest/filtering/filteringConfiguration.xml
30
Filtering and Aliasing
Example of one hidden property and another writable in a nucleus
component and a repository item
– <rest-filtering>
<component name="/some/Component" default-include="true">
<property name="property1" hidden="true"/>
<property name="property2" writable="false"/>
</component>
<component name="/some/Repository" default-include="true">
<item-descriptor name=“itemDescriptorName">
<property name="repProperty1" hidden="true"/>
<property name="repProperty2" writable="false"/>
</item-descriptor>
</component>
</rest-filtering>
31
Filtering and Aliasing
The default-include attribute tells the system whether or not to
include the native properties defined in the component or
repository item or just the ones listed in the configuration file
– <rest-filtering>
<component name="/some/Component" default-include="true">
<property name="property1" hidden="true"/>
<property name="property2" writable="false"/>
</component>
<component name="/some/Repository" default-include="true">
<item-descriptor name=“itemDescriptorName">
<property name="repProperty1" hidden="true"/>
<property name="repProperty2" writable="false"/>
</item-descriptor>
</component>
</rest-filtering>
32
Filtering and Aliasing
Additional properties which do not exist in the nucleus component or repository
item can be added as virtual properties
The configuration also contains the information about the source of the values of
the virtual properties
– <rest-filtering>
<component name="/some/Component" default-include="true">
<property name=“label" target=“displayName"/>
<property name=“color" target=“specs.color"/>
</component>
<component name="/some/Repository" default-include="true">
<item-descriptor name=“itemDescriptorName">
<property name=“label" target=“displayName"/>
<property name=“color" target=“specs.color"/>
</item-descriptor>
</component>
</rest-filtering>
33
Filtering and Aliasing
Adding a component attribute to the property tag and using that in combination
with the target tag, the value of a property can come from another nucleus
component
Dot notation can be used in the target attribute
<rest-filtering>
<component name="/some/Component" default-include="true">
<property name=“price" component="/some/other/Component" target=“price"/>
</component>
<component name="/some/Repository" default-include="true">
<item-descriptor name=“itemDescriptorName">
<property name=“price" component="/some/other/Component" target=“price"/>
</item-descriptor>
</component>
</rest-filtering>
34
Filtering and Aliasing
If you need to write custom code to specify your value, then you must use the
property-customizer attribute
<rest-filtering>
<component name="/some/Component" default-include="true">
<property name=“manufacturer" property-customizer="some.class.Here"/>
</component>
<component name="/some/Repository" default-include="true">
<item-descriptor name=“itemDescriptorName">
<property name="manufacturer" property-customizer="some.class.Here"/>
</item-descriptor>
</component>
</rest-filtering>
atg.rest.filtering.RestPropertyCustomizer interface
– public Object getPropertyValue(String pPropertyName, Object pResource);
– public void setPropertyValue(String pPropertyName, Object pValue, Object
pResource);
35
Filtering and Aliasing
One thing which can be done is to specify the name of a component
which does not exist in the name attribute of the component tag
When this component is requested, the list of properties which is
specified inside the component tag will be rendered
Only use the property tag with the component/target attributes or the
property-customizer attribute
<rest-filtering>
<component name="/some/nonexisting/Component">
<property name="property1" component="/some/other/Component“
target="aProperty"/>
<property name="property2" property-customizer="some.class.Here"/>
</component>
<rest-filtering>
36
ATG REST Client Libraries
37
ATG REST Client Libraries
There are two client libraries which makes using ATG REST
Web Services very easy
– Java
– Actionscript (Flex/Flash)
Hides all the complexity of ATG REST Web Services
Exposes methods to
– Read/Write Nucleus component property values
– Execute Nucleus component and form handler methods
– Create/Read/Update/Delete repository items and properties
– Query repositories/Execute RQL queries
38
Java Client Lib
RestSession
RestComponentHelper
RestRepositoryHelper
RestResult
RestConstants
RestClientException
39
Java Client Lib Example
public RestSession login() throws RestClientException {
RestSession session = RestSession.createSession(getHostname(),
getPort(), getUsername(), getPassword());
session.setUseHttpsForLogin(false);
session.login();
return session;
}
public void logout(RestSession pSession) throws RestClientException {
if (pSession != null)
pSession.logout();
}
40
Java Client Lib Example – Get Component
RestSession session = null;
RestResult result = null;
try {
session = login();
result = RestComponentHelper.getComponent("/atg/dynamo/Configuration", null, session);
String res = result.readInputStream();
// do something with the result (either JSON or XML formatted)
}
catch (RestClientException e) {
e.printStackTrace();
fail(e.toString());
}
catch (IOException e) {
e.printStackTrace();
fail(e.toString());
}
finally {
if (result != null)
result.close();
logout(session);
}
41
Java Client Lib Example – Get Property Value
RestResult result =
RestComponentHelper.getPropertyValue("/atg/dynamo/Configuration", “httpPort",
null, session);
42
Java Client Lib Example – Set Property Value
RestResult result =
RestComponentHelper.setPropertyValue("/atg/dynamo/Configuration", “httpPort",
8080, session);
43
Java Client Lib Example – Execute Method
RestResult result =
RestComponentHelper.executeMethod("/some/nucleus/component",
“methodName", new Object [] {10, “string”}, null, session);
Map<String,Object> params = new HashMap<String,Object>();
params.put(RestConstants.METHOD, “(I;Ljava/lang/String)V”);
RestResult result =
RestComponentHelper.executeMethod("/some/nucleus/component",
“methodName", new Object [] {10, “string”}, params, session);
44
Java Client Lib Example – Execute Form Handler
Method
Map<String,Object> params = new HashMap<String,Object>();
params.put("firstName", "Andy");
params.put("lastName", "Jones");
RestResult result =
RestComponentHelper.executeMethod("/some/FormHandler", "create", null,
params, session);
45
Java Client Lib Example - Parameters
No parameters
– RestResult result = RestComponentHelper.executeMethod("/some/nucleus/component",
“methodName", null, session);
Simple parameter
– RestResult result = RestComponentHelper.executeMethod("/some/nucleus/component",
“methodName", new Object[] {10}, session);
– RestResult result = RestComponentHelper.executeMethod("/some/nucleus/component",
“methodName", new Object[] {“string”}, session);
– RestResult result = RestComponentHelper.executeMethod("/some/nucleus/component",
“methodName", new Object[] {10, “string”},
session);
Collection parameter
– List<Integer> list = new ArrayList<Integer>();
list.add(10);
RestResult result = RestComponentHelper.executeMethod("/some/nucleus/component",
“methodName", new Object[] {list}, session);
Object parameter
– MyObject myObject = new MyObject();
RestResult result = RestComponentHelper.executeMethod("/some/nucleus/component",
“methodName", new Object[] {myObject}, session);
46
Java Client Lib Example – Get Repository Item
RestResult result =
RestRepositoryHelper.getItem("/atg/commerce/catalog/ProductCatalog", “product",
“prod12345”, null, session);
47
Java Client Lib Example – Get Repository Items
RestResult result =
RestRepositoryHelper.getItems("/atg/commerce/catalog/ProductCatalog",
“product", null, session);
48
Java Client Lib Example – Execute RQL Query
RestRepositoryHelper.executeRQLQuery("/atg/commerce/catalog/ProductCatalog“
, “product", “ALL”, null, session);
Map<String,Object> params = new HashMap<String,Object>();
params.put(RestConstants.INDEX, 0);
params.put(RestConstants.COUNT, 10);
RestResult result =
RestRepositoryHelper.executeRQLQuery("/atg/commerce/catalog/ProductCatalog“
, “product", “ALL”, params, session);
49
Java Client Lib Example – Get Repository
Property Value
RestResult result =
RestRepositoryHelper.getPropertyValue("/atg/commerce/catalog/ProductCatalog",
“product", “prod12345”, “displayName”, null, session);
50
Java Client Lib Example – Set Repository
Property Value
RestResult result =
RestRepositoryHelper.setPropertyValue("/atg/commerce/catalog/ProductCatalog",
“product", “prod12345”, “displayName”, “My Product Name”, null, session);
51
Java Client Lib Example – Create Repository
Item
RestResult result =
RestRepositoryHelper.createItem("/atg/commerce/catalog/ProductCatalog",
“product", null, session);
RestResult result =
RestRepositoryHelper.createItem("/atg/commerce/catalog/ProductCatalog",
“product", “myProductId12345”, null, session);
Map<String,Object> params = new HashMap<String,Object>();
params.put(RestConstants.TRANSIENT, true);
RestResult result =
RestRepositoryHelper.createItem("/atg/commerce/catalog/ProductCatalog",
“product", params, session);
52
Java Client Lib Example – Remove Repository
Item
RestResult result =
RestRepositoryHelper.removeItem("/atg/commerce/catalog/ProductCatalog",
“product", “prod12345”, null, session);
53
Rest Parameters
atg.rest.client.RestConstants
– public static final String INDEX = "atg-rest-index";
– public static final String COUNT = "atg-rest-count";
– public static final String TRANSIENT = "atg-rest-transient";
– public static final String METHOD = "atg-rest-method";
– public static final String OUTPUT = "atg-rest-output";
– public static final String DEPTH = "atg-rest-depth";
54
Rest Parameters - Output
Allows the server’s configured output format to be overridden on
each request
– atg-rest-output=json
– atg-rest-output=xml
Map<String,Object> params = new HashMap<String,Object>();
params.put(RestConstants.OUTPUT, “xml”);
55
Rest Parameters - Depth
The atg-rest-depth parameter allows the caller to
determine how deep of an object tree to return
– Default is 0 which means references are returned as
URLs
– Value of 1 or more means that all references and
multivalued objects will be included in the output
56
Rest Parameters - Depth
<atgResponse>
<displayName>My Product</displayName>
<specs>
http://localhost/rest/repository/atg/commerce/catalog
/ProductCatalog/specs/spec12345
</specs>
</atgResponse>
<atgResponse>
<displayName>My Product</displayName>
<specs>
<color>red</color>
<size>medium</size>
</specs>
</atgResponse>
57
Actionscript Client Lib
Similar structure, classes, and methods as Java
client lib
Helper methods take resultHandler and
faultHandler callback methods as arguments
There is no RestResult class
58
Actionscript Client Lib
public function login():void {
session = RestSession.createSession(getHostname(), getPort(), getUserName(), getPassword());
session.useHttpsForLogin = false;
session.login(handleLogin, handleLoginFault);
}
public function handleLogin(pEvent:Event):void {
// handle login success
}
public function handleLoginFault(pEvent:Event):void {
// handle login fault
}
59
Actionscript Client Lib
public function getItem():void {
RestRepositoryHelper.getItem("/atg/commerce/catalog/ProductCatalog", "product",
“prod12345”, null, session, handleResult, handleFault);
}
public function handleResult(pEvent:Event):void {
if (session.outputFormat == RestConstants.JSON) {
var json:Object = JSON.decode(pEvent.target.data);
// do something with the data in json variable
}
else if (session.outputFormat == RestConstants.XML) {
var xml:XML = new XML(pEvent.target.data);
// do something with the data in xml variable
}
}
public function handleFault(pEvent:Event):void {
Alert.show("Fault: " + pEvent.toString());
}
60
Q&A
Questions?
61
Get documents about "