Monday, October 8, 2012

Creating new bespoke web Application on Websphere Commerce





Have you ever tried creating new web application in websphere commerce workspace that would be just like any other web application like Stores or CommerceAccelrator and be able to use underlying command framework, EJBs and access control policies? Though this requirement sounds very rare but will make you to think for a while as to how to make this happen.  This was a requirement with one of our customer who wanted to move a legacy application on websphere commerce platform that would do some stuff for order management. Initial thought was to use CommerceAccelrator(Tools Framework) to achieve the same but since IBM is eventually going to dis continue with Tools framework, it was decided to create a new web app in websphere commerce workspace and I was again selected to this POC.  After so many trial and errors I managed to do this and again, I decided to document the steps for future references. I am not sure if this is the best way to do it but POC was successful for me, there may be some even better way to achieve the same.
I named my web application MyWebApp and here the steps for creating it.
1.       Open Websphere Commerce Developer and Click File → New → Other  and select Dynamic




2.       Type 'MyWebApp' as  name of the project. Make sure WC is selected in EAR Membership section and click Next.




3.       On the Configure web module settings page change the context Root to /webapp/wcs/mywebapp and click Finish. This will create a MyWebApp  project in the workspace.


4.       Right Click MyWebApp project and select properties. In the properties window click on Java Build Path and select Projects tab. Click on Add and select WebsphereCommerceServerExtensionLogic project and click Ok.


5.       Right Click MyWebApp project and select properties. In the properties window click on Java Build Path and select Order and Export tab. Select the check box EAR Libraries. Click Ok.


6.       Right Click MyWebApp project and select properties. In the properties window click on Project Facets and select checkboxes against JSTL and Struts. Leave the default ones selected. Click Ok.


7.       Copy struts-config.xml, struts-config-ext.xml from stores project and paste under MyWebApp →  WebContent → WEBINF folder. This is somewhat to make steps easy, otherwise you may want to create just one struts-config file for entire web project. Also, the struts-config files needs to be cleaned later to remove un wanted entries. I copied them because I wanted to inherit the use of error pages from Stores project.


8.       Copy error pages (error.jsp, error404.jsp, GenericApplicationError.jsp, GenericApplicationErrorXML.jsp, GenericError.jsp, GenericJSPPageError.jsp, GenericSystemError.jsp, GenericSystemErrorXML.jsp )  from stores project and paste under MyWebApp → WebContent folder . You can change the styling and contents of these pages later.


