Thursday, February 14, 2013

How can improper coding leads to InvalidVersionException?

Small example showing how "atg.commerce.order.InvalidVersionException" is thrown when coding is done improperly.
In below example: one of the order property is udpated and updateOrder is called. In below case InvalidVersionException is thrown.
Note: Please go through http://atgkid.blogspot.com/2011/11/regarding-concurrentupdateexception-and.html
to know more about InvalidVersionException and ConcurrentUpdateException.

public class TestOrderDroplet extends DynamoServlet {
    @Override
    public void service(DynamoHttpServletRequest req,
            DynamoHttpServletResponse res) throws ServletException, IOException {
        OrderHolder ordholder = (OrderHolder) req.resolveName("/atg/commerce/ShoppingCart");
        OrderManager ordMgr = (OrderManager) req.resolveName("/atg/commerce/order/OrderManager");
        WalgreensOrderImpl order = (WalgreensOrderImpl) ordholder.getCurrent();

        // a custom persistent property called storeNumber at order level
        order.setStoreNumber(59151);
       
        try {
        ordMgr.updateOrder(order);
    } catch (CommerceException e) {
        e.printStackTrace();
    }
    }
}
In jsp - test.jsp - Just calling above droplet
<%@ taglib uri="dsp" prefix="dsp"%>
<dsp:page>
    <dsp:droplet name="/com/TestOrderDroplet">
    </dsp:droplet>
</dsp:page>
When above page is accessed

In logs -
atg.commerce.order.InvalidVersionException: This order (2368070835) is out of date. Changes have been made to the order and the operation should be resubmitted.
Order version 15, Repository item version 16.
        at atg.commerce.order.OrderManager.updateOrder(OrderManager.java:2670)
        at com.TestOrderDroplet.service(TestOrderDroplet.java:26)
        at atg.servlet.DynamoServlet.service(DynamoServlet.java:123)
        at atg.taglib.dspjsp.DropletTag.invokeServlet(DropletTag.java:349)
        at atg.taglib.dspjsp.DropletTag.doAfterBody(DropletTag.java:616)
        at org.apache.jsp.test_jsp._jspx_meth_dsp_005fdroplet_005f0(test_jsp.java:138)
        at org.apache.jsp.test_jsp._jspx_meth_dsp_005fpage_005f0(test_jsp.java:98)
        at org.apache.jsp.test_jsp._jspService(test_jsp.java:67)

