WebService API - Security Architecture in Hybris e-commerce suit



The Security Strategies The web service security framework implements the strategy pattern, allowing the user to select from a set of security strategies that currently include:
  • Access Manager Security Strategy - based upon the hMC security paradigm
  • Property File Security Strategy - based upon configuration provided in a properties file
  • Custom Security Strategy - allowing the user to write their own strategy
User Group for Web Services
By default the Access Manager Security Strategy is adopted, which authorises a user only if they are in a new security group named webservicegroup. This is not set up by default, so be sure to create this group for your RESTful calls to be authorised as discussed below.
Each strategy implements the SecurityStrategy interface:
public interface SecurityStrategy
{
 boolean isResourceOperationAllowed(final RestResource resource, final String operation);
 boolean isResourceCommandAllowed(final RestResource resource, final String command);
 boolean isDtoOperationAllowed(final Class<?> objectClass, final String operation);
 boolean isAttributeOperationAllowed(final Class<?> attrObjectClass, final String attrQualifier, final String attrOperation);
}
However both strategies differ in implementations and intentions. To specify which strategy to adopt, modify the securityStrategy entry in the platformwebservices-web-spring.xml file:
platformwebservices-web-spring.xml
<beans>
  <!-- ... --->
  <bean id="securityStrategy"
  class="de.hybris.platform.webservices.AccessManagerSecurityStrategy"
  scope="prototype" parent="abstractSecurityStrategy"/>
 
  <!-- <bean id="securityStrategy"
  class="de.hybris.platform.webservices.PropertyFileSecurityStrategy"
  scope="prototype" parent="abstractSecurityStrategy"/>  -->
 
  <!-- <bean id="securityStrategy"
  class="de.hybris.platform.webservices.CustomSecurityStrategy" scope="prototype"
  parent="abstractSecurityStrategy"/>--->
  <!-- ... --->
 
  <bean id="abstractBaseResource"
  class="de.hybris.platform.webservices.AbstractResource" abstract="true"
  scope="prototype">
  <!-- ... --->
  <property name="securityStrategy" ref="securityStrategy"/>
  </bean>
</beans>
If you wish to disable security mechanisms for any reason, it is enough to remove securityStrategy property from the abstractBaseResource bean.
Below we consider the various strategies, starting with the default: Access Manager Security Strategy.

Access Manager Security Strategy

The Access Manager Security Strategy is the default strategy adopted by the hybris WebService API and uses the hMC Access Rights approach.
The Access Manager Security Strategy authorises a user only if they are in a security group named webservicegroup. This is not set up by default, so please be sure to create this group as discussed below, for your RESTful calls to be accepted. The name of this user group is configurable in project.properties file:
webservices.security.group=webservicegroup
By default three user groups are members of this group:
  • admingroup
  • employeegroup
  • customergroup


In RESTful communication, the mapping between the HTTP methods and CRUD operations are as follows:
HTTP method CRUD operation
GET Read
POST Create / Update
PUT Create / Update
DELETE Delete
As seen, both POST and PUT may refer to Create and Update operations. To determine which is meant, when a POST or PUT request is processed, we check if the referenced resource already exists or not. The following situations are possible:
  • If the referenced resource does not exist, it is necessary to check if the user has the right to create instances of the corresponding type.
  • Ff the referenced resource does exist, it is necessary to check if the user has the right to update instances of the corresponding type.
The central management of access rights to each type and its attributes is located within the hybris Management Console:

The type based web services security configuration, managed in hMC is divided into two basic steps:
  1. Resource (type) level security
  2. Attribute level security, which also contains the type level security
For resource level it is possible to set Read, Change, Create and Delete rights. For attribute level security, only the Read and Change rights may be set.
If a user does not have the right to a specified operation on a requested resource, the following message appears:
You do not have permission to request this resource (resource name) using HTTP_method method.
Type level security is included in attribute level security checking. If any operation is not allowed for the specified attribute type, the user receives the message:
You do not have permission to CRUD operation: DTOclassName dto.
If a user has no Read rights for a certain attribute of the requested resource, this attribute is excluded from the response. If a user tries to update an attribute, which he is not allowed to change, the attribute is not modified and the HTTP status code Forbidden (403) is sent with the message:
You do not have permission to change list_of_attributes attributes of the DTOclassName dto.
If a user has Change right to some, but not all attributes of a resource and tries to update all of them, none of them are updated. In this case the user should remove not allowed attributes from the request.
If a user requests a resource and has Read access to some, but not all attributes of the requested resource, then those unavailable attributes are not included in the XML response.

