Wednesday, October 28, 2009

WCS Accelerator tip

At notebook view, to remember the current panel, set:

 

top.setReturningPanel(parent.getCurrentPanelAttribute("name"));

Friday, September 04, 2009

Email blog testing

A testing

 

 

Allan

 

WebSphere Commerce Acceleator customization

Two scenarios of customizing Accelerator


Create a dynamiclist in Accelerator:

1. Update instance.xml to add entry of new resources.xml

locate \WC\xml\config\wc-server.xml, search
<ToolsGeneralConfig DTDPath="tools/common;tools/devtools;tools/bi;tools/catalog;schema/xml;sar" XMLCacheSize="0" XMLPath="tools;tools/devtools;WEB-INF/xml/tools;WEB-INF" developmentMode="false"

you can udpate developmentMode to true, this allows the xml/properties files being refreshed in run time.

Assume we add codes into "custom" folder, then add new line like this:

<resourceConfig file="custom/resources.xml"/>

2. Create resources.xml in \WC\xml\tools\custom location.

the custom must match #1 "custom". sample resources.xml

---


<!DOCTYPE resourceConfig SYSTEM "../common/Resources.dtd">

<!-- Operational Time Tools specific model extensions -->
<resourceConfig >

<resource nameSpace="custom">

<!-- resource bundle file mappings -->

<resourceBundle name="customRB"
bundle="com.ibm.commerce.tools.sears.properties.customRB" />


<!-- XML file mappings -->

<resourceXML name="customXML"
file="custom/customXMLr.xml" />

</resource>

</resourceConfig>

name space is defined as "custom", then the resource bundle can be referenced as custom.customRB.

3. Create menu

Locate this file: WC\xml\tools\common\CommerceAcceleratorMHS.xml

depends on what type of your store, you may have to find the right xml file.

Run "select store_id,storetype from store where store_id=xxx" to find out what store type is.

In eSite, the store type is MHS.

  • B2C = Consumer direct
  • BBB = Basic B2B direct
  • B2B = B2B direct
  • CHS = Channel hub
  • CPS = Catalog asset store
  • RHS = Consumer direct reseller store
  • BRH = B2B reseller store
  • RPS = Consumer direct reseller storefront asset store
  • BRP = B2B reseller storefront asset store
  • DPS = Distributor asset store
  • DPX = Distributor proxy store
  • SCP = Supplier hub
  • SPS = Supplier asset store
  • SHS = Supplier hosted store
  • HCP = Hosting hub
  • PBS = Store directory
  • MHS = Consumer direct hosted store
  • BMH = B2B hosted store
  • MPS = Consumer direct hosted storefront asset store
  • BMP = B2B hosted storefront asset store.

Open above xml file, follow the existing pattern, create the menu / node accordingly.

Notice "users" define the user access control.

In this example, we create a new sub menu called "process pending order" under "Operation" menu.

search for " <menuitem name="operations" " , and <node name="separator" url=""/>

under this separator, we create a new node, add below codes:

------------

<node name="pendOrder"
url="$webapp_accelerator$NewDynamicListView?ActionXMLFile=custom.customXML&cmd=CustomLandingView"
users="cusRep cusSup opMgr seller"/>


<node name="separator"
url=""/>
----------------

where name="pendOrder", you need register this name in properties: WC\properties\com\ibm\commerce\tools\properties\mccNLS.properties . at the end of file, add:

" pendOrder = process the pending order. "

this will be showing in the Accelerator as node name. Add locale properties as needed.

url , is the URL when you click on this sub menu (node). This URL will open a dynamic list view, which contents are displaying with the result of view: CustomLandingView. we will create this view later.

users is the access control of the list of allowed users

4. resourceXML file (customXML.xml)

in #2, the resource config file define resourceXML, "custom/customXML.xml",

create this file at WC\xml\tools\custom\resourceXML

The resourceXML defines a type of panel, like dynamci list, wizard, dialog, etc. Base on what panel you requried, create related xml files.

<!DOCTYPE action SYSTEM "../common/List.dtd"> will determine the type by the dtd. The dtd files can be found in WC\xml\tools\common folder.

in #3, it defines the url of the button to "NewDynamicListView?ActionXMLFile=custom.customXML", the page will load the dynamic view, then render the page/buttons base on the ActionXMLFile (custom.customXML).

sample:

--------

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE action SYSTEM "../common/List.dtd">

<action resourceBundle="custom.customRB"
formName="csrPendOrderForm">