Why above exception is thrown?
During "order.setStoreNumber(59151)" value is updated in order table, updateItem is called and order item version is updated (but Order (session) object does'nt know about version change)
During "updateOrder" - ATG OOTB will compare Order (session) object version with order item version, since both are not equal - InvalidVersionException is thrown.

How can we avoid such type of exception?
By having a transaction while update order. Go through below example.
public class TestOrderDroplet extends DynamoServlet {
  
    @Override
    public void service(DynamoHttpServletRequest req,
            DynamoHttpServletResponse res) throws ServletException, IOException {
        OrderHolder ordholder = (OrderHolder) req.resolveName("/atg/commerce/ShoppingCart");
        OrderManager ordMgr = (OrderManager) req.resolveName("/atg/commerce/order/OrderManager");
        MutableRepository repo = (MutableRepository) req.resolveName("/atg/commerce/order/OrderRepository");
        TransactionManager tManger = (TransactionManager) req.resolveName("/atg/dynamo/transaction/TransactionManager");

        WalgreensOrderImpl order = (WalgreensOrderImpl) ordholder.getCurrent();
      
        // added for transaction
        TransactionDemarcation td =new TransactionDemarcation();
        boolean rollback = false;
      
        try {
            // transaction beginning
            td.begin(tManger,TransactionDemarcation.REQUIRES_NEW);
          
            RepositoryItem orderItem = repo.getItemForUpdate(order.getId(), "order");
          
            logDebug("Before set - order version : "+order.getVersion());
            logDebug("Before set - order item version: "+orderItem.getPropertyValue("version"));
          
            order.setStoreNumber(59151);

            // Note: if you call updateItem on order item, order item version will be increased
            // but order (session) object is not, so if you call udpateItem here
            // during update order, InvalidVersionException is thrown even with transaction in place.
            // repo.updateItem((MutableRepositoryItem)orderItem);
          
            logDebug("After set - order version : "+order.getVersion());
            logDebug("After set order item version: "+orderItem.getPropertyValue("version"));

           ordMgr.updateOrder(order);
      
            logDebug("After updateOrder - order version : "+order.getVersion());
            logDebug("After updateOrder order item version: "+orderItem.getPropertyValue("version"));

    } catch (Exception e) {
        e.printStackTrace();
        rollback = true;
    }
      
    try {
        // transaction end
        td.end(rollback);
    } catch (TransactionDemarcationException e) {
        e.printStackTrace();
    }
  
    }

}
In logs -
**** debug      Thu Feb 14 11:17:38 CST 2013    1360862258581   /com/TestOrderDroplet   Before set - order version : 28
**** debug      Thu Feb 14 11:17:39 CST 2013    1360862259957   /com/TestOrderDroplet   Before set - order item version: 28
**** debug      Thu Feb 14 11:17:42 CST 2013    1360862262224   /com/TestOrderDroplet   After set - order version : 28
**** debug      Thu Feb 14 11:17:43 CST 2013    1360862263115   /com/TestOrderDroplet   After set order item version: 28
**** debug      Thu Feb 14 11:17:44 CST 2013    1360862264475   /com/TestOrderDroplet   After updateOrder - order version : 30
**** debug      Thu Feb 14 11:17:45 CST 2013    1360862265225   /com/TestOrderDroplet   After updateOrder order item version: 30

Why above code will work without "InvalidVersionException" exception?

During "order.setStoreNumber(59151)" since transaction is in place, value is NOT updated yet in database or in item cache, so item version is NOT updated.
During "updateOrder" - ATG OOTB will compare Order (session) object version with order item version, in this case both are equal (since both are not updated yet).
ATG OOTB pipeline "updateOrder" is executed and ProcSaveOrderObject will call updateItem on orderItem, which will update the item version.
once whole pipeline is executed at the end of the updateOrder method - order (session) object is updated with order Item version.So once updateOrder is finished both order (session) object version and order item version will be in sync.

Hope this helps!!

Wednesday, February 13, 2013

Is calling updateItem necessary after calling setPropertyValue on item?

In this article, below scenarios are considered to see how values are updated in database and at what point.
Case 1 : What happens if setPropertyValue is called on an item - without calling updateItem and without any parent transaction?
Case 2 : What happens if setPropertyValue is called on an item - calling updateItem and without any parent transaction?
Case 3 : What happens if setPropertyValue is called on item - with parent transaction and without updateItem call?
Case 4 : What happens if setPropertyValue is called on item - With Transaction, with UpdateItem call?

=============================================================================================
Case 1 : What happens if setPropertyValue is called on an item - without calling updateItem and without any parent transaction?
for every item.setPropertyValue - update sql query is fired, commit is called, value is updated in database.

For example -
MutableRepositoryItem mutItem = repo.getItemForUpdate("900001", "addressValidation_req_log");
mutItem.setPropertyValue("city", "Des Plaines2");
In logs -
 UPDATE www_addr_verify_req_log
    SET CITY=?
  WHERE REQUEST_LOG_ID=?
-- Parameters --
p[1] = {pd: city} Des Plaines2 (java.lang.String)
p[2] = {pd} 900001 (java.lang.String)

updateItem(addressValidation_req_log:900001) (changes applied: {city=Des Plaines2})
=============================================================================================
Case 2 : What happens if setPropertyValue is called on an item - calling updateItem and without any parent transaction?
Even though updateItem is called it does'nt mean that changes in database will get updated only after updateItem is called.
In this case too, for every item.setPropertyValue - update sql query is fired, commit is called, value is updated in database.
Note: When updateItem is called seperately - Since no changes nothing is done.

For example -
mutItem.setPropertyValue("city", "Des Plaines2");
mutItem.setPropertyValue("streetAddr2", "Des 2");
repo.updateItem(mutItem);

MutableRepositoryItem mutItem = repo.getItemForUpdate("900001", "addressValidation_req_log");
mutItem.setPropertyValue("city", "Des Plaines2");
In logs -
 UPDATE www_addr_verify_req_log
    SET CITY=?
  WHERE REQUEST_LOG_ID=?
-- Parameters --
p[1] = {pd: city} Des Plaines2 (java.lang.String)
p[2] = {pd} 900001 (java.lang.String)

updateItem(addressValidation_req_log:900001) (changes applied: {city=Des Plaines2})

 UPDATE www_addr_verify_req_log
    SET STREET_ADDR2=?
  WHERE REQUEST_LOG_ID=?
-- Parameters --
p[1] = {pd: streetAddr2} Des 2 (java.lang.String)
p[2] = {pd} 900001 (java.lang.String)

updateItem(addressValidation_req_log:900001) (changes applied: {streetAddr2=Des 2})

updateItem(addressValidation_req_log:900001) (no changes)
=============================================================================================
Case 3 : What happens if setPropertyValue is called on item - with parent transaction and without updateItem call?
If transaction is in place, then only one update query is fired for all property changes for that item.
A single update query is fired at for EACH item (even if there are many properties changed) at the end of transaction.

For example:
MutableRepositoryItem mutItem = repo.getItemForUpdate("900001", "addressValidation_req_log");
mutItem.setPropertyValue("city", "Des Plaines2");
mutItem.setPropertyValue("streetAddr2", "Des 2");

setPropertyValue(addressValidation_req_log:900001.city,Des Plaines2)
setPropertyValue(addressValidation_req_log:900001.streetAddr2,Des 2)

MutableRepositoryItem mutItem1 = repo1.getItemForUpdate("1335", "categorytier3info");
mutItem1.setPropertyValue("createUser", "mktg-team1");
mutItem1.setPropertyValue("updateUser", "mktg-team1");

setPropertyValue(categorytier3info:1335.createUser,mktg-team1)
setPropertyValue(categorytier3info:1335.updateUser,mktg-team1)

td.end(true);
In logs -
 UPDATE www_addr_verify_req_log
    SET STREET_ADDR2=?,CITY=?
  WHERE REQUEST_LOG_ID=?
-- Parameters --
p[1] = {pd: streetAddr2} Des 2 (java.lang.String)
p[2] = {pd: city} Des Plaines2 (java.lang.String)
p[3] = {pd} 900001 (java.lang.String)

updateItem(addressValidation_req_log:900001) (changes applied: {streetAddr2=Des 2,city=Des Plaines2})
updateItem(categorytier3info:1335) (changes applied: {createUser=mktg-team1,updateUser=mktg-team1})

 UPDATE WWW_CONTACTUS_DTL
    SET CREATE_USER=?,UPDATE_USER=?
  WHERE SUB_CATEGORY_ID=?
-- Parameters --
p[1] = {pd: createUser} mktg-team1 (java.lang.String)
p[2] = {pd: updateUser} mktg-team1 (java.lang.String)
p[3] = {pd} 1335 (java.lang.Integer)

=============================================================================================
Case 4: What happens if setPropertyValue is called on item - With Transaction, with UpdateItem?
update query is fired for each item when updateItem is called, but changes got updated in database only
when transaction is commited.

Note: The difference between case 3 and case 4 is, in case 3 all update queries are fired and committed when transaction ends. In case 4 update queries are fired during updateItem call and commit will be done only at the end of the transaction.

For example:
MutableRepositoryItem mutItem = repo.getItemForUpdate("900001", "addressValidation_req_log");
mutItem.setPropertyValue("city", "Des Plaines2");
mutItem.setPropertyValue("streetAddr2", "Des 2");
repo.updateItem(mutItem);

MutableRepositoryItem mutItem1 = repo1.getItemForUpdate("1335", "categorytier3info");
mutItem1.setPropertyValue("createUser", "mktg-team1");
mutItem1.setPropertyValue("updateUser", "mktg-team1");
repo1.updateItem(mutItem1);
In logs -
setPropertyValue(addressValidation_req_log:900001.city,Des Plaines2)
setPropertyValue(addressValidation_req_log:900001.streetAddr2,Des 2)
 UPDATE www_addr_verify_req_log
    SET STREET_ADDR2=?,CITY=?
  WHERE REQUEST_LOG_ID=?
-- Parameters --
p[1] = {pd: streetAddr2} Des 2 (java.lang.String)
p[2] = {pd: city} Des Plaines2 (java.lang.String)
p[3] = {pd} 900001 (java.lang.String)
updateItem(addressValidation_req_log:900001) (changes applied: {streetAddr2=Des 2,city=Des Plaines2})

setPropertyValue(categorytier3info:1335.createUser,mktg-team1)
setPropertyPD{categorytier3info,1335,updateUser} = mktg-team1 (java.lang.String)
 UPDATE WWW_CONTACTUS_DTL
    SET CREATE_USER=?,UPDATE_USER=?
  WHERE SUB_CATEGORY_ID=?
-- Parameters --
p[1] = {pd: createUser} mktg-team1 (java.lang.String)
p[2] = {pd: updateUser} mktg-team1 (java.lang.String)
p[3] = {pd} 1335 (java.lang.Integer)
updateItem(categorytier3info:1335) (changes applied: {createUser=mktg-team1,updateUser=mktg-team1})
=============================================================================================
Hope this helps!!

Thursday, November 29, 2012

Session sharing issue with JBOSS application server

Problem statement -
Session sharing between web applications is not happening. Each web application (war) gets a separate session id and cookie. For each JBoss session, unique ATG session-scoped components (e.g. Order and Profile) are getting created instead of being shared by all web applications.

Environment details where this issue is reproduced
Application server - JBoss EAP 4.3.0 CP10
ATG - ATG 9.4
Java version - JDK_1_6_0_27

Explanation of above problem with example -
sample_application.ear has 2 wars
    common.war with "/" context
    pharmacy.war with "/pharmacy" context
instead of having one jsession id, 2 jsesson id's are getting created
And session objects like "profile" and "order" are not getting shared between these modules.

Here is the snapshot of 2 separate session id's created for each module



Here is the snapshot of these jsession id's in GenericSessionManager in Nucleus component browser.
http://localhost:8080/dyn/admin/nucleus/atg/dynamo/servlet/sessiontracking/GenericSessionManager/ 



Expected behavior - A single instance of a session scoped component should be available to all web applications participating in session sharing. Each web application should use the same session id.

This issue exists even though parentContextName is defined in web.xml in each module.
In general, if parentContextName is defined, ATG should maintain session sharing between wars.
<context-param>
  <param-name>atg.session.parentContextName</param-name>
  <param-value>/dyn</param-value>
</context-param>
<context-param>
  <param-name>atg.dafear.bootstrapContextName</param-name>
  <param-value>/dyn</param-value>
</context-param>

Reason
There are 2 issues related to this -
1) Issue in JBOSS - Seperate JSESSION is being created for each domain.
https://issues.jboss.org/browse/JBWEB-107
" Currently the JSESSIONID cookie domain is set to the domain name of the Host that emits the cookie (e.g. www.domain.com). This is an issue with customers using Aliases (e.g. secure.domain.com, zzz.domain.com, etc.), as the session is lost when switching between the main domain and any aliases. In these cases, it would be useful to be able to specify the domain to be "domain.com" so the same JSESSIONID cookie is used across the aliases and converges to the same session."