Examples


User A has all access rights.
MyLanguage resource extends Language resource.
Type Attribute Read Change Create Delete
Language  
MyLanguage  

Method URL Result
GET /languages List of all Language instances, but without MyLanguage instances.
GET /languages/de Details of de language.
GET /mylanguages/myde HTTP status code Forbidden (403) informing that the user does not have sufficient rights to execute the requested operation.
PUT/POST /languages/de If the referenced de language exists, it is updated. Otherwise it is created.
DELETE /languages/de Delete de language.
User B has only Read right.
Type Attribute Read Change Create Delete
Language  

Method URL Result
PUT/POST /languages/de HTTP status code Forbidden (403) informing that the user does not have sufficient rights to execute the requested operation.
DELETE /languages/de HTTP status code Forbidden (403) informing that the user does not have sufficient rights to execute the requested operation.
User C is not allowed to update Language resource.
Type Attribute Read Change Create Delete
Language  

Method URL Result
PUT/POST /languages/de If the referenced language does no exist, it is created.
If the referenced language exists, the request results in HTTP status code Forbidden (403), informing that the user does not have sufficient rights to execute update operation.
User D has no rights for Language resource.
Type Attribute Read Change Create Delete
Language  

Method URL Result
GET /languages Empty list, as user D has no Read access to language instances.
GET /languages/de HTTP status code Forbidden (403) informing that the user does not have sufficient rights to execute the requested operation.
PUT/POST /languages/de HTTP status code Forbidden (403) informing that the user does not have sufficient rights to execute the requested operation.
DELETE /languages/de HTTP status code Forbidden (403) informing that the user does not have sufficient rights to execute the requested operation.
User A has all rights.
Type Attribute Read Change Create Delete
Language  
  isocode    
  name    

Method URL Result
GET /languages/de
<language>
  <isocode>de</isocode>
   <name>German</name>
</language>
User B has no rights to read or update the name attribute.
Type Attribute Read Change Create Delete
Language  
  isocode    
  name    

Method URL Result
PUT /languages/de Body of the request:
<language>
   <isocode>de</isocode>
</language>
PUT /languages/fr Body of the request:
<language>
   <isocode>fr</isocode>
   <name>French</name>
</language>

Results in HTTP status code Forbidden (403) informing that the user has no rights to change the name attribute.

Property File Security Strategy

This strategy is based on the configuration project.properties file in the platformwebservices extension. It is a resource level security strategy.

Security Access Roles

Secured resources are given by:
  1. key, which addresses single classes or whole packages, similar to log4j
  2. value, which is a group or role followed by a list of allowed HTTP methods
Leave value of this property empty or set one or more groups.
Examples:
  • Global options. The following settings allow specified groups access to all resources, however anonymous group may just Read them:
    restjersey.security.de=admingroup[GET,PUT,DELETE,POST]
    restjersey.security.de.hybris.platform.restjersey.resources=anonymous[GET]
  • The following settings assign groups to specified resources:
    restjersey.security.de.hybris.platform.restjersey.resources.CatalogsResource=
    anonymous[GET]; customergroup[GET]
    restjersey.security.de.hybris.platform.restjersey.resources.CatalogResource=
    anonymous[GET]; customergroup[GET]

Examples of Different Configurations

