Wednesday, October 11, 2017

Swagger Documentation Setup Configuration for ATG JAX-RS REST service

Swagger Documentation Setup Configuration  for ATG JAX-RS REST service ATG 11.3 by default comes with the required Swagger librarie... thumbnail 1 summary


Swagger Documentation Setup Configuration  for ATG JAX-RS REST service


ATG 11.3 by default comes with the required Swagger libraries in the installation package.

Swagger produces documentation in JSON or YAML format, and can be accessed through the URL in the format of

In this post we will see the setup and configuration of Swagger UI .

Step 1
Clone or download the zip file from GitHub repository.

Step 2
Extract the package and copy the dist folder to your server. [json-server/Apache Tomcat/JBoss/Etc.,]

Step 3
                Load the url http://localhost:8181/dist [8181 is my server port]
                
You can see the default JSON specification of http://petstore.swagger.io/v2/swagger.json.

Step 4
                Provide the ATG JSON url in the Swagger UI test box in the top and hit Explore button. You can  see the error says it fails.
                Unfortunately, that is a built in security feature on all browsers. Swagger-Ui uses ajax to fetch files, and that can only be accomplished if you run it on a server.
               
Step 5
                You can open your chrome browser with the disable-web-security option .
Open Windows->Run-> chrome.exe --user-data-dir="C:/Chrome dev session" --disable-web-security
Chrome will be opened and load the swagger UI url and hit it again. You can see the below shows the end point details.


Step 6
                Verify the end point details.




Thanks.

ATG Oracle Commerce 11.3 JAX-RS Handling Exceptions – RestException

ATG Oracle Commerce 11.3 JAX-RS Handling Exceptions – RestException       ATG JAX-RS REST Endpoint resource exceptions are handled... thumbnail 1 summary


ATG Oracle Commerce 11.3 JAX-RS Handling Exceptions – RestException


      ATG JAX-RS REST Endpoint resource exceptions are handled as a RestException. RestException  objects instance be created using utility methods in RestUtils. This allows endpoint to specify a response status code with an error . 

     The RestExceptionMapper instance of the Jersey ExceptionMapper builds a response from the RestException that is returned to the client.  Exceptions are automatically rendered by the framework output producer into the correct format before returning back to the client.

    When we build a RestException, we need to set HTTP response codes, error messages, debug information and, optionally, error codes that are returned from your endpoint method.

To understand the custom error message setting we will take the below OOTB  Resource

atg.commerce.order.restresources.CartRestResource

cancelCart() method will throw Internal server error when current order is null.

RestException object created by providing error messages and status code. The error messages are loaded from bundle.



@DELETE
       @Endpoint(id = "/cart/DELETE", isSingular = true, filterId = "cart-Default")
       @ApiOperation("Delete the current order from the cart and replace with an empty                 order.")
       public RepresentationModel cancelCart() throws RestException, CommerceException, ServletException {
              OrderHolder shoppingCart = this.getShoppingCart();
              Order currentOrder = shoppingCart.getCurrent();
              if (null == currentOrder) {
              String executor1=ResourceUtils.getUserMsgResource("nullOrderHolder"
                        "atg.commerce.order.OrderResources",sResourceBundle);
               throw new RestException(Status.INTERNAL_SERVER_ERROR.getStatusCode(),executor1);
              } else {
                if (this.isLoggingDebug()) {
                   this.logDebug("Initiating cancelCart for : " + currentOrder.getId());
                     }

                     .......


           return this.getRepresentationModelBuilder(shoppingCart.getCurrent()).build();
              }
       }


Resource bundle  

Error Response from postman app.


If we need to customize our error response then we need to customize the component /atg/dynamo/service/jaxrs/RestExceptionMapper ‘s method


//atg.service.jaxrs.RestExceptionMapper
public Response toResponse(RestException pException) {
              return JSONErrorResponseBuilder.buildResponse(pException);
       }


Thanks.

Sunday, October 8, 2017