Fix is already mentioned in https://issues.jboss.org/browse/JBWEB-107
i) Breifly - Deploy customvalve.jar in  \jboss-eap-4.3\jboss-as\server\<servername>\deploy\jboss-web.deployer\
ii) And in jboss-eap-4.3/jboss-as/server/<servername>/deploy/jboss-web.deployer/server.xml, set cookie Domain to “.<your_domain>.com”
   <Valve className="com.redhat.jboss.support.ConfigureSessionCookieValve" cookieSecure="false" cookieDomain=".<your_domain>.com" />

2) If emptySessionPath attribute in server.xml is false, then each web application will have its own jsessionid cookie.
 http://tomcat.apache.org/tomcat-6.0-doc/config/ajp.html
"The issue is generally caused by the Tomcat/JBoss setting of the emptySessionPath attribute. This attribute defaults to true which allows all web applications to use the same jsessionid cookie (with cookie path of /). If this is set to false, each web application will receive its own jsessionid cookie (with a cookie path set to the context root of the web application)."

To fix this
The jboss-eap-4.3/jboss-as/server/<servername>/deploy/jboss-web.deployer/server.xml file and check the emptySessionPath setting. A setting of true will ensure that the jsessionid cookie will have a cookie path of / and all web-applications will use the same session id value.