9.       Open MyWebApp/WebContent/WEB-INF/web.xml and replace its contents with following configurations.
Web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" 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>
      MyWebApp</display-name>
    <servlet>
        <description/>
        <display-name>
                  MyWebApp Request Servlet
            </display-name>
        <icon>
            <small-icon/>
            <large-icon/>
        </icon>
        <servlet-name>MyWebApp Request Servlet</servlet-name>
        <servlet-class>com.ibm.commerce.struts.ECActionServlet</servlet-class>
        <init-param>
            <param-name>config</param-name>
            <param-value>/WEB-INF/struts-config.xml,/WEB-INF/struts-config-ext.xml</param-value>
        </init-param>
        <init-param>
            <param-name>detail</param-name>
            <param-value>2</param-value>
        </init-param>
        <init-param>
            <param-name>validate</param-name>
            <param-value>true</param-value>
        </init-param>
        <init-param>
            <param-name>configFactory</param-name>
            <param-value>com.ibm.commerce.struts.config.UpdatableModuleConfigFactory</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>MyWebApp Request Servlet</servlet-name>
        <url-pattern>/servlet/*</url-pattern>
    </servlet-mapping>
    <servlet>
        <description/>
        <display-name>CompositionRequestServlet</display-name>
        <icon>
            <small-icon/>
            <large-icon/>
        </icon>
        <servlet-name>CompositionRequestServlet</servlet-name>
        <servlet-class>com.ibm.commerce.messaging.composer.servlet.CompositionRequestServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>CompositionRequestServlet</servlet-name>
        <url-pattern>/IBM.WC.Compose/*</url-pattern>
    </servlet-mapping>
    <filter>
        <icon/>
        <filter-name>RuntimeServletFilter</filter-name>
        <filter-class>com.ibm.commerce.webcontroller.RuntimeServletFilter</filter-class>
        <init-param>
            <param-name>ServletName</param-name>
            <param-value>CommerceAccelerator</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>RuntimeServletFilter</filter-name>
        <servlet-name>MyWebApp Request Servlet</servlet-name>
    </filter-mapping>
    <filter>
        <icon/>
        <filter-name>CacheFilter</filter-name>
        <filter-class>com.ibm.commerce.dynacache.filter.CacheFilter</filter-class>
        <init-param>
            <param-name>ServletName</param-name>
            <param-value>MyWebAppRequestServlet</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>CacheFilter</filter-name>
        <servlet-name>MyWebApp Request Servlet</servlet-name>
    </filter-mapping>
    <filter>
        <icon/>
        <filter-name>CompositionFilter</filter-name>
        <filter-class>com.ibm.commerce.messaging.composer.servlet.CompositionFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>CompositionFilter</filter-name>
        <servlet-name>CompositionRequestServlet</servlet-name>
    </filter-mapping>
    <ejb-local-ref>
        <ejb-ref-name>ejb/BusinessContextServiceWrapperLocal</ejb-ref-name>
        <ejb-ref-type>Session</ejb-ref-type>
        <local-home>com.ibm.commerce.component.contextservice.objects.BusinessContextServiceWrapperLocalHome</local-home>
        <local>com.ibm.commerce.component.contextservice.objects.BusinessContextServiceWrapperLocal</local>
        <ejb-link>Enablement-BusinessContextEngineInterface.jar#BusinessContextServiceWrapper</ejb-link>
    </ejb-local-ref>
    <ejb-local-ref>
        <ejb-ref-name>ejb/MemberGroupMemberService</ejb-ref-name>
        <ejb-ref-type>Session</ejb-ref-type>
        <local-home>com.ibm.commerce.user.objects.service.MemberGroupMemberServiceLocalHome</local-home>
        <local>com.ibm.commerce.user.objects.service.MemberGroupMemberServiceLocal</local>
        <ejb-link>Member-MemberManagementData.jar#MemberGroupMemberService</ejb-link>
    </ejb-local-ref>
    <ejb-local-ref>
        <ejb-ref-name>ejb/ContextManagement</ejb-ref-name>
        <ejb-ref-type>Entity</ejb-ref-type>
        <local-home>com.ibm.commerce.context.objects.ContextManagementLocalHome</local-home>
        <local>com.ibm.commerce.context.objects.ContextManagementLocal</local>
        <ejb-link>Enablement-BusinessContextEngineData.jar#ContextManagement</ejb-link>
    </ejb-local-ref>
    <ejb-local-ref>
        <ejb-ref-name>ejb/ContextData</ejb-ref-name>
        <ejb-ref-type>Entity</ejb-ref-type>
        <local-home>com.ibm.commerce.context.objects.ContextDataLocalHome</local-home>
        <local>com.ibm.commerce.context.objects.ContextDataLocal</local>
        <ejb-link>Enablement-BusinessContextEngineData.jar#ContextData</ejb-link>
    </ejb-local-ref>
    <jsp-config>
        <taglib>
            <taglib-uri>flow.tld</taglib-uri>
            <taglib-location>/WEB-INF/flow.tld</taglib-location>
        </taglib>
    </jsp-config>
</web-app>

10.   Open MyWebApp/WebContent/WEB-INF/ibm-web-bnd.xml and replace its contents with following configuration.

<?xml version="1.0" encoding="UTF-8"?>
<web-bnd
      xmlns="http://websphere.ibm.com/xml/ns/javaee"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://websphere.ibm.com/xml/ns/javaee http://websphere.ibm.com/xml/ns/javaee/ibm-web-bnd_1_0.xsd"
      version="1.0">

      <virtual-host name="WC_default_host" />

      <ejb-ref name="ejb/BusinessContextServiceWrapperLocal" binding-name="ejb/com/ibm/commerce/component/contextservice/objects/BusinessContextServiceWrapperHome" />
      <ejb-ref name="ejb/MemberGroupMemberService" binding-name="ejb/com/ibm/commerce/user/objects/service/MemberGroupMemberServiceLocalHome" />
      <ejb-ref name="ejb/ContextManagement" binding-name="ejb/com/ibm/commerce/context/objects/ContextManagementHome" />
      <ejb-ref name="ejb/ContextData" binding-name="ejb/com/ibm/commerce/context/objects/ContextDataHome" />
</web-bnd>

11.   Open MyWebApp/WebContent/WEB-INF/ibm-web-ext.xml and replace its contents with following configuration.

<?xml version="1.0" encoding="UTF-8"?>
<web-ext
      xmlns="http://websphere.ibm.com/xml/ns/javaee"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://websphere.ibm.com/xml/ns/javaee http://websphere.ibm.com/xml/ns/javaee/ibm-web-ext_1_0.xsd"
      version="1.0">

      <default-error-page uri="error.jsp"/>
      <file-serving-attribute name="file.serving.patterns.deny" value="WEB-INF/* META-INF/*" />
      <jsp-attribute name="keepgenerated" value="true" />
      <reload-interval value="0"/>
      <context-root uri="/webapp/wcs/mywebapp" />
      <enable-directory-browsing value="false"/>
      <enable-file-serving value="true"/>
      <enable-reloading value="true"/>
      <enable-serving-servlets-by-class-name value="false" />

</web-ext>

12.   Open WC/xml/config/wc-server.xml and locate the Tag <WebModule> and add following module.


                 <Module contextPath="/webapp/wcs/mywebapp"
                      fileServletEnabled="false"
                      name="MyWebApp"
                      urlMappingPath="/servlet" webAlias="/wcsmywebapp">
                      <InitParameters
                        adapters="XML/HTTP, BrowserAdapter"
                        contextSetName="MyWebApp" handleDoubleClick="true"/>
                      <URLRedirectFilter enable="true"/>
               </Module>

13.  In wc-server.xml locate the tags <NonSecurePort and <SecurePort and add following within each tag.

<Alias name="wcs" value="C:\IBM\WCDE_P~1/workspace/MyWebApp/WebContent"/>


14.  Open WC/META-INF/application.xml and loacate  Teleconnect.war. Ensure value  of  <context-root> is /webapp/wcs/mywebapp.


   <module id="Module_1349726114303">
      <web>
            <web-uri>MyWebApp.war</web-uri>
            <context-root>/webapp/wcs/mywebapp</context-root>
      </web>
</module>

15.   To test your new web application and ensure it inherits all websphere commerce behavior, Create a folder TestView under  MyWebApp/WebContent and create a new jsp under it. Place some test contents in the jsp.
16.   Open MyWebApp/WebContent/WEB-INF/struts-config.xml and add following entries to it.

<forward className="com.ibm.commerce.struts.ECActionForward"
            name="myTestView" path="/TestView/MyTestJsp.jsp">
        </forward>
<action path="/myTestView" type="com.ibm.commerce.struts.BaseAction">
        </action>

17.  Clean and build entire work space. Restart and publish  Websphere Commerce Test server.

18.   http://localhost/webapp/wcs/mywebapp/servlet/myTestView . If you have not disabled the access control policy, note that you will be presented with a page saying you do not have authority to access this view. Now add the following

19.   Add the access control policy for the new view, refresh the registry. You will see the view with your page.

Similarly you can try with accessing controller commands, do some logic and redirecting to new views.


Hope this helps !!!!

Thanks
Sajjad