Create Configure Deploy new JAX-RS ATG Module in Oracle ATG Commerce 11.3

Create Configure Deploy new JAX-RS ATG Module in Oracle ATG Commerce 11.3 ATG Module structure remains same where we need to create new ... thumbnail 1 summary
Create Configure Deploy new JAX-RS ATG Module in Oracle ATG Commerce 11.3

ATG Module structure remains same where we need to create new configuration files for JAX-RS service.

Final JAX-RS Module will contains the following folder structure and files.




We will see all major components and configurations on this module.

1    1.Web.xml

We will start with Application deployment descriptor file(web.xml). Here we are going to add Jersey servlet configuration in addition with our NucleusServlet.

If you already deployed the atg-jaxrspublic-version1.war into your EAR then simply copy the web.xml from there and paste into your new module.  [Refer here to deploy atg-jaxrspublic-version1.war]
·             Change the context-root to public/service [You can give the value as per the needs]
·             You can see the Jersey servlet configuration to load jaxrs servlet classes and other swagger related classes.




1    2. JerseyClassLoaderService.properties

This component is registers the classpathFiles files and childFirstPrefixes.

#JerseyClassLoaderService.properties
childFirstPrefixes+=\
              atg/service/jaxrs/security,\
              atg/userprofiling/restresources

classpathFiles+=\
       {appModuleResource?moduleID=JAX-RS.REST&resourceURI=lib/classes.jar}

[Note: Instead of classes.jar you can create a jar file with jersey-classloader.jar and that can be specified here]


3. RestResourceRegistry.properties

The RestResourceRegistry   register a Nucleus REST resource with Jersey. [This is similar to /atg/rest/registry/ActorChainRestRegistry.properties in MVC REST]

#RestResourceRegistry.properties

nucleusRestResources+=\
/com/userprofiling/UserLookupByEmailResource

1    4. PayloadSchemaRegistry.properties

This component provides the path to the payloadSchema.xml.
Payload schema framework provides validation framework to handles validation and updating target dynamic beans

definitionFile=atg/dynamo/service/payloadschema/payloadSchema.xml
[This is similar to Bean filtering in MVC REST]

2.      payloadSchema.xml
This file defines the actual payload schema tags. Each schema tag represents a java-bean class or a repository item type and specifies the entity that validation input represents.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE payload-schemas PUBLIC "-//Art Technology Group, Inc.//Payload Schema Specifier
Specifier 1.0//EN" "http://www.atg.com/dtds/payloadschema/payloadschema_1.0.dtd">
<payload-schemas>

  <!--***********************************************************************-->
  <!--    The filters defined below should be kept in alphabetical order.    -->
  <!--***********************************************************************-->

  <!--*************************************************-->
  <!--                   RESPONSE VOs  for filterId attribute in service  operation  -->
  <!--*************************************************-->
  <schema id="xxx-id-validate" include-all-simple="true">
    <untyped-bean/>
    <property name="email" required="true">
      <validator-instance class="EmailValidator"/>
    </property>

  </schema>
  </payload-schemas>

<!-- @version $Id: //product/DCS/version/11.3/templates/DCS/config/atg/dynamo/service/payloadschema/payloadSchema.xml#4 $$Change: 1392901 $ -->


Once you assemble the EAR files with this module you can access your custom service. We will see how to create a new custom service and end points in up coming posts.

Thanks.

Saturday, October 7, 2017

ATG 11.3 JAX-RS API – DropletInvoker

ATG 11.3 JAX-RS API – DropletInvoker The DropletInvoker is used to invoke droplets and returns output data for each oparam. The drop... thumbnail 1 summary

ATG 11.3 JAX-RS API – DropletInvoker