Example -
<Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"
        maxThreads="150" scheme="https" secure="true"
        emptySessionPath="true"
        clientAuth="false"
        strategy="ms"
        address="${jboss.bind.address}"
        keystoreFile="${jboss.server.home.dir}/conf/server.keystore"
        keystorePass="tc-ssl"
        truststoreFile="${jboss.server.home.dir}/conf/server.keystore"
        truststorePass="tc-ssl"
        sslProtocol="TLS"/>     

Note: Information related to "emptySessionPath" setting is provided by Oracle ATG Support.
After having above 2 settings this issue is resolved.

Hope this helps!!

Friday, May 25, 2012

Minimizing query execution time using oracle hints

Querying on a indexed columns generally improves query performance but in some cases if all columns in where clause are indexed columns degrades query performances. And this can be observed if table you are querying has humongous data (*many* rows). In that scenario, execution time of query on a table (which has many rows) will increase as the number of indexed columns in the where condition increase.

For example: Below are the columns present in dcspp_order table

Indexes that present in this table


Query 1: Querying dcspp_order with creation_date and state, only state is indexed column
set serveroutput on
variable n number
exec :n := dbms_utility.get_time;
SELECT count(*) FROM dcspp_order WHERE  creation_date>='01-Jan-02' and creation_date <='12-Dec-02' and state = 'INCOMPLETE';
exec dbms_output.put_line( ((dbms_utility.get_time-:n)/100) || ' seconds....' );

 The output -
  COUNT(*)
----------
         0
1 row selected.
35.07 seconds....
PL/SQL procedure successfully completed.

Execution plan for above query-
1 Every row in the table PROFILEV5.DCSPP_ORDER  is read.
2 For the rows returned by step 1, filter out rows depending on filter criteria.
3 The rows were sorted to support a group operation (MAX,MIN,AVERAGE, SUM, etc).
4 Rows were returned by the SELECT statement.

Query 2 : Querying dcspp_order with last_modified_date and state, both columns are indexed
set serveroutput on
variable n number
exec :n := dbms_utility.get_time;
SELECT count(*) FROM dcspp_order WHERE last_modified_date>='01-Jan-02' and last_modified_date <='12-Dec-02' and state = 'INCOMPLETE';
exec dbms_output.put_line( ((dbms_utility.get_time-:n)/100) || ' seconds....' );
The output -
  COUNT(*)
----------
         0