All use cases for admingroup are presented in the simple example. Results are retrieved using GET method.
Below different available configurations are presented:
  • restjersey.security.de.hybris.platform.restjersey.resources=
    admingroup[GET,PUT,DELETE,POST]
    restjersey.security.de.hybris.platform.restjersey.resources.CatalogsResource=
    restjersey.security.de.hybris.platform.restjersey.resources.CatalogResource=
    or
    restjersey.security.de.hybris.platform.restjersey.resources=
    admingroup[GET,PUT,DELETE,POST]
    or
    restjersey.security.de.hybris.platform.restjersey.resources=
    restjersey.security.de.hybris.platform.restjersey.resources.CatalogsResource=
    admingroup[GET,PUT,DELETE,POST]
    restjersey.security.de.hybris.platform.restjersey.resources.CatalogResource=
    admingroup[GET,PUT,DELETE,POST]
    or
    restjersey.security.de.hybris.platform.restjersey.resources.CatalogsResource=
    admingroup[GET,PUT,DELETE,POST]
    restjersey.security.de.hybris.platform.restjersey.resources.CatalogResource=
    admingroup[GET,PUT,DELETE,POST]
Request Response
http://localhost:9001/ws410/rest/catalogs/ Retrieves all catalogs
http://localhost:9001/ws410/rest/catalogs/hwcatalog/ Retrieve the specified catalog.
  • restjersey.security.de.hybris.platform.restjersey.resources=
    restjersey.security.de.hybris.platform.restjersey.resources.CatalogsResource=
    admingroup[GET,PUT,DELETE,POST]
    restjersey.security.de.hybris.platform.restjersey.resources.CatalogResource=
    employeegroup[GET]
Request Response
http://localhost:9001/ws410/rest/catalogs/ Retrieves all catalogs
http://localhost:9001/ws410/rest/catalogs/hwcatalog/ HTTP status FORBIDDEN with the message:
You do not have permission to request this resource (CatalogResource) using GET method..
  • restjersey.security.de.hybris.platform.restjersey.resources=
    restjersey.security.de.hybris.platform.restjersey.resources.CatalogsResource=
    restjersey.security.de.hybris.platform.restjersey.resources.CatalogResource=
    admingroup[GET,PUT,DELETE,POST]
    or
    restjersey.security.de.hybris.platform.restjersey.resources.CatalogResource=
    admingroup[GET,PUT,DELETE,POST]
Request Response
http://localhost:9001/ws410/rest/catalogs/ HTTP status FORBIDDEN with the message:
The (CatalogsResource) resource is not available for any user.
http://localhost:9001/ws410/rest/catalogs/hwcatalog/ Retrieve the specified catalog.
  • restjersey.security.de.hybris.platform.restjersey.resources=
    restjersey.security.de.hybris.platform.restjersey.resources.CatalogsResource=
    restjersey.security.de.hybris.platform.restjersey.resources.CatalogResource=
    or any properties.
Request Response
http://localhost:9001/ws410/rest/catalogs/ HTTP status FORBIDDEN with the message:
The (CatalogsResource) resource is not available for any user.
http://localhost:9001/ws410/rest/catalogs/hwcatalog/ HTTP status FORBIDDEN with the message:
The (CatalogsResource) resource is not available for any user.

Custom Security Strategy

It is possible for users to create their own security strategies by:
  • Implementing the SecurityStrategy interface:
public interface SecurityStrategy
{
   boolean isResourceOperationAllowed(final RestResource resource, final String operation);
   boolean isResourceCommandAllowed(final RestResource resource, final String command);
   boolean isDtoOperationAllowed(final Class<?> objectClass, final String operation);
    boolean isAttributeOperationAllowed(final Class<?> attrObjectClass, final String attrQualifier, final String attrOperation);
}
  • Registering the bean in platformwebservices-web-spring.xml:
platformwebservices-web-spring.xml
<beans>
   <!-- ... --->
   <bean id="securityStrategy" class="de.hybris.platform.webservices.CustomSecurityStrategy" scope="prototype" parent="abstractSecurityStrategy"/>
   <!-- ... --->
</beans>

Security Specific Web Services Resources


Checking credentials:

A request for a validation of the provided credentials:
http://localhost:9001/ws410/rest/login If the login process is:
  • Valid: Status is 200 OK
  • Invalid: Status is 401 Unauthorized

Lost Password Scenario

