Archive for January, 2010
Enabling non-XA Resources in JBoss 4.2 with ATG
by Frank Kim on Jan.28, 2010, under Configuration
(Photo: a dog and it’s boss by Pixel Addict)
ATG documents how to enable non-XA resources in JBoss 4.2 for SOLID. We ended up following the same instructions to work with Oracle.
JBoss Note: JBoss 4.2 by default assumes XA drivers, which some ATG applications use; however, there are no XA drivers for SOLID. To enable multiple non-XA resources in JBoss 4.2, add the property in bold text to the jbossjta-properties.xml file, under the <property depends="arjuna" name="jta"> tag:
<property depends="arjuna" name="jta"> <property name="com.arjuna.ats.jta.allowMultipleLastResources" value="true"/>You may still see warnings in your log file, but ATG applications will run correctly. To suppress these warnings, add the following to your jboss-log4j.xml file:
<category name="com.arjuna.atg.jta.logging"> <priority value="ERROR"/> </category>
For further reading please see Starting the SOLID SQL Database document in the Running Nucleus-Based Applications section of the ATG Installation and Configuration Guide.
Configuring ATG to Send Email via Comcast SMTP
by Frank Kim on Jan.25, 2010, under Configuration
(Photo: Comcast still sucks by dmuth)
When you are developing at home you will probably need to configure your ATG application to send email via your ISP’s SMTP server. Here is how I configured ATG to send email via Comcast’s SMTP server.
First you need to update ATG’s configuration to point to the Comcast SMTP server by modifying {ATG}/home/localconfig/atg/dynamo/Configuration.properties.
emailHandlerHost=smtp.comcast.net emailHandlerPort=587
Typically you don’t need to set the emailHandlerPort, it is by default set to port 25. But Comcast has recently been switching over to use port 587 because email viruses use port 25 on infected computers.
Next you need to update ATG’s SMTP Email service configuration by modifying {ATG}/home/localconfig/atg/dynamo/service/SMTPEmail.properties.
defaultFrom=betweengo@comcast.net username=betweengo password=betweengo
These values used to be optional but now are required because Comcast requires authentication as part of its increased security.
Specifying One-to-Many Relationship in ATG Repositories
by Frank Kim on Jan.21, 2010, under Repository
(Photo: Monta driving by Yogma)
Specifying one-to-many relationships is ridiculously easy in Ruby on Rails. Unfortunately it’s not so straight-forward in ATG repositories.
First you specify the “belongs to” relationship. In this example the player belongs to a team.
<item-descriptor name="player">
<table name="team_players" type="auxiliary" id-column-names="team_id" shared-table-sequence="1">
<property name="team" column-name="team_id" item-type="team" />
</table>
</item-descriptor>
Then you specify the “has many” relationship. In this example the team has many players.
<item-descriptor name="team">
<table name="team_players" type="multi" id-column-names="player_id" shared-table-sequence="2">
<property name="players" column-name="player_id" data-type="set" component-item-type="player" />
</table>
</item-descriptor>
Note the trick is specifying the “shared-table-sequence.”
Here is the SQL for the table that specifies this relationship in our example.
CREATE TABLE team_players ( team_id VARCHAR2(40) NOT NULL, player_id VARCHAR2(40) NOT NULL, CONSTRAINT team_players_pk PRIMARY KEY (team_id, player_id), CONSTRAINT team_players_players_fk foreign key (player_id) references players (id), CONSTRAINT team_players_team_fk foreign key (team_id) references teams (id) );
SQL Insert in One Table Based on Values in Another Table
by Frank Kim on Jan.18, 2010, under Oracle
(Photo: Love’s Old Sweet Song by linda yvonne)
The syntax for doing this is similar to doing an update in one table based on values in another table yet simpler.
INSERT INTO suppliers (name) SELECT customers.name FROM customers WHERE customers.id = suppliers.id);
If you want to add constant values into the insert you can do something like this.
INSERT INTO suppliers (name, city) SELECT customers.name, 'Toronto' FROM customers WHERE customers.id = suppliers.id);
For further reading please see SQL INSERT INTO.
Limiting the Quantity Added to a Cart
by Frank Kim on Jan.14, 2010, under Commerce
(Photo: Speed Limit 14 MPH by bredgur)
Sometimes the client will ask that the quantity of items you can add to the cart be limited to some number, say 14 like in the photo above.
Often people will implement this by putting in checks throughout the JSP. But this is not the best solution because it is more labor intensive and you may miss something.
Another solution is to deal with the issue in the CartModifierFormHandler by extending the doAddItemsToOrder method. Simply check the quantity of each AddCommerceItemInfo item and make sure that its quantity plus the quantity of the same item already in the cart does not go over the limit. If it does modify the quantity in the AddCommerceItemInfo item appropriately.
Here is how I implemented this.
@Override
protected void doAddItemsToOrder(DynamoHttpServletRequest pRequest,
DynamoHttpServletResponse pResponse) throws ServletException,
IOException {
// fetch the order
Order order = getOrder();
if (order == null) {
String msg = formatUserMessage(MSG_NO_ORDER_TO_MODIFY, pRequest,
pResponse);
throw new ServletException(msg);
}
// iterate through the add commerce item infos, making sure that adding
// any of them will not result in a quantity greater than LIMIT
AddCommerceItemInfo[] addCommerceItemInfos = getItems();
for (int ii = 0; ii < addCommerceItemInfos.length; ii++) {
// see if there is a commerce item already in the order for the next
// add commerce item info
AddCommerceItemInfo addCommerceItemInfo = addCommerceItemInfos[ii];
String catalogRefId = addCommerceItemInfo.getCatalogRefId();
CommerceItem commerceItem = findCommerceItemByCatalogRefId(order,
catalogRefId);
if (commerceItem == null) {
continue;
}
// check that the quantity we add won't result in a total quantity
// greater than LIMIT
long addQty = addCommerceItemInfo.getQuantity();
long qty = commerceItem.getQuantity();
if (qty >= LIMIT) {
addCommerceItemInfo.setQuantity(0);
} else if (qty + addQty > LIMIT) {
long newAddQty = LIMIT - qty;
addCommerceItemInfo.setQuantity(newAddQty);
}
}
super.doAddItemsToOrder(pRequest, pResponse);
}
protected CommerceItem findCommerceItemByCatalogRefId(Order pOrder,
String pCatalogRefId) {
for (int ii = 0; ii < numCommerceItems; ii++) {
CommerceItem commerceItem = (CommerceItem) commerceItems.get(ii);
String catalogRefId = commerceItem.getCatalogRefId();
if (catalogRefId.equals(pCatalogRefId))
return commerceItem;
}
return null;
}
Combining XML in ATG
by Frank Kim on Jan.12, 2010, under Programming
(Photo: Legospective by Guillermо)
ATG uses XML files sometimes instead of Java properties files for configuration. Combining them is not as straight-forward as with Java properties files but more flexible.
The XML File Combination section in the Nucleus: Organizing JavaBean Components chapter of the ATG Programming guide gives a good explanation. You can combine XML files using one of these methods.
- replace
- remove
- append
- append-without-matching
- prepend
- prepend-without-matching
In most cases you will append. In one case I wanted to update the id-spaces for orders but I had to first remove before appending because replace did not work in this case. This is how I did it.
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <id-spaces> <id-space xml-combine="remove" name="order" seed="1" batch-size="10000" prefix="o"/> <id-space name="order" seed="100" batch-size="1" prefix="m"/> </id-spaces>
To see the result of XML combining you can use the Dynamo Administration Server’s Component Browser to go to the component and then click on the property which specifies the XML file(s).
For example to find the result of combining idspaces.xml’s you would go to http://localhost:8080/dyn/admin/nucleus/atg/dynamo/service/IdGenerator/?propertyName=initialIdSpaces.
To find the result of combining productCatalogs.xml’s you would go to http://localhost:8080/dyn/admin/nucleus/atg/commerce/catalog/ProductCatalog/?propertyName=definitionFiles.