1 row selected.
224.43 seconds....
PL/SQL procedure successfully completed.

Execution Plan for above query -
1 One or more rows were retrieved using index PROFILEV5.IX_DCSPP_ORDER_01 .  The index was scanned in ascending order..
2 One or more rows were retrieved using index PROFILEV5.ORDER_LASTMOD_IDX .  The index was scanned in ascending order..
3 The result sets from steps 1, 2 were joined (hash).
4 A view definition was processed, either from a stored view PROFILEV5.index$_join$_001  or as defined by steps 3.
5 For the rows returned by step 4, filter out rows depending on filter criteria.
6 The rows were sorted to support a group operation (MAX,MIN,AVERAGE, SUM, etc).
7 Rows were returned by the SELECT statement.

As you can observe Query 2 execution time (224.43 secs) is more than Query 1 execution time (35.07 secs) , even though Query 2 has both indexed columns in the condition.

Why?
If you observe the execution plan of Query 1, STATE column index - PROFILEV5.IX_DCSPP_ORDER_01 is not considered that's because of condition also has a column creation_date which doesn't have any index. So there is a full table scan in this case. Now If you observe the execution plan of Query 2, since all the columns in the condition has indexes,  STATE column index PROFILEV5.IX_DCSPP_ORDER_01 and LAST_MODIFED_DATE column index PROFILEV5.ORDER_LASTMOD_IDX are considered while executing, first scans through STATE index and next scan through LAST_MODIFED_DATE index and then results from both are joined which is taking much time since there are hugh number of rows in dcspp_order table.

How to optimize Query 2 execution time?
 Using oracle hints we can ask to skip one index, which will avoid hash join.

Query 2 optimizing using oracle hints
set serveroutput on
variable n number
exec :n := dbms_utility.get_time;
SELECT /*+NO_INDEX(dcspp_order IX_DCSPP_ORDER_01)*/  count(*) FROM dcspp_order WHERE last_modified_date>='01-Jan-02' and last_modified_date <='12-Dec-02' and state = 'INCOMPLETE';
exec dbms_output.put_line( ((dbms_utility.get_time-:n)/100) || ' seconds....' );
output -
  COUNT(*)
----------
         0

1 row selected.
28.17 seconds....
PL/SQL procedure successfully completed.

Execution plan -
1 Every row in the table PROFILEV5.DCSPP_ORDER  is read.
2 For the rows returned by step 1, filter out rows depending on filter criteria.
3 The rows were sorted to support a group operation (MAX,MIN,AVERAGE, SUM, etc).
4 Rows were returned by the SELECT statement.

So execution time Query 2 is reduced from 224.43 seconds to 28.17 seconds.
We used NO_INDEX oracle hint to skip STATE column index to avoid hash join.

Hope this helps

Thursday, February 23, 2012

Issue with invalidating caches at regular intervals

After setting some values in an item & before calling updateItem on that item, if that particular repository cache is invalidated then the changes made to item in that transaction are lost/not updated.

And in logs you will see something like
Changes not updated for item in commit: <item-descriptor-name>:<id-of-item> changes={<property-name>=<value-that-being-set>}

For example -
Suppose there is www_person table in /com/person/PersonRepository

public boolean handleUpdate(DynamoHttpServletRequest pRequest,
DynamoHttpServletResponse pResponse) throws Exception {
MutableRepositoryItem personItem = personRepository.getItemForUpdate("100001");
personItem.setPropertyValue("lastname", "Mike");

// Invalidate cache at this point, as you can observe last value set is lost. 
logInfo("Last name"+(String) personItem.getPropertyValue("lastname"));

personRepository.updateItem(personItem);
return true;
}

Refer below screenshot - 

In logs -
**** Error      Thu Feb 23 18:21:12 CST 2012    1330042872864   /       Changes not updated for item in commit: person:100001 changes={lastname=Mike}

If you have some cron jobs which are invalidating repositories in regular intervals, then above type of errors may occur.

For example - If you have cron job for invalidating OrderRepository at regular intervals, then the values set to order item or commerce item or shipping item will be lost or not updated if invalidate cache is called before updateOrder/UpdateItem method.

ATG/Oracle support created a patch regarding this issue.

Hope this helps.

Tuesday, February 14, 2012

Performance using Cache

Below are some examples showing how having or not having cache, impacts performance.
To give a overall idea how ATG cache works please refer below diagram.(click to enlarge).


Note: To effectively use cache & to improve performance follow green path & avoid red.
If Cache is disabled
For example – “siteConfiguration” item-descriptor in SiteConfiguration Repository
  <item-descriptor name="siteConfiguration" cache-mode=" disabled" default="false">
              <table name="www_site_configuration" type="primary" id-column-name="APPLICATION_NAME">
                        <property name="configName" column-name="CONFIG_NAME" data-type="String"> </property>
                      ….  