<parameter listsize="10"
startindex="0"
ActionXMLFile="custom.customXML"
resultssize="0"
/>
<scrollcontrol title="theTitle"
display="false" />

<controlpanel display="true" />

<button>
<menu name="findPendOrders"
action="basefrm.findPendingOrders()"
users="cusRep cusSup opMgr seller siteAdmin" />
<menu name="print"
action="basefrm.print()"
users="cusRep cusSup opMgr seller siteAdmin" />
<menu name="markProcessed"
action="basefrm.markProcessed()"
users="cusRep cusSup opMgr seller siteAdmin" />
</button>

<jsFile arc="/wcs/javascript/tools/common/Util.js" />
<jsFile arc="/wcs/javascript/tools/common/DateUtil.js" />
</action>

------

where resourceBundle="custom.customRB" defines the resourcebundle created in next #4.

ActionXMLFile="custom.customXML" points to the resourcesXML,

scrollControl display="false" actually turnning off the scroll control

<button> section defines all the buttons.

name is the propeties key of button name, properites is the custom.customRB points to.(#4)

action = define the javascript associate with this button, use "basefrm.xxx()" . basefrm is system default. the function will be created inside the jsp files or js files whichever uses this xml as resource xml.

again, users defines the access control.

the jsFile are mandatory.

5. Create properties (customRB)

create customRB.properties (locale properites if needed) in folder WC\properties\com\ibm\commerce\tools\custom\properties\

inside the properties, you need define all the keys that you are going to use for buttons/links, etc

6. Create tools controller command and view

the jsp can be created in

CommerceAccelerator\tools\custom

add into \WEB-INF\struts-config-migrate.xml for the view/URL entries. (CustomLandingView)

insdie the jsp file, which will be shown in the main content of the dynamic list, you need add :

//Mandatory:

<%@include file="../common/common.jsp"%>

<%

CommandContext cmdContextLocale = (CommandContext) request.getAttribute(ECConstants.EC_COMMANDCONTEXT);
Locale jLocale = cmdContextLocale.getLocale();
Integer langId = cmdContextLocale.getLanguageId();
Integer storeId = cmdContextLocale.getStoreId();
String currency = cmdContextLocale.getCurrency();

//use below to load your properties file. Hashtable pendOrderRB = (Hashtable) ResourceDirectory.lookup("custom.customXML", jLocale);
%>

<head>
<SCRIPT SRC="/wcs/javascript/tools/common/dynamiclist.js"></SCRIPT>
<SCRIPT SRC="/wcs/javascript/tools/common/Util.js"></SCRIPT>
<script language="JavaScript">

function onLoad () {

// This will load the frames parent.loadFrames();
}

function findPendingOrders(){
// CustomCommandURL' is the ToolsCommandController returns a redirect URL to show in currect content.

// the returned view must define simliar to this file style to loadFrames,

top.setContent('<%=UIUtil.toJavaScript((String) pendOrderRB.get("report"))%>','/webapp/wcs/tools/servlet/NewDynamicListView?ActionXMLFile=custom.customXML&cmd=CustomCommandURL',false)
}


function print() {

window.focus();
top.print();
}

<body onLoad="onLoad()">

<!--your layout -->

</body>

<script>
// This will render the buttons// Mandatory parent.afterLoads(); </script>

</html>

You can use JSTL tag lib in your jsp files.

Add “list All Address” function under Operation/Customer/Address button

1. Locating the modification place

1.1. Find the resourceXML. Locate CommerceAcceleratorMHS.xml , Operations ->find customer, get URL, find XMLFile=csr.shopperSearchB2C. From this we know the name space is “csr”.

<node name="findCustomers"

url="$webapp_accelerator$DialogView?XMLFile=csr.shopperSearchB2C"

users="cusRep cusSup opMgr seller"/>

1.2. Open WC\xml\tools\csr\resources.xml (notice the namespace csr) . Locate shopperSearchB2C (we get from 2 steps before), find

<resourceXML name="shopperSearchB2C" file="csr/ShopperSearchDialogB2C.xml" />

csr/ShopperSearchDialogB2C.xml is located under wc\xml\tools\

Inside this xml, located the “search” panel. Because we know at Accelerator, you have to click search button to go in the panel that we are going to modify. Check its URL, which is ShopperSearchB2C.

· Open struts-config.xml, locate this link ShopperSearchB2C. path="/tools/csr/ShopperSearchB2C.jsp">

· Open this file under CommerceAccelerator\WebContent\tools\csr

· Inside the file, you will find :

var url = "/webapp/wcs/tools/servlet/NewDynamicListView";

var urlPara = new Object();

urlPara.ActionXMLFile='csr.shopperListB2C';

urlPara.cmd='ShopperListB2C';

· From this we learn: it opens a dynamicList, using resourceXML csr.shopperListB2C, and command to call is ShopperListB2C.

Now, open open the xml base on “csr.shopperListB2C” .

· Now open resources.xml file again, find csr.shopperListB2C.

<resourceXML name="shopperListB2C"

file="csr/ShoppersActionsB2C.xml" />

Open struts-config.xml file again, locate URL “ShopperListB2C”,

find name="ShopperListB2C" path="/tools/csr/ShopperListB2C.jsp">

· Now open resource xml ShoppersActionsB2C.xml at wc\xml\tools\csr, locate button “change”, find its action = “basefrm.changeCustomerInfo()”.

At ShopperListB2C.jsp find the javascript function changeCustomerInfo() definition.

function changeCustomerInfo(id) {

if (id == null && parent.buttons.buttonForm.changeButton.className=='disabled') {

return;

}

if (id == null) {

id = parent.getSelected();

}

debugAlert(id);

// The following url will not contains NLS data

top.setContent(getNotebookTitle(), '/webapp/wcs/tools/servlet/NotebookView?XMLFile=csr.shopperNotebook&shrfnbr='+id+'&locale=<%=cmdContext.getLocale().toString()%>',true);

return;

}

The top.setContent() is where to render the page.

It is opening a notebook, with resourceXML called “csr.shopperNotebook”, not we need use resources.xml file again to locate this resource xml file.

<resourceXML name="shopperNotebook"

file="csr/ShopperGetProperties.xml" /&gt;

2. Modification:

2.1. Now, finally, at this “ShopperGetProperties.xml” we will find the panel definition where we are going to edit.

Between

<panel name="Address"

url="PropertyAddressView"

parameters="shrfnbr,locale"

helpKey="MC.optoolsCSR.shopperGetPropertiesAddressPanel.Help" />

<panel name="Contact"

url="PropertyContactView"

parameters="shrfnbr,locale"

helpKey="MC.optoolsCSR.shopperGetPropertiesContactPanel.Help" />

add

<panel name="listAllAddress"

url="ListAllAddressView"

parameters="shrfnbr,locale"

helpKey=" " />

this will add a button between Address and Contact.

2.2. Add custom properties

Open resource bundle by looking for ShopperActionB2C.xml, resourceBundle=”csr.userNLS”, to open

WC\properties\com\ibm\commerce\tools\csr\properties\userNLS.properties

Add:

listAllAddress = All Addresses

this will display as the button label.

2.3. Create a new view ListAllAddressView by creaeting jsp CommerceAccelerator\WebContent\tools\Sears\ListAllAddressDisplay.jsp

And define in struts-config-ext.xml

<forward className="com.ibm.commerce.struts.ECActionForward" name="ListAllAddressView" path="/tools/Sears/ListAllAddressDisplay.jsp">

<set-property property="resourceClassName" value="com.ibm.commerce.tools.command.ToolsForwardViewCommandImpl"/>

</forward>

<action path="/ListAllAddressView" type="com.ibm.commerce.struts.BaseAction">

<set-property property="https" value="0:1"/>

</action>

Create Access Control for the new view

insert into acaction (acaction_id, action) values ((SELECT MAX(acaction_id) + 1 from acaction), 'ListAllAddressView');

insert into acactactgp (acactgrp_id, acaction_id) values ((select acactgrp_id from acactgrp where groupname='CustomerServiceRepresentativeViews'),(select acaction_id from acaction where action='ListAllAddressView'));

Thursday, January 08, 2009

javax.mail.MessagingException: Could not connect to SMTP host: localhost, port: 25

Properties props = new Properties();
props.setProperty("mail.host",smtpHost);
props.setProperty("mail.smtp.host", smtpHost);
Session session = Session.getDefaultInstance(props, null);


The default mail session instance is sharable across the server.

If the session is not initialized, a new session instance will be created with the properties passing in.

However, if an instance does exist, it will be returned. The passing properties will be ignored.


If there are two separate applications running in the same App server, the default session will be shared.

Be careful of your session is initialized by the other application first, and cause your passing properties become useless.

To avoid this, try use:

Session session = Session.getInstance(props, null);


or, another way, to call the smtp server explicitly:

Transport trans = session.getTransport("smtp");
trans.connect(smtpHost,-1,null,null);
trans.sendMessage(msg,msg.getAllRecipients());
trans.close();