If the restjersey.security property is set to enabled, only RetrievePasswordResource is available for users who lost their passwords.
They have to access to http://localhost:9001/ws410/rest/retrievepassword resource without using basic authentication.
For example, editor user forgets his password. He uses GET method and the following URL path: http://localhost:9001/ws410/rest/retrievepassword/editor. If the user does not have access to PasswordQuestion and AnswerQuestion it is not possible to retrieve password. In other cases, user can retrieve password.
The GET method returns response with PasswordQuestion.
Now, user uses PUT method and the same URL path:
http://localhost:9001/ws410/rest/retrievepassword/editor He places PasswordAnswer within body request and executes request.
    <passwordAnswer>YOUR ANSWER</passwordAnswer>
</user>
If the PasswordAnswer is correct, user retrieves a new password in raw format. In database the password is encoded into a md5 hash.

Change Password Scenario

Use http://localhost:9001/ws410/rest/changepassword, PUT method and the following HTTP body:
<changepassword>
   <newpassword>NO EMPTY</newpassword>
</changepassword>
If you log in correctly, the new password is set.

Security Architecture Configuration

The following configuration files:
  • web.xml
  • platformwebservices-web-spring.xml
are located within the platformwebservices extension and are used to specify and wire up the security framework.

Configuration of web.xml File