Cache stats for this item in component browser
In Below example – querying for siteConfiguration.configName=”shopduringdowntime”
<%@ taglib uri="dsp" prefix="dsp"%>
<dsp:page>
<dsp:setvalue param="confName" value="shopduringdowntime"/>

<dsp:droplet name="/atg/dynamo/droplet/RQLQueryForEach">
  <dsp:param name="queryRQL" value="configName=:confName"/>
  <dsp:param name="repository" value="/repositories/siteConfiguration/SiteConfiguration"/>
  <dsp:param name="itemDescriptor" value="siteConfiguration"/>
  <dsp:oparam name="output">
     Config Value : <dsp:valueof param="element.configValue"/> <br>
  </dsp:oparam>
</dsp:droplet>

</dsp:page>

In logs –
First to get id (id-column-name) for the required item with given params (configName=”shopduringdowntime”)
**** debug      Mon Jan 30 16:09:53 CST 2012    1327961393403   /repositories/siteConfiguration/SiteConfiguration       [++SQLQuery++]
 SELECT t1.APPLICATION_NAME
   FROM www_site_configuration t1
  WHERE (t1.CONFIG_NAME = ?)
-- Parameters --
p[1] = {pd: configName} shopduringdowntime (java.lang.String)
[--SQLQuery--]

**** debug      Mon Jan 30 16:09:53 CST 2012    1327961393450   /repositories/siteConfiguration/SiteConfiguration       getItems(siteConfiguration: [quickshop])
Once we got the id load item (all properties) with that id
**** debug      Mon Jan 30 16:21:10 CST 2012    1327962070167   /repositories/siteConfiguration/SiteConfiguration       [++SQLSelect++]
  SELECT CONFIG_NAME,CONFIG_VALUE,APPLICATION_NAME,UPDATE_DTTM,CREATE_DTTM,CREATED_USER_ID,UPDATED_USER_ID,DESCRIPTION
   FROM www_site_configuration
  WHERE APPLICATION_NAME=?
-- Parameters --
p[1] = {pd} quickshop (java.lang.String)
[--SQLSelect--]

So total 2 queries are fired.  In this case, for every iteration 2 queries are fired.
If 2 iterations are there for same rql as below then 4 queries are fired.
<%@ taglib uri="dsp" prefix="dsp"%>
<dsp:page>
<dsp:setvalue param="confName" value="shopduringdowntime"/>

<%-- iteration 1 --%>
<dsp:droplet name="/atg/dynamo/droplet/RQLQueryForEach">
  <dsp:param name="queryRQL" value="configName=:confName"/>
  <dsp:param name="repository" value="/repositories/siteConfiguration/SiteConfiguration"/>
  <dsp:param name="itemDescriptor" value="siteConfiguration"/>
  <dsp:oparam name="output">
     Config Value : <dsp:valueof param="element.configValue"/> <br>
  </dsp:oparam>
</dsp:droplet>

<%-- iteration 2 --%>
<dsp:droplet name="/atg/dynamo/droplet/RQLQueryForEach">
  <dsp:param name="queryRQL" value="configName=:confName"/>
  <dsp:param name="repository" value="/repositories/siteConfiguration/SiteConfiguration"/>
  <dsp:param name="itemDescriptor" value="siteConfiguration"/>
  <dsp:oparam name="output">
     Config Value : <dsp:valueof param="element.configValue"/> <br>
  </dsp:oparam>
</dsp:droplet>

</dsp:page>

Transaction Cache
But if both are in same transaction like below –
<%@ taglib uri="dsp" prefix="dsp"%>
<dsp:page>
<dsp:setvalue param="confName" value="shopduringdowntime"/>

<%-- open transaction --%>
<dsp:droplet name="/atg/dynamo/transaction/droplet/Transaction">
  <dsp:param name="transAttribute" value="required"/>
  <dsp:oparam name="output">

<%-- iteration 1 --%>
<dsp:droplet name="/atg/dynamo/droplet/RQLQueryForEach">
  <dsp:param name="queryRQL" value="configName=:confName"/>
  <dsp:param name="repository" value="/repositories/siteConfiguration/SiteConfiguration"/>
  <dsp:param name="itemDescriptor" value="siteConfiguration"/>
  <dsp:oparam name="output">
     Config Value : <dsp:valueof param="element.configValue"/> <br>
  </dsp:oparam>
</dsp:droplet>

<%-- iteration 2 --%>
<dsp:droplet name="/atg/dynamo/droplet/RQLQueryForEach">
  <dsp:param name="queryRQL" value="configName=:confName"/>
  <dsp:param name="repository" value="/repositories/siteConfiguration/SiteConfiguration"/>
  <dsp:param name="itemDescriptor" value="siteConfiguration"/>
  <dsp:oparam name="output">
     Config Value : <dsp:valueof param="element.configValue"/> <br>
  </dsp:oparam>