The DropletInvoker is used to invoke droplets and returns output data for each oparam. The droplet result gets filled up for each output of oparam using the call back mechanism.
  •  Droplet Invoker object can be created using the constructor as below


              DropletInvoker dropletInvoker = new  DropletInvoker(“path to your droplet”);
             
  •  Adding inputs to the invoker [addInput(String pKey, Object pObject)]


               dropletInvoker.addInput("pParamName1", pParamVal1);
               dropletInvoker.addInput("pParamName2", pParamVal2);
               dropletInvoker.addInput("pParamName3", pParamVal3);
  •  Adding open parameter to the invoker
               OParam oParamOutput = dropletInvoker.addOParam("output");

  • Adding output parameter to the invoker

              oParamOutput.addOutput("outputObj", " outputObj ");

  •  Executing the droplet

             dropletInvoker.invoke();

  • Getting the response from the execution


             OParam oParamOutputResponse = dropletInvoker.getOParam("output");

           if(oParamOutputResponse!=null){
                                Object responseObj = oParamOutputResponse.getOutput("outputObj ");
                                  …
                     }



Example code to invoke droplet to get the user details based on email id.

@GET
       ...
       public RepresentationModel getUser(@QueryParam("email") String email,@QueryParam("token") String authtoken) throws RestException {
              ...
              RepresentationModel.Builder builder = null;
              //Adds Input and output parameter to RestProfileDisplayWarningsDroplet
              DropletInvoker dropletInvoker = new  DropletInvoker("/com/../YourUserLookupDroplet");
              dropletInvoker.addInput("token", token);
              dropletInvoker.addInput("email", email);
              OParam oParamOutput = dropletInvoker.addOParam("output");
              oParamOutput.addOutput("users", "users");
              dropletInvoker.invoke();
              OParam oParamOutputResponse = dropletInvoker.getOParam("output");
              List usersRepItem = null;
              ResponsePayload responsePayload = getResponsePayload(); //Your custom Response Payload
             
              if(oParamOutputResponse!=null){
                     Output users = oParamOutputResponse.getOutput("users");
                     usersRepItem = (List)users.getObject();
                     RepositoryItem userItem = (RepositoryItem)usersRepItem.get(0);
                     builder = getRepresentationModelProfileBuilder(responsePayload, userItem);
              }
               return builder.build();
  }



API Ref doc : http://docs.oracle.com/cd/E69533_01/Platform.11-3/apidoc/atg/service/jaxrs/DropletInvoker.html

ATG 11.3 JAX-RS API – FormHandlerExecutor

ATG 11.3 JAX-RS API – FormHandlerExecutor FormHandlerExecutor class invokes the form handler based on handle method provided in con... thumbnail 1 summary
ATG 11.3 JAX-RS API – FormHandlerExecutor


FormHandlerExecutor class invokes the form handler based on handle method provided in constructor. Forwards are disabled and the request and response are wrapped to capture any redirect response in the result instead.

Executor object can be created using the constructor as below,

FormHandlerExecutor executor = new FormHandlerExecutor(pFormHandlerPath,pHandleMethod);

Adding inputs to the executor.

executor.addInput(pParamName,pParamValue);

Execute the formhandler using

executor.execute();

As well in ootb have a method to process the results.

executor.processFormHandlerResult(executor.execute());

This processFormHandlerResult method process the results and if it has any form exception(s) it will create a DropletException and add it to the error stack.

Example code for formHandlerExecutor from CurrentUserRestResource class

@POST
    @Path("/login")
    ...
    public Map<String, String> login(...) throws RestException ... {
       ...
       try {
          ...
          FormHandlerExecutor executor = new FormHandlerExecutor(this.getProfileFormHandlerPath(), this.getLoginHandleMethod());
          this.addInputsForLogin(executor, pLogin, pPassword);
          executor.processFormHandlerResult(e.execute());
          ...

          HashMap statusCode1 = new HashMap();
          ...
          ...
          return statusCode;
       } catch (...) {
          ...
       }
    }
       protected void addInputsForLogin(FormHandlerExecutor pExecutor, String pLogin, String pPassword)
                     throws ServletException {

              pExecutor.addInput("value.login", pLogin);
              pExecutor.addInput("value.password", pPassword);
         }




Thanks.