web.xml
<web-app>
 <!-- ... -->
 
 <filter>
  <filter-name>springSecurityFilterChain</filter-name>
  <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
 </filter>
 
 <filter-mapping>
  <filter-name>springSecurityFilterChain</filter-name>
  <url-pattern>/*</url-pattern>
 </filter-mapping>
 
 <!-- ... -->
</web-app>
This provides a hook into the Spring Security web infrastructure. DelegatingFilterProxy is a Spring Framework class which delegates to a filter implementation which is defined as a Spring bean in an application context. In this case, the bean is named springSecurityFilterChain, which is an internal infrastructure bean created by the namespace to handle web security. Note that you should not use this bean name yourself.
The next step is configuring the application context file.

Configuration of Spring File


Web security services are configured using security elements.
platformwebservices-web-spring.xml
    <!-- ... -->
 
    <security:http>
        <security:intercept-url  pattern="/**" />
        <security:http-basic />
        <security:logout />
        <security:remember-me />
    </security:http>
 
    <security:authentication-manager  alias="mainAuthenticationManager">
      <security:authentication-provider user-service-ref="userDetailsService">
        <security:password-encoder ref="hybrisPasswordValidator">
            <!-- SaltedMD5PasswordEncoder is used -->
            <!-- <security:salt-source user-property="whatever"/> -->
        </security:password-encoder>
      </security:authentication-provider>
    </security:authentication-manager>
 
    <bean id="userDetailsService"
    class="de.hybris.platform.webservices.security.impl.HybrisUserDetailsService"
    scope="prototype">
        <property name="userService" ref="userService"/>
        <property name="modelService" ref="modelService"/>
        <property name="encryptionInfo" ref="encryptionInfo"/>
    </bean>
 
    <bean id="hybrisPasswordValidator"
    class="de.hybris.platform.webservices.security.impl.HybrisPasswordValidator">
        <property name="encryptionInfo" ref="encryptionInfo"/>
    </bean>
 
    <bean id="encryptionInfo"
    class="de.hybris.platform.webservices.security.impl.EncryptionInfo"/>
 
    <!-- ... -->
</beans>
  • http configuration:
    This element enables web security and denotes that all URLs within our web services should be secured. The WebService API uses basic authentication which is used to prompt for a login when a user attempts to access a protected resource.
  • authentication-provider and password-encoder:
    The hybris web services framework authenticates users against hMC members. We have own implementation of Spring Security UserDetailsService, within which by currently authenticated username it passes the user password and granted authorities (hmc usergroups) to the password validation procedure. Some users have encrypted password (Salted MD5) and others not. Therefore we provide the hybrisPasswordValidator, which takes appropriate care of password comparison.

Step by Step to create web services in Hybris e-commerce suit | E-commerce domain ERP

Create a new extension

We will create a new extension similar to the one already covered in Trail+~New+Extension, to expose our webservice. However we won't define any new Items in the data model.
  1. Open the Ant view in Eclipse and invoke the platform's task extgen
    1. Enter the name "cuppywstrail" for the extension WHICH MUST BE ONE WORD IN LOWER CASE
    2. Enter the package prefix "de.hybris.platform.cuppywstrail" also WHICH MUST BE ALL IN LOWER CASE
    3. Select yempty for the extension template
  2. The Ant script will now create a skeleton extension for you in <YOURPATH>/bin/custom/cuppywstrail but this is not yet imported into Eclipse
  3. Import the generated extension into your Eclipse environment
    1. Right-click in package explorer and select Import
    2. Select General|Existing Projects into Workspace and browse to the new extension <YOURPATH>/bin/custom/cuppywstrail
    3. Remember to ensure that the "Copy projects into workspace" check box is not checked before clicking on the Finish button
    4. You should now see the extension in your Eclipse Package Explorer
    5. You can ignore any build errors currently being reported as the configuration is not yet complete
  4. Append the new extension to config/localextensions.xml file in the config project:
    config/localextensions.xml
    ...
       <extension dir="${HYBRIS_BIN_DIR}/custom/cuppywstrail"/>
    </extensions>
  5. Run Ant's all task from Eclipse
    1. This will generate the Java Source files representing the Data Entities ("items") in all the -items.xml files (see buildprocessessentials for an overview)
    2. See the output in Eclipse's console view and wait for completion
  6. Load the generated files into Eclipse and build
    1. Select all top-level projects in the Package Explorer, right-click and select refresh - this will reload all generated files into Eclipse
    2. Ensure that in Eclipse the option Project|Build Automatically is checked
    3. Eclipse will now start to build your project
  7. Explore your new extension's structure
  8. Run hybris and ensure your new extension is accessible
    1. Start hybris (by executing hybrisserver.bat or ./hybrisserver.sh from the command line in the directory <YOURPATH>/bin/platform)
    2. Open http://localhost:9001/cuppywstrail and verify that you get a simple message with the extension name, "cuppywstrail" and "welcome to my extension" below it.
    3. You can also verify that your extension is running by opening http://localhost:9001 under Platform/Extensions. You should see "cuppywstrail" in the list.

      This tells you that the extension is now running

Generated Classes

As discussed in Trail+~+New+Data+Model, the hybris build framework generates a number of java source files for each item type defined in items.xml. This includes:
  • models created for the service layer (business logic should go there)
  • classes created to support CRUD logic via RESTful URIs
  • low-level Jalo classes which we won't discuss as their use is discouraged
We will now explore the classes generated for supporting the CRUD cycle through RESTful webservice calls.
A Stadium Data Entity is defined in cuppytrail's items.xml file. As described in Trail+~+New+Data+Model, we should expect to see several files generated for this entity including DTOs and Resources. These were created for the cuppytrail extension where we defined the Item type Stadium. It is important to note that they are actually created in the platform project. To verify that these classes exist, search for them in Eclipse, using the Navigate Menu / Open Type, or the shortcut key Ctrl-Shift-T. If you search for "StadiumDTO", for example, you will see that it has been created in the platform project, in the package de/hybris/platform/cuppytrail/dto which is located in the web/gensrc folder.
  • Since DTOs and Resources are located in the platform's web folder, they are in the web-layer of the platform. If we try and reference them in code which is in our web layer, i.e. the web folder of the cuppywstrail extension, they will not be in the build path. Web-layers within separate extensions are not able to see each other's classes. Eclipse handles this by dynamically applying a build path to the entire workspace, but when you build your project with Ant, any references you make, for example to the data transfer object for Stadium, will result in a build failure. Individual web applications do not share the same class loaders which matches the final deployment scenario. However this usually turns out to be quite inconvenient for developing and deploying.
  • Next we will see how to solve this problem.

Webservice nature

To allow the cuppywstrail extension to expose the Stadium item type to a web service client, we need to do two things:
First, we need make the cuppywstrail extension visible to the cuppytrail extension where the Stadium class is defined.
Add the following tags inside the extension tag in extensioninfo.xml of the cuppywstrail project.
extensioninfo.xml
<requires-extension name="cuppy"/>
<requires-extension name="cuppytrail"/>
Next we need include the generated DTOs and Resources from cuppytrail in our classpath.
This is done by assigning cuppywstrail a "webservice nature which generates the file core-webservices.jar containing the platform's generated DTOs and Resources in cuppywstrail/webroot/WEB-INF/lib. As the folder is included in cuppywstrail's classpath, we can now reference and extend the DTOs and Resources. A new web.xml file will be created, as well as the file cuppywstrail/resources/cuppywstrail-web-spring.xml redirecting requests to our webservice request handler.

  • In Eclipse, drag the file cuppywstrail/build.xml into your Ant View.
  • Select the cuppywstrail target webservice_nature
  • Clean your extension by running your extension's ant clean (Note this is not the platform clean's ant task)
  • Finally run the platform all ant task
The DTO class will be extended later to demonstrate how to customise DTO and Resource behaviour.
Let's summarize the previous steps:
  • we created a new extension referencing the cuppytrail extension
  • classes in this extension were not able to access the generated DTOs and Resources because they reside in the platform's web-layer
  • we assigned a webservice nature to cuppywstrail and rebuilt the system resulting in a jar (core-webservices.jar) with DTOs and resources from the cuppytrail extension to be copied to cuppywstrail

Webservice support for the Stadium Data Entity

We have now we have enabled web service support for the Stadium Data Entity.

Perform standard CRUD operations via RESTful URIs - Attempt 1

A regular web browser is not suitable for testing our RESTful calls as we also need to be able to enter a client's username and password via a pre-emptive BASIC protocol which is not supported by a regular browser. To this end we will use a RESTful webservices client to test the web-services exposure of our Stadium object. Note that as our extension now has a web services nature, the default "welcome to my extension" message will no longer be returned from http://localhost:9001/cuppywstrail. In fact, you will get a 404 error saying "The requested resource (/cuppywstrail/) is not available.".
  1. Start hybris
  2. Start a RESTful Client
    1. Go to http://code.google.com/p/rest-client/downloads/list and download the REST Client
    2. Download the latest RESTClient GUI release
    3. Run the RESTClient and open Authentication tab, set the Authentication Mode to Basic and Enter “admin” and “nimda” as credentials
  3. Make a RESTful request to view a list of the Stadium
    1. Type and run the URI request http://localhost:9001/cuppywstrail/rest/stadiums in the RESTful Client
    2. You will (probably) receive a response stating that you are not allowed to view this resource

      We will address this issue now.

Modify the RESTful access rights

As discussed in WebService API - Security Architecture users must be a member of the webservicegroup to be able to access resource via REST which is not done by default.
To verify that this user group is set up for you:
  • Open the hMC and see if the usergroup webservicegroup is listed; if not:
    • Create the webservicegroup:
    • Add the user group AdminGroup to the user group webservicegroup:

Perform standard CRUD operations via RESTful URIs - Attempt 2

  1. With a new user group webservicegroup defined as described in WebService API - Security Architecture and the admingroup added to it, our RESTful request with user name admin should now succeed.

    The request returns an XML representation of the Stadiums that are currently in the system.
    <?xml version="1.0" encoding="UTF-8"?>
        <stadium code="Wembley" pk="8796093065099" uri="http://localhost:9001/cuppytrail/rest/stadiums/Wembley"/>
        <stadium code="Allianz" pk="8796093097867" uri="http://localhost:9001/cuppytrail/rest/stadiums/Allianz"/>
    </stadiums>
  2. Enter the http://localhost:9001/cuppywstrail/rest/stadiums/Wembley to obtain an XML representation of the Wembley Stadium.
    <?xml version="1.0" encoding="UTF-8"?>
    <stadium code="Wembley" pk="8796093065099" uri="http://localhost:9001/cuppytrail/rest/stadiums/Wembley"
        <comments/>
        <creationtime>2010-11-08T16:30:40+01:00</creationtime>
        <modifiedtime>2010-11-08T16:30:40+01:00</modifiedtime>
        <capacity>123456</capacity>
        <matches/>
        <stadiumType>openair</stadiumType>
    </stadium>
  3. Add some matches to Wembley Stadium in the hMC.
  4. Rerun the query http://localhost:9001/cuppytrail/rest/stadiums/Wembley and you will see the matches you just added.
    <?xml version="1.0" encoding="UTF-8"?>
    <stadium code="Wembley" pk="8796093065099" uri="http://localhost:9001/cuppytrail/rest/stadiums/Wembley"
        <comments/>
        <creationtime>2010-11-08T16:30:40+01:00</creationtime>
        <modifiedtime>2010-11-10T13:00:40+01:00</modifiedtime>
        <capacity>123456</capacity>
        <matches>
            <match id="1" pk="8796093055137" uri="http://localhost:9001/cuppytrail/rest/stadiums/Wembley/matchs/8796093055137">
                <matchday>0</matchday>
            </match>
            <match id="4" pk="8796093153441" uri="http://localhost:9001/cuppytrail/rest/stadiums/Wembley/matchs/8796093153441">
                <matchday>0</matchday>
            </match>
        </matches>
        <stadiumType>openair</stadiumType>
    </stadium>
  5. Notice that the URI attributes in the XML are also URIs pointing to resources. This is a standard RESTful practice in which RESTful responses may contain URIs that in turn can be interrogated.
    Tip
    You may have noticed that responses are by default in XML format. hybris optionally accepts and sends responses in JSON format. To change the default, all you have to do is to set the headers for the request and response:
    Header Entry Value Result
    Accept application/xml Response is sent in XML format
    Accept application/json Response is sent in JSON format
    Content-type application/xml Body in request is expected to be in XML format
    Content-type application/json Body in request is expected to be in JSON format

Modify a Stadium via REST

We will now send a RESTful PUT request to modify the capacity of the wembley stadium.

Custom DTOs and Custom Resources

Earlier we wrote code in your own extension that references the DTOs and Resource generated in the Platform.  Default DTO and Resource implementations may be customized by extending the respective classes.  See Customizing Resources and DTOs for a discussion on how to do this.

Triggering Commands via REST

In addition to performing CRUD on Data via REST, hybris allows you to easily create commands that can then be triggered via RESTful calls. See REST Commands Tutorial for a discussion.

Summary

In this step you should have learned
  • what classes are generated for supporting RESTful CRUD operations on your Data Entities
  • what the webservice_nature target is and why it is needed
  • how to perform RESTful CRUD operations on your Data Entities
  • how to extend DTOs and Resources
  • how to write virtual DTOs

Linux and Unix Usefull command | How to Find Runtime of a Process in UNIX and Linux

 So you checked your process is running in Linux operating system and it's running find, by using ps command. But now you want to know, from how long process is running, What is start date of that process etc. Unfortunately ps command in Linux or any UNIX based operating system doesn't provide that information. But as said, UNIX has commands for everything, there is a nice UNIX tip, which you can use to check from how long a process is running. It’s been a long time, I have posted any UNIX or Linux command tutorial, after sharing some UNIX productivity tips . So I thought to share this nice little tip about finding runtime of a process in UNIX based systems e.g. Linux and Solaris. In this UNIX command tutorial, we will see step by step guide to find, since when a particular process is running in a server.


Commands to find Runtime of a process in UNIX
UNIX command to find runtime of a process in LinuxAs I said, there is no single command, which can tell us that from how long a process is running. We need to combine multiple commands, and our knowledge of UNIX based systems to find uptime of a process.

Step 1 : Find process id by using ps command e.g.

$ ps -ef | grep java
user 22031 22029   0   Jan 29 ?          24:53 java -Xms512M -Xmx512 Server

here 22031 is process id or PID. By the way if there are more than one Java process running in your server, than you might want to use a more specific grep command to find PID. Anyway, once you found PID, you can look into proc directory for that process and check creation date, that's the time when your process was started. By looking that timestamp you can easily find from how long your process is running in Linux. In order to check timestamp of any process id proc directory, you can use following ls UNIX command with option -ld as shown below :

$ ls -ld /proc/20317
dr-x--x--x   5 user     group           832 Jan 22 13:09 /proc/22031

Here process with PID 22031 has been running from Jan 22, 13:09.

That's all on How to find uptime for a process in Java. Yes, it's similar to what uptime command return for a server. I really like this UNIX tips, as it's a great tool to find from how long a process is running in UNIX or Linux