</dsp:droplet>

 </dsp:oparam>
</dsp:droplet>
<%-- end transaction --%>

</dsp:page>

For iteration 1: 2 queries are fired.
But for iteration 2: only below query is fired
**** debug      Mon Jan 30 16:37:44 CST 2012    1327963064454   /repositories/siteConfiguration/SiteConfiguration       [++SQLQuery++]
  SELECT t1.APPLICATION_NAME
   FROM www_site_configuration t1
  WHERE (t1.CONFIG_NAME = ?)
-- Parameters --
p[1] = {pd: configName} shopduringdowntime (java.lang.String)
[--SQLQuery--]

Since above query is already cached in Transaction Cache, next query is not fired. So there by only 3 queries (instead of 4) are fired if both are in same transaction.

So If you have 10 same queries in different transaction in same thread, then total queries will be 10*2 = 20.
If you have 10 same queries in same transaction in same thread, then total queries will (1*2)+(9*1) = 11.

If Cache is enabled (& if query-cache is disabled)
For any cache mode (either simple/distributed/hybrid), by default item-cache-size is enabled (default is 1000) & query-cache-size is disabled (default is 0).
For example – “siteConfiguration” item-descriptor in SiteConfiguration Repository.
<item-descriptor name="siteConfiguration" cache-mode=" simple" default="false">
              <table name="www_site_configuration" type="primary" id-column-name="APPLICATION_NAME">
                        <property name="configName" column-name="CONFIG_NAME" data-type="String"> </property>
                      ….  
In Below example – querying for siteConfiguration.configName=”shopduringdowntime”.
<%@ taglib uri="dsp" prefix="dsp"%>
<dsp:page>
<dsp:setvalue param="confName" value="shopduringdowntime"/>

<dsp:droplet name="/atg/dynamo/droplet/RQLQueryForEach">
  <dsp:param name="queryRQL" value="configName=:confName"/>
  <dsp:param name="repository" value="/repositories/siteConfiguration/SiteConfiguration"/>
  <dsp:param name="itemDescriptor" value="siteConfiguration"/>
  <dsp:oparam name="output">
     Config Value : <dsp:valueof param="element.configValue"/> <br>
  </dsp:oparam>
</dsp:droplet>

</dsp:page>

First Iteration
In logs -
First to get id (id-column-name) for the required item with given params (configName=”shopduringdowntime”)
**** debug      Mon Jan 30 17:14:05 CST 2012    1327965245245   /repositories/siteConfiguration/SiteConfiguration       [++SQLQuery++]
  SELECT t1.APPLICATION_NAME
   FROM www_site_configuration t1
  WHERE (t1.CONFIG_NAME = ?)
-- Parameters --
p[1] = {pd: configName} shopduringdowntime (java.lang.String)
[--SQLQuery--]
Next query is to load item for that id
**** debug      Mon Jan 30 17:14:05 CST 2012    1327965245276   /repositories/siteConfiguration/SiteConfiguration       [++SQLQuery++]
  SELECT t1.APPLICATION_NAME,t1.DESCRIPTION,t1.UPDATE_DTTM,t1.CREATED_USER_ID,t1.CREATE_DTTM,t1.CONFIG_VALUE,t1.UPDATED_USER_ID,t1.CONFIG_NAME
   FROM www_site_configuration t1
  WHERE t1.APPLICATION_NAME = ?
-- Parameters --
p[1] = {pd} quickshop (java.lang.String)
[--SQLQuery--]

Next Iterations
Once below query is exected –
**** debug      Mon Jan 30 17:23:51 CST 2012    1327965831278   /repositories/siteConfiguration/SiteConfiguration       [++SQLQuery++]
  SELECT t1.APPLICATION_NAME
   FROM www_site_configuration t1
  WHERE (t1.CONFIG_NAME = ?)
-- Parameters --
p[1] = {pd: configName} shopduringdowntime (java.lang.String)
[--SQLQuery--]

When getItems(siteConfiguration: [quickshop]) is called, since “quickshop” item is already cached in item-cache,  another query is not required. So once item cached, for all next iterations querying for same item will have only 1 query (instead of 2, if query is disabled).

In above case

If you have 10 iterations without using item-cache, then total queries will be 10*2 = 20.
If you have 10 iterations using  item-cache, then total queries will (1*2)+(9*1) = 11.

Regarding Transaction cache while cache is enabled – Since items are already cached in item-cache having or not having transaction cache will result in same 1 query (above query to get id)

If Cache is enabled (& if query-cache is enabled)
If query-cache-size is also enabled (suppose size set is 1000) –
If you enable query-cache along with item-cache then the 1 query to get id’s is also not queried since that will be cached in query-cache until the query params are not changed.
For example – “siteConfiguration” item-descriptor in SiteConfiguration Repository.
 <item-descriptor name="siteConfiguration" cache-mode=" simple" default="false" item-cache-size="1000" query-cache-size="1000">
              <table name="www_site_configuration" type="primary" id-column-name="APPLICATION_NAME">
                        <property name="configName" column-name="CONFIG_NAME" data-type="String"> </property>
                      ….   

