Wednesday, 18 July 2018

ATG 11.3 JAXRS information


1)Configuration as part of web.xml

<servlet>
    <servlet-name>Jersey</servlet-name>
    <servlet-class>atg.service.jaxrs.JerseyServletWrapper</servlet-class>
    <init-param>
        <param-name>jersey.config.server.provider.packages</param-name>
        <param-value>com.xxx.yyy.resource.abc</param-value>  (might be not required)
    </init-param>
    <init-param>
      <param-name>atg.service.jaxrs.JerseyServletWrapper.servletClasses</param-name>
      <param-value>org.glassfish.jersey.servlet.ServletContainer,atg.service.swagger.SwaggerBootstrap</param-value>
    </init-param>
    <!-- Params for JerseyServletWrapper servlet  -->
    <init-param>
      <param-name>javax.ws.rs.Application</param-name>
      <param-value>atg.service.jaxrs.JAXRSApplication</param-value>
    </init-param>
    <init-param>
      <param-name>jersey.config.server.provider.classnames</param-name>
      <param-value>atg.service.swagger.SwaggerApiListingResource,io.swagger.jaxrs.listing.SwaggerSerializers</param-value>
    </init-param>
    <init-param>
   <!--  Params for JAXRSApplication  -->
      <param-name>atg.service.jaxrs.JAXRSApplication.resourceRegistryPath</param-name>
      <param-value>/atg/dynamo/service/jaxrs/RestResourceRegistry</param-value>
    </init-param>
    <init-param>
      <param-name>atg.service.jaxrs.JAXRSApplication.payloadSchemaRegistryPath</param-name>
      <param-value>/atg/dynamo/service/payloadschema/PayloadSchemaRegistry</param-value>
    </init-param>
    <init-param>
    <!-- Params for SwaggerBootstrap servlet  -->
      <param-name>atg.service.swagger.SwaggerBootstrap.bootstrapService</param-name>
      <param-value>/atg/dynamo/service/swagger/SwaggerBootstrapService</param-value>
    </init-param>
    <load-on-startup>3</load-on-startup>
    <async-supported>true</async-supported>
  </servlet>
  <servlet-mapping>
    <servlet-name>Jersey</servlet-name>
    <url-pattern>/services/*</url-pattern>
  </servlet-mapping>



The following are components


1) /atg/dynamo/service/payloadschema/PayloadSchemaRegistry.properties
   definitionFile=atg/dynamo/service/payloadschema/payloadSchema.xml

2)atg/dynamo/service/payloadschema/payloadSchema.xml


3) atg/dynamo/service/jaxrs/JerseyClassLoaderService.properties
   childFirstPrefixes+=\
                                   com/xxxpath/resource,\
                                   com/yypath/reosurce2
classpathFiles+=\

The childFirstPrefixes should have the paths of the all services.


4)atg/dynamo/service/jaxrs/RestExceptionMapper.properties
    $class=com.Lxx.gyy.p1.p2.xxxExceptionMapper
$classloader=/atg/dynamo/service/jaxrs/JerseyClassLoaderService


5) /atg/dynamo/service/jaxrs/RestResourceRegistry.properties

     nucleusRestResources+=\
                         /com/xxxpath/yyyyService,\
                            /come/zzzpath/absService

The RestResourceRegistry can also register a Nucleus REST resource with Jersey. To register a Nucleus component, you must add it to the RestResourceRegistry.properties file.


The End point service should be as follows.

yyyyService.properties
$class=com.xxxpath.resource.XXXService
$classloader=/atg/dynamo/service/jaxrs/JerseyClassLoaderService
responsePayload=/com/abcPath/response/xxxPayload
xxxManager=/com/xyzpath/manager/XXXManager (regular nucleus components)


XXXService.java(Resource class)

@RestResource(id = "xxxService")
@Path("/xxx")
@Api("xxx")
public class XXXService  extends GenericService{

   @POST
@Path("/function")
@Endpoint(id = "/function#POST", filterId = "xxx-Filter",validatorId="xxxValidator", isSingular = true)
public RepresentationModel function(JSONObject pInputData){

xxxPayload xxxPayLoad=new xxxPayload();
RepresentationModel.Builder builder = null;
builder = new RepresentationModel.Builder().state(xxxPayLoad);
return builder.build();
}
}

Annotating Resource Class   (These are class level)
@Path:
When we create a root resource, we must provide the @Path annotation.The annotation contains the URI path for the resource . Eg., /cart .If we create a sub-resource, the @Path is not required.


@RestResource
The @RestResource must be present for all resource classes, as it specifies the ID of the resource. The ID is a string that uniquely identifies the resource and does not change when the context and/or version change.



Annotating Endpoint Methods
@Endpoint 
We can use the @Endpoint annotation to annotate resource methods and configure the various setting for the endpoint, such as transactions, security, and cache.

 We can use the following annotations when creating an endpoint method:

@Path 


 When creating an endpoint method, use the @Path annotation if there are additional path elements beyond the resource path or the sub-resource methods. The annotation is not required if the path is empty.


@GET, @POST, @PUT, @PATCH, and, @DELETE


These annotations are used as necessary when working with the endpoint. But we used @POST annotation most of the times.


@Endpoint

This annotation identifies the endpoint with a unique string ID. The ID does not change if the context or version changes. If the endpoint is for a singular resource, the isSingular attribute must be true.


Naming Endpoint Annotations

When you define an ID in a @Endpoint annotation, it is best to name it as a combination of the resource URI and the method request type. For example, a product resource might be:


@Endpoint(id="/products/{productId}#GET, isSingular = true)

Ordering Endpoint Annotations
When creating an endpoint, it is best to be consistent with the order of the annotations. For example:

@GET
@Path("/{productId}")

@Endpoint(id="/products/{productId}#GET", isSingular = true)

The endpoint method should be public.
If the endpoint response is a representation of the resource, the return type should be RepresentationModel. The model holds the data needed to support hypermedia formats. It includes properties, links, the representation state and any embedded resources URI that should be included in the response.
Note: In some cases, the endpoint method may return only the status code. If this is the case, you should use the javax.ws.rs.core.Response class that has the javax.ws.rs.core.Response.Status enum to set and return the proper status code.


RepresentationModel
An endpoint should return an instance of a RepresentationModel if the response is a representation of the resource. You can obtain an instance of a RepresentationModel by using the build method of a RepresentationModel.Builder instance. The RepresentationModel.Builder method begins a RepresentationModel.Builder instance. The following builder methods are available.

1) State Builder Method
2)Properties Builder Methods
3)Links Builder Method
4)Self Builder Methods

1) State Builder Method

The state(Object pState) bean or dynamic bean holds the current state of the resource, for example a repository item or an Order bean. This object is filtered and rendered by the framework into the media type, and can be null, although it would normally be null only for collection resources.


Sample code for  State Builder Method.We used this as part of our implementation.
xxxPayLoad guestPayLoad=new xxxPayLoad();
RepresentationModel.Builder builder = null;
builder = new RepresentationModel.Builder().state(xxxPayLoad);
return builder.build(); (return type is RepresentationModel)

 Associating a Validator with an Endpoint

@Endpoint(id = "/addGroup#POST", filterId = "xx.abc-Filter",validatorId="xxValidator", isSingular = true)


Sample code @payloadSchema.xml

<schema include-all-simple="false" id="xxxValidator"
treat-container-as-bean="true">
<bean class="org.json.JSONObject" />
<property name="cxxl" writable="false" required="true" />
<property name="bxxd" writable="false" required="true" />
<property name="exxd" writable="false" required="true" />
<property name="gxxxe" writable="false" required="true" />
</schema>

 Associating a Filter with an Endpoint
Using the filterId property of the @Endpoint annotation, which is described in Associating a Filter with an Endpoint

@Endpoint(id = "/addGroup#POST", filterId = "xx.abc-Filter",validatorId="xxValidator", isSingular = true)

Sample code @PayloadSchema.xml

<schema include-all-simple="false" id="xx.abc-Filter"
treat-container-as-bean="true">
<bean
class="com.xxabc.response.xxxPayload" />
<bean-property use-schema-id="Status-VO" name="status" writable="false" />
<bean-property use-schema-id="ItemInfo" name="itemInfo" writable="false" />
</schema>



PayloadSchemaRegistry
Need to configure/add the cusatom payload schemas.
atg/dynamo/service/payloadschema/PayloadSchemaRegistry.properties
definitionFile=atg/dynamo/service/payloadschema/payloadSchema.xml

Customizing Property Output

We can customize the output of properties by using the property-customizer attribute of the property element.
This attribute specifies a Nucleus component that is a class implementing the atg.service.filter.bean.PropertyCustomizer interface.

Sample payloadSchema code

<schema id="orders.id-Full" include-all-simple="true">
  <bean class="atg.commerce.order.Order"/>
  <property name="orderTotal" property-customizer="atg.PricePropertyCustomizer"/>
</schema>

The following example shows a PricePropertyCustomizer:

public class PricePropertyCustomizer implements PropertyCustomizer {
  public Object getPropertyValue(Object pTargetObject, String pPropertyName,
      Map<String,String> pAttributes)
          throws BeanFilterException {
    Double value = (Double)DynamicBeans.getPropertyValue(pTargetObject,
        pPropertyName);
    return "£" + String.valueOf(value);
  }
}

embedded element
We can use the embedded element of the payload schema XML for filtering embedded resources. By default, embedded resources and sub-resources occur in the response as a self link

<schema id="orders.id-Full" include-all-simple="true">
  <bean class="atg.TestOrder"/>
  <embedded name="commerceItems" hidden="false"/>
</schema>

{
  "id": "o12345",
  "state": "SUBMITTED",
  ...
  "commerceItems": [
    {
      "id": "ci1",
      "quantity": "3",
      "productId": "prod001"
      "_links":{
        "self":{
          "href": "test/orders/commerceitems/ci1"
        }
      }
    },
    {
      "id": "ci2",
      "quantity": "2",
      "productId": "prod006"
      "_links":{
        "self":{
          "href": "test/orders/commerceitems/ci2"
        }
      }
    },
  ],

}

The embedded element has a use-schema-id attribute that We can use to override the schema defined by an endpoint when the embedded resource or sub-resource is provided as part of the root response.

<schema id="orders.id-Summary">
    <bean class="java.util.List"/>
    <embedded name="items" expand="true" use-schema-id="
      commercieitem.id-Summary"/>
</schema>

Even we can use as part of the validator and filter.

Collections and embedded 
<schema id="products-Summary">
  <bean class="java.util.Collection"/>
  <embedded name="items" hidden="false" use-schema-id="products.id-Summary"/>
</schema>

Using Query Parameters
We can filter the response output using query parameters.
 There are many . 


NOTE: Web service guide

https://docs.oracle.com/cd/E69533_01/Platform.11-3/ATGWSFrameGuide/html/s0604usingthepayloadschemaregistry01.html



The OOTB table is getting incremented  for every service request by RAXRS.

(/atg/dynamo/service/jaxrs/ETagService/)

Because of this, DB connectivity issue occurs and crashes. So to avoid this issue, disabled the the above service (ETagService).

No comments:

Post a Comment