First Iteration
In logs -
First to get id (id-column-name) for the required item with given params (configName=”shopduringdowntime”)
**** debug      Mon Jan 30 17:46:14 CST 2012    1327967174714   /repositories/siteConfiguration/SiteConfiguration       [++SQLQuery++]
 SELECT t1.APPLICATION_NAME
   FROM www_site_configuration t1
  WHERE (t1.CONFIG_NAME = ?)
-- Parameters --
p[1] = {pd: configName} shopduringdowntime (java.lang.String)
[--SQLQuery--]

Next query is to load item for that id.
**** debug      Mon Jan 30 17:46:14 CST 2012    1327967174745   /repositories/siteConfiguration/SiteConfiguration       [++SQLQuery++]
  SELECT t1.APPLICATION_NAME,t1.DESCRIPTION,t1.UPDATE_DTTM,t1.CREATED_USER_ID,t1.CREATE_DTTM,t1.CONFIG_VALUE,t1.UPDATED_USER_ID,t1.CONFIG_NAME
   FROM www_site_configuration t1
  WHERE t1.APPLICATION_NAME = ?
-- Parameters --
p[1] = {pd} quickshop (java.lang.String)
[--SQLQuery--]

Next Iterations
No queries are fired, since above query is already cached.

In above case
If you have 10 iterations without using item-cache & query-cache, then total queries will be 10*2 = 20.
If you have 10 iterations using item-cache & query-cache, then total queries will (1*2)+(9*0) = 2.

Summary of above examples -
If cache is disabled & no transaction cache - for 10 iterations, 20 queries are fired.
If cache is disabled & using transaction cache - for 10 iterations, 11 queries are fired. (only for that transaction)
If item-cache is enabled & query-cache is disabled - for 10 iterations, 11 queries are fired.
If item-cache & query-cache enabled - for 10 iterations, 2 queries are fired.

Thursday, January 26, 2012

To develop sample webservice application using CXF

Regarding CXF -
"Apache CXF is an open source services framework. CXF helps you build and develop services using frontend programming APIs, like JAX-WS and JAX-RS. These services can speak a variety of protocols such as SOAP, XML/HTTP, RESTful HTTP, or CORBA and work over a variety of transports such as HTTP, JMS or JBI." -- http://cxf.apache.org/

Previously CXF is known as Xfire -
"User's looking to use XFire on a new project, should use CXF instead. CXF is a continuation of the XFire project and is considered XFire 2.0. It has many new features, a ton of bug fixes, and is now JAX-WS compliant! XFire will continue to be maintained through bug fix releases, but most development will occur on CXF now" -- http://xfire.codehaus.org/

If you are looking for sample webservice application using Xfire
refer - http://atgkid.blogspot.com/2012/01/to-develop-sample-webservice.html

Below are the steps to create a sample web service "AdditionWebService" (by using CXF) which takes input 2 numbers and returns sum of those numbers as response.
As mentioned in To develop sample webservice application using Xfire - Follow same steps for creating webservice project using eclipse & Java classes.

With CXF - refer http://cxf.apache.org/docs/writing-a-service-with-spring.html for more info
No need to have In /<Project-Name>/WebContent/META-INF/xfire/services.xml
Instead we need to have /<Project-Name>/WebContent/WEB-INF/cxf-servlet.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">
<import resource="classpath:META-INF/cxf/cxf.xml" />
<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
<jaxws:endpoint
 id="AddService"
 implementor="com.test.service.AdditionWebServiceImpl"
 address="/AddService" />
</beans>
And in /<Project-Name>/WebContent/WEB-INF/web.xml
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
         http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
    <display-name>TestWebService</display-name>

    <servlet>
        <servlet-name>cxf</servlet-name>
        <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>cxf</servlet-name>
        <url-pattern>/services/*</url-pattern>

    </servlet-mapping>

    <session-config>
        <session-timeout>60</session-timeout>
    </session-config>

</web-app>
dependencies & libraries needed for cxf
Download http://www.apache.org/dyn/closer.cgi?path=/cxf/2.5.1/apache-cxf-2.5.1.zip, once you extract you will find all libs mentioned below in \apache-cxf-2.5.1\lib

Thats it once you have done above steps, build war using export functionality in eclipse (refer To develop sample webservice application using Xfire)

Once war is created deploy & to generate wsdl go to http://localhost:8080/<context>/services/<address-mentioned-in-cfx-servlet.xml>?wsdl
For example - http://localhost:8080/TestWebService/services/AddService?wsdl


To test using SOAP UI -


Follow same steps mentioned in " To develop sample webservice application using Xfire" to develop Java client.