Weblogic WAR Deployment Error

It looks like weblogic throws this error when web application is deployed only as WAR. But it doesn't throw any exception when deployed as exploded.
weblogic.management.DeploymentException: Cannot set web app root system property when WAR file is not expanded - with nested exception:  [java.lang.IllegalStateException: Cannot set web app root system property when WAR file is not expanded].

There are two ways we can fix this issue when you still want to deploy as WAR.
1. Go to server admin console->Domain-> Web applications. Click the checkbox of Archived Real Path Enabled. This should make an entry into domain config.xml as below. or you can directly edit your domain config.xml and add the below entry.
       <web-app-container>
          <show-archived-real-path-enabled>true</show-archived-real-path-enabled>
       </web-app-container>
2. Second option is at webapp level by updating weblogic.xml as below:
      <container-descriptor>
         <show-archived-real-path-enabled>true</show-archived-real-path-enabled>
       </container-descriptor>
The value of <show-archived-real-path-enabled> set in the web app has precedence over the value set at the domain level. The default value of this property is false.  

ServletContext.getRealPath returns null

Another weird behavior from weblogic when webapp is deployed as WAR. ServletContext.getRealPath() returns null when deployed as WAR but it works ok when deployed as exploded. There are two ways we can fix this issue when you still want to deploy as WAR but would like to get over with this issue:
1. Go to server admin console->Domain-> Web applications. Click the checkbox of Archived Real Path Enabled. This should make an entry into domain config.xml as below.
       <web-app-container>
          <show-archived-real-path-enabled>true</show-archived-real-path-enabled>
       </web-app-container>

2. Second option is at webapp level by updating weblogic.xml as below:
      <container-descriptor>
         <show-archived-real-path-enabled>true</show-archived-real-path-enabled>
       </container-descriptor>
The value of <show-archived-real-path-enabled> set in the web app has precedence over the value set at the domain level. The default value of this property is false.

Java exception unknown source

Sometimes when debugging application we may run into this exception - Java Exception unknown source.
The possible reason could be when compiling the application, javac ant tasks omits debug option by defaut. So we will have to explicity set debug flag to true. See the javac ant task documentation for more info. You can mention some thing like below:
<target name="compile">
  <javac srcdir="${src.dir}" destdir="{dest.dir}." debug="on" debuglevel="lines,vars,source" />
</target>
Hope this helps.

Log4jConfigListener Deployment Issue

It looks like Spring framework's Log4jConfigListener is having an issue when webapp is deployed as WAR. Log4jConfigListener is defined in web.xml. I got the below error while deploying the application in weblogic 10.3.
weblogic.management.DeploymentException: Cannot set web app root system property when WAR file is not expanded - with nested exception:  [java.lang.IllegalStateException: Cannot set web app root system property when WAR file is not expanded].

The solution is deploy the WAR as exploded or don't use Log4jConfigListener. The spring framework documentation also says the WAR should be exploded.

There is some update here. There is a solution available to this without any code change. We just need to set "Archived Real Path Enabled" option checked. Please check this blog entry on how to enable.

Useful Links:

To read more articles on Weblogic, please click here.

ResourceUtils.getFile() bug in Spring Framework 2.0.8 with weblogic10.3

I cam across this weird problem which gave me really hard time for about 2-3 weeks. The issue is as below:
We use spring framework in one of our web applications. One of the java classes loads XMLs which reside in web-inf/classes folder. It uses ResourceUtils.getFile() method as below:
           File file = ResourceUtils.getFile("classpath://data-values.xml");
This method works fine when we deploy as exploded WAR in weblogic 10.3 but when we deploy as WAR, it gives FileNotFoundException. What weblogic does during WAR deployment(obviously it internally explodes) is, it puts all the files reside in web-inf/classes folder into jar called _wl_cls_gen.jar file and copies into web-inf/lib directory. This is where the problem during deployment as the java class was unable to read the xml and throwing FileNotFoundException.
        The exact error message is as below:
java.io.FileNotFoundException: class path resource [//data-values.xml] cannot be resolved to absolute file path because it does not reside in the file system: zip:C:/domains/devDomain/servers/AdminServer/tmp/_WL_user/testWebApp/8j5e1y/war/WEB-INF/lib/_wl_cls_gen.jar!/data-values.xml
           So I was looking to see if there is a way to tell weblogic to avoid generating this jar as my java classes were unable to load XMLs which resides in that jar file now. It looks like as for as my knowledge there may not be a way. Even I have asked the same question in oracle forums itself but that didn't help. Also when we googled we came across this issue in number of search results. Some say it is spring issue with ResourceUtils.getFile().
        Some suggested use different approach to load xmls. So one of our team members tried using  org.springframework.core.io.ClassPathResource which fixed the issue. The code snippet is as below:

      String xmlFile = "classpath://data-values.xml";

      final int index = StringUtils.lastIndexOf(xmlFile, "/") == -1 ? 0 : StringUtils.lastIndexOf(xmlFile, "/");
      final Resource resource = new ClassPathResource(StringUtils.substring(xmlFile, index, xmlFile.length()));
      final InputStream is = resource.getInputStream();
      try {
        final InputStreamReader reader = new InputStreamReader(is);
        try {
          final Document headerDoc = new SAXBuilder().build(reader);
        } finally {
          reader.close();
        }
      } finally {
        is.close();
      }

It looks like Spring's 2.0.8 version ResourceUtils.getFile() method is having a bug while loading xmls when you deploy as WAR in weblogic. But no issues when you deploy as exploded. But ClasspathResource seems to be working fine.

Weblogic portal content propagation using Ant tasks

Content propagation is the process of moving portal artifacts from from one domain environment to other usually from staging to production. This moving basically involves the contents from database & ldap.






Weblogic offers three ways to do this:
1. Using Weblogic workshop by creating propagation session.
2. Customized Ant scripts
3. Import/export utility.

When you use weblogic workshop, it involves a lot of manual tasks. Those manual tasks are error prone. I thought ant scripts are more effective as you have a lot of control and it is automated process. I never tried the third option. This blog will cover how to do propagation using ant scripts.

Pre-requests:
Both source & destination admin server should be running and should have same weblogic portal version. Ant environment variable needs to be set up.

How to set up Ant:
1. Create environment variabale ANT_HOME in your local machine with value ${BEA_HOME}\modules\org.apache.ant_1.6.5. Eg: if you installed in C drive, value would be C:\bea\modules\org.apache.ant_1.6.5
2. Create another variable called ANT_OPTS with value of -Xmx500M

Steps for propagation:
1. Create a folder called propagation from you planned to run scripts

2. Copy propagation.xml file from below into propagation folder.

propagation.xml:


<?xml version="1.0" ?>
<!-- ==================================================================== -->
<!-- Propagation Ant Script -->
<!-- Author        :        Ananth Kannan -->
<!-- Date        :        05/30/2008      -->
<!-- Title:       propagation.xml                                            -->
<!--                                                                         -->
<!-- Usage Notes:                                                            -->
<!--                                                                         -->
<!-- The normal sequence of using this script is to invoke the targets in    -->
<!-- the following order:                                                    -->
<!--                                                                         -->
<!-- ant pingSrc                                                             -->
<!-- ant pingDest                                                             -->
<!-- ant downloadSrc                                                         -->
<!-- ant validateSrc                                                         -->
<!-- ant downloadDest                                                        -->
<!-- ant validateDest                                                        -->
<!-- ant combine                                                             -->
<!-- ant commit                                                                 -->
<!-- ant uploadCombined                                                      -->
<!--                                                                         -->
<!-- ======================================================================= -->

<project name="Portal Propagation Ant Tasks" basedir="." default="usage">
    <property environment="env"/>

    <!-- Environment Settings -->
   
    <!-- Runtime: this variable must point to your install directory. -->
    <property name="deploy.dir" value="C:\bea\wlserver_10.0"/>

    <!-- Runtime: this variable must indicate where the files will be read/written. -->
    <property name="working.dir" value="C:\propagation"/>

    <!-- Source: -->
    <!--         Setup the variables that identify your source environment (staging, for example) -->
    <!--         These variables are explained below, or consult the Propagation Ant Task documentation. -->
    <property name="source.servlet.url" value="http://{src_admin_server}:7001/EAR_NamePropagation/inventorymanagement"/>
    <property name="source.admin.username" value="weblogic"/>
    <property name="source.admin.password" value="weblogic"/>
    <property name="source.allow.http" value="true"/>

    <!-- Destination: -->
    <!--         Setup the variables that identify your destination environment (production, for example) -->
    <!--         These variables are explained below, or consult the Propagation Ant Task documentation. -->
    <property name="dest.servlet.url" value="http://{dest_admin_server}:7001/EAR_NamePropagation/inventorymanagement"/>
    <property name="dest.admin.username" value="weblogic"/>
    <property name="dest.admin.password" value="weblogic"/>
    <property name="dest.allow.http" value="true"/>
   
    <path id="onlineTask.classpath">
        <pathelement location="${deploy.dir}/platform/lib/p13n/p13n_common.jar"/>
        <pathelement location="${deploy.dir}/portal/lib/propagation/propagation.jar"/>
        <pathelement location="${deploy.dir}/portal/lib/propagation/propagation_ant.jar"/>
        <pathelement location="${deploy.dir}/portal/lib/propagation/content_prop.jar"/>
        <pathelement location="${deploy.dir}/portal/lib/propagation/netuix_prop.jar"/>
    </path>
   
    <path id="offlineTask.classpath">
        <pathelement location="${deploy.dir}/platform/lib/p13n/p13n_common.jar"/>
        <pathelement location="${deploy.dir}/platform/lib/wlp/wsrp-common.jar"/>
        <pathelement location="${deploy.dir}/portal/lib/propagation/propagation.jar"/>
        <pathelement location="${deploy.dir}/portal/lib/propagation/propagation_ant.jar"/>
        <pathelement location="${deploy.dir}/portal/lib/propagation/content_prop.jar"/>
        <pathelement location="${deploy.dir}/portal/lib/propagation/netuix_prop.jar"/>
        <pathelement location="${deploy.dir}/server/lib/api.jar"/>
        <pathelement location="${deploy.dir}/../modules/com.bea.core.xml.beaxmlbeans_2.2.0.0.jar"/>
        <pathelement location="${deploy.dir}/../modules/com.bea.core.weblogic.stax_1.0.1.0.jar"/>
        <pathelement location="${deploy.dir}/../modules/com.bea.core.utils_1.0.1.0.jar"/>   
    </path>   

    <!--
        SERVLET.URL:
       
        The online Propagation ant tasks require that the Propagation servlet be deployed in the
        application. By default, Portal applications will include the Propagation application library
        module which deploys the Propagation web application. Look for the following in the application's
        META-INF/weblogic-application.xml
       
       <library-ref>
           <library-name>wlp-propagation-app-lib</library-name>
       </library-ref>
       <library-context-root-override>
           <context-root>propagation</context-root>
           <override-value>portalAppPropagation</override-value>
       </library-context-root-override>
      
       In this example, the Propagation application module has been included, and the Propagation
       web application which is normally at context root "propagation" has been overridden to listen
       to context path "portalAppPropagation". Therefore, the servletURL in this case would be:
      
       http://hostname:port/portalAppPropagation/inventorymanagement
      
       The Propagation servlet is deployed by default to map to "inventorymanagement".
     -->

    <!-- ==================================================================== -->
    <!-- Targets -->
    <!-- ==================================================================== -->


    <target name="usage" description="list of commands">
        <echo message="Usage Instructions:" />
        <echo message="Choose from this list of standard ant targets, or modify the build file to create your own." />
        <echo message="1.  pingSrc and pingDest - pings the server and application to make sure it is alive" />
        <echo message="2.  checkMutexSrc and checkMutexDest - determines if another user is working with the application" />
        <echo message="3.  lockSrc and lockDest - prevents admin changes on the src and dest system." />
        <echo message="4.  downloadSrc and downloadDest - creates src.zip and dest.zip files respectively" />
        <echo message="5.  validateSrc and validateDest - makes sure the src.zip and dest.zip files are good" />
        <echo message="6.  listScopes - lists the scopes in src.zip, for potential scoping of the differencing step" />
        <echo message="6a. listPolicies - lists the policies in src.zip, for potential polices for the differencing step" />
        <echo message="7.  search - finds nodes with a specific string in their name, to help verify the wanted node was exported" />
        <echo message="8.  diff - differences src.zip and dest.zip and writes the results to diff_cm.xml" />
        <echo message="9.  combine - combines src.zip and dest.zip into a new inventory, combined.zip" />
        <echo message="10. validateCombined - makes sure combined.zip is a good file" />
        <echo message="11. extractCombined - extracts the working artifacts out of combined.zip for viewing" />
        <echo message="12. insertCombined - inserts updated working artifacts into combined.zip" />
        <echo message="13. checkManualElections - Test for the presence of manual elections. Used as condition to determine if continue to upload/commit or quit." />
        <echo message="14. uploadCombined - uploads combined.zip to the destination server" />
        <echo message="15. commit or commitOpt - commits uploaded inventory on dest, either pessimistically or optimistically" />
        <echo message="16. unlockSrc and unlockDest - allows admin changes on the src and dest system again." />
        <echo message="17. electionsAdd and electionsSubtract - allows for algebraic operations on two changemanifest files." />
    </target>


    <!-- ONLINEPING TASK -->

    <taskdef name="onlinePing" classname="com.bea.propagation.ant.taskdefs.OnlinePingTask">
        <classpath refid="onlineTask.classpath"/>
    </taskdef>

    <target name="pingSrc" description="ping the server">
        <echo message="****** Start: pingSrc ******" />
        <onlinePing
            servletURL="${source.servlet.url}"
            username="${source.admin.username}"
            password="${source.admin.password}"
            allowHttp="${source.allow.http}"
        />
        <echo message="****** Finish: pingSrc ******" />
    </target>

    <target name="pingDest" description="ping the server">
        <echo message="****** Start: pingDest ******" />
        <onlinePing
            servletURL="${dest.servlet.url}"
            username="${dest.admin.username}"
            password="${dest.admin.password}"
            allowHttp="${dest.allow.http}"
        />
        <echo message="****** Finish: pingDest ******" />
    </target>

    <!-- alternate method of pinging using Condition Ant construct -->
    <target name="pingDestC1" description="ping the server">
        <echo message="****** Start: pingDestC1 ******" />
        <condition property="ping_success">
            <onlinePing
                servletURL="${dest.servlet.url}"
                username="${dest.admin.username}"
                password="${dest.admin.password}"
                allowHttp="${dest.allow.http}"
            />
        </condition>
        <antcall target="ping_success" />
        <echo message="****** Finish: pingDestC1 ******" />
    </target>
    <target name="ping_success" if="ping_success"><echo message="The server is available." /></target>


    <!-- ONLINEMUTEX TASK -->

    <taskdef name="onlineMutex" classname="com.bea.propagation.ant.taskdefs.OnlineCheckMutexTask">
        <classpath refid="onlineTask.classpath"/>
    </taskdef>

    <target name="checkMutexSrc" description="checks to see if the mutex is available">
        <echo message="****** Start: checkMutexSrc ******" />
        <onlineMutex
            servletURL="${source.servlet.url}"
            username="${source.admin.username}"
            password="${source.admin.password}"
            allowHttp="${source.allow.http}"
            failOnError="false"
            retryTimes="3"
        />
        <echo message="****** Finish: checkMutexSrc ******" />
    </target>

    <target name="checkMutexDest"  description="checks to see if the mutex is available">
        <echo message="****** Start: checkMutexDest ******" />
        <onlineMutex
            servletURL="${dest.servlet.url}"
            username="${dest.admin.username}"
            password="${dest.admin.password}"
            allowHttp="${dest.allow.http}"
            failOnError="false"
            retryTimes="10"
        />
        <echo message="****** Finish: checkMutexDest ******" />
    </target>

    <!-- alternate method of checking the mutex using Condition Ant construct -->
    <target name="checkMutexDestC1" description="checks to see if the mutex is available">
        <echo message="****** Start: checkMutexDestC1 ******" />
        <condition property="mutex_success">
            <onlineMutex
                servletURL="${dest.servlet.url}"
                username="${dest.admin.username}"
                password="${dest.admin.password}"
                allowHttp="${dest.allow.http}"
                failOnError="false"
                retryTimes="10"
            />
        </condition>
        <antcall target="mutex_success" />
        <echo message="****** Finish: checkMutexDestC1 ******" />
    </target>
    <target name="mutex_success" if="mutex_success"><echo message="The mutex is available." /></target>


    <!-- onlineMaintenanceMode TASK -->

    <taskdef name="onlineMaintenanceMode" classname="com.bea.propagation.ant.taskdefs.OnlineMaintenanceModeTask">
        <classpath refid="onlineTask.classpath"/>
    </taskdef>

    <target name="lockSrc" description="put the server into maintenance mode">
        <echo message="****** Start: lockSrc ******" />
        <onlineMaintenanceMode
            servletURL="${source.servlet.url}"
            username="${source.admin.username}"
            password="${source.admin.password}"
            allowHttp="${source.allow.http}"
            enable="true"
        />
        <echo message="****** Finish: lockSrc ******" />
    </target>

    <target name="lockDest" description="put the server into maintenance mode">
        <echo message="****** Start: lockDest ******" />
        <onlineMaintenanceMode
            servletURL="${dest.servlet.url}"
            username="${dest.admin.username}"
            password="${dest.admin.password}"
            allowHttp="${dest.allow.http}"
            enable="true"
        />
        <echo message="****** Finish: lockDest ******" />
    </target>

    <!-- alternate method of locking using Condition Ant construct -->
    <target name="lockDestC1" description="put the server into maintenance mode">
        <condition property="lock_success">
            <onlineMaintenanceMode
                servletURL="${dest.servlet.url}"
                username="${dest.admin.username}"
                password="${dest.admin.password}"
                allowHttp="${dest.allow.http}"
                enable="true"
            />
        </condition>
        <antcall target="lock_success" />
    </target>
    <target name="lock_success" if="lock_success"><echo message="Maintenance mode has been toggled." /></target>


    <!-- ONLINEDOWNLOAD TASK -->

    <taskdef name="onlineDownload" classname="com.bea.propagation.ant.taskdefs.OnlineDownloadTask">
        <classpath refid="onlineTask.classpath"/>
    </taskdef>

    <target name="downloadSrc">
        <echo message="****** Start: downloadSrc ******" />
        <delete file="${working.dir}/src.zip" quiet="true" />
        <delete file="${working.dir}/downloadSrc.log" quiet="true" />
        <onlineDownload
            servletURL="${source.servlet.url}"
            username="${source.admin.username}"
            password="${source.admin.password}"
            allowHttp="${source.allow.http}"
            failOnError="true"
            outputInventoryFile="${working.dir}/src.zip"
            logFile="${working.dir}/downloadSrc.log"
        >
            <modifier name="cm_exportPolicy" value="lastPublished" />
            <modifier name="allowMaintenanceModeDisabled" value="true"/>
            <modifier name="allowSecurityOutOfSync" value="true"/>
        </onlineDownload>
        <echo message="****** Finish: downloadSrc ******" />
        <echo message="****** Please check :: src.zip is downloaded into ******${working.dir}" />
    </target>

    <target name="downloadSrcRemote">
        <echo message="****** Start: downloadSrcRemote ******" />
        <delete file="${working.dir}/src.zip" quiet="true" />
        <delete file="${working.dir}/downloadSrcRemote.log" quiet="true" />
        <onlineDownload
            servletURL="${source.servlet.url}"
            username="${source.admin.username}"
            password="${source.admin.password}"
            allowHttp="${source.allow.http}"
            failOnError="true"
            outputToServerFileSystem="true"
            outputInventoryFile="D:\TEMP\prop_test\src.zip"
            logFile="${working.dir}/downloadSrcRemote.log"
        >
            <modifier name="allowMaintenanceModeDisabled" value="true"/>
        </onlineDownload>
        <echo message="****** Finish: downloadSrcRemote ******" />
    </target>

    <target name="downloadDest">
        <echo message="****** Start: downloadDest ******" />
        <delete file="${working.dir}/dest.zip" quiet="true" />
        <delete file="${working.dir}/downloadDest.log" quiet="true" />
        <onlineDownload
            servletURL="${dest.servlet.url}"
            username="${dest.admin.username}"
            password="${dest.admin.password}"
            allowHttp="${dest.allow.http}"
            outputInventoryFile="${working.dir}/dest.zip"
            logFile="${working.dir}/downloadDest.log"
        >
            <modifier name="allowMaintenanceModeDisabled" value="true"/>
            <modifier name="allowSecurityOutOfSync" value="true"/>

        </onlineDownload>
        <echo message="****** Finish: downloadDest ******" />
    </target>


    <!-- OFFLINEVALIDATE TASK -->

    <taskdef name="offlineValidate" classname="com.bea.propagation.ant.taskdefs.OfflineValidateTask">
        <classpath refid="offlineTask.classpath"/>
    </taskdef>

    <target name="validateSrc" description="valid inventory, with logging">
        <echo message="****** Start: validateSrc ******" />
        <delete file="${working.dir}/validateSrc_log.txt" quiet="true" />
        <delete file="${working.dir}/validateSrc_verboselog.txt" quiet="true" />

        <offlineValidate
            sourceFile="${working.dir}/src.zip"
            logFile="${working.dir}/validateSrc_log.txt"
            verboseLogFile="${working.dir}/validateSrc_verboselog.txt"
        />
        <echo message="****** Finish: validateSrc ******" />
    </target>

    <target name="validateDest" description="validates to see if an inventory file is a valid inventory">
        <echo message="****** Start: validateDest ******" />
        <delete file="${working.dir}/validateDest_log.txt" quiet="true" />
        <delete file="${working.dir}/validateDest_verboselog.txt" quiet="true" />

        <offlineValidate
            sourceFile="${working.dir}/dest.zip"
            logFile="${working.dir}/validateDest_log.txt"
            verboseLogFile="${working.dir}/validateDest_verboselog.txt"
        />
        <echo message="****** Finish: validateDest ******" />
    </target>

    <!-- alternate method of validating using Condition Ant construct -->
    <target name="validateDestC1" description="validates to see if an inventory file is a valid inventory">
        <echo message="****** Start: validateC1 ******" />
        <condition property="validate_success">
            <offlineValidate
                sourceFile="${working.dir}/dest.zip"
            />
        </condition>

        <antcall target="validate_success" />

        <echo message="****** Finish: validateC1 ******" />
    </target>
    <target name="validate_success" if="validate_success"><echo message="The validation succeeded." /></target>


    <!-- OFFLINELISTSCOPES TASK -->

    <taskdef name="offlineListScopes" classname="com.bea.propagation.ant.taskdefs.OfflineListScopesTask">
        <classpath refid="offlineTask.classpath"/>
    </taskdef>

    <target name="listScopes" description="lists the scopes found in the source inventory">
        <echo message="****** Start: listScopes ******" />
        <delete file="${working.dir}/listScopes_scopes.properties" quiet="true" />
        <delete file="${working.dir}/listScopes_log.txt" quiet="true" />
        <delete file="${working.dir}/listScopes_verboselog.txt" quiet="true" />
        <mkdir dir="${working.dir}/scopes"/>

        <offlineListScopes
            sourceFile="${working.dir}/src.zip"
            scopeFile="${working.dir}/scopes/listScopes_scopes.properties"
            logFile="${working.dir}/scopes/listScopes_log.txt"
            verboseLogFile="${working.dir}/scopes/listScopes_verboselog.txt"
        />
        <echo message="****** Finish: listScopes ****** under ${working.dir}/scopes" />
    </target>

    <!-- OFFLINELISTPOLICIES TASK -->

    <taskdef name="offlineListPolicies" classname="com.bea.propagation.ant.taskdefs.OfflineListPoliciesTask">
        <classpath refid="offlineTask.classpath"/>
    </taskdef>

    <target name="listPolicies" description="lists the scopes found in the source inventory">
        <echo message="****** Start: listPolicies ******" />
        <delete file="${working.dir}/listPolicies_policies.properties" quiet="true" />
        <delete file="${working.dir}/listPolicies_log.txt" quiet="true" />
        <delete file="${working.dir}/listPolicies_verboselog.txt" quiet="true" />
        <mkdir dir="${working.dir}/policies"/>

        <offlineListPolicies
            sourceFile="${working.dir}/src.zip"
            policyFile="${working.dir}/policies/listPolicies_policies.properties"
            globalAddFlag="true"
            globalUpdateFlag="false"
            globalDeleteFlag="true"
            logFile="${working.dir}/policies/listPolicies_log.txt"
            verboseLogFile="${working.dir}/policies/listPolicies_verboselog.txt"
        />
        <echo message="****** Finish: listPolicies ****** under ${working.dir}/policies" />
    </target>

    <!-- OFFLINESEARCH TASK -->

    <taskdef name="offlineSearch" classname="com.bea.propagation.ant.taskdefs.OfflineSearchTask">
        <classpath refid="offlineTask.classpath"/>
    </taskdef>

    <target name="search" description="finds the nodes that contain the search string in the name">
        <echo message="****** Start: search ******" />
        <delete file="${working.dir}/search.txt" quiet="true" />
        <delete file="${working.dir}/search_log.txt" quiet="true" />
        <delete file="${working.dir}/search_verboselog.txt" quiet="true" />

        <offlineSearch
            searchString="Global"
            sourceFile="${working.dir}/src.zip"
            listFile="${working.dir}/search.txt"
            logFile="${working.dir}/search_log.txt"
            verboseLogFile="${working.dir}/search_verboselog.txt"
        />
        <echo message="****** Finish: search ******" />
    </target>

    <!-- alternate method of searching using Condition Ant construct -->
    <target name="searchC1" description="finds the nodes that contain the search string in the name">
        <echo message="****** Start: searchC1 ******" />
        <condition property="search_success">
            <offlineSearch
                searchString="Global"
                sourceFile="${working.dir}/src.zip"
            />
        </condition>

        <antcall target="search_success" />

        <echo message="****** Finish: searchC1 ******" />
    </target>
    <target name="search_success" if="search_success"><echo message="The search succeeded." /></target>


    <!-- OFFLINEDIFF TASK -->

    <taskdef name="offlineDiff" classname="com.bea.propagation.ant.taskdefs.OfflineDiffTask">
        <classpath refid="offlineTask.classpath"/>
    </taskdef>

    <target name="diff" description="compare two inventories with logging">
        <echo message="****** Start: diff ******" />
        <delete file="${working.dir}/diff_cm.xml" quiet="true" />
        <delete file="${working.dir}/diff_log.txt" quiet="true" />
        <delete file="${working.dir}/diff_verboselog.txt" quiet="true" />

        <offlineDiff
            sourceFile="${working.dir}/src.zip"
            destFile="${working.dir}/dest.zip"
            changeManifestFile="${working.dir}/diff_cm.xml"
            logFile="${working.dir}/diff_log.txt"
            verboseLogFile="${working.dir}/diff_verboselog.txt"
        />
        <echo message="****** Finish: diff ******" />
    </target>

    <!-- alternate method of diffing using Condition Ant construct -->
    <target name="diffC1" description="compare two inventories">
        <echo message="****** Start: diffC1 ******" />
        <delete file="${working.dir}/diffC1_cm.xml" quiet="true" />
        <condition property="diff_success">
            <offlineDiff
                sourceFile="${working.dir}/src.zip"
                destFile="${working.dir}/dest.zip"
                changeManifestFile="${working.dir}/diffC1_cm.xml"
            />
        </condition>
        <antcall target="diff_success" />

        <echo message="****** Finish: diffC1 ******" />
    </target>
    <target name="diff_success" if="diff_success"><echo message="The two inventories are different." /></target>


    <!-- OFFLINECOMBINE TASK -->

    <taskdef name="offlineCombine" classname="com.bea.propagation.ant.taskdefs.OfflineCombineTask">
        <classpath refid="offlineTask.classpath"/>
    </taskdef>

    <target name="combine" description="Combine two inventories with logging">
        <echo message="****** Start: combine ******" />
        <delete file="${working.dir}/combined.zip" quiet="true" />
        <delete file="${working.dir}/combine_cm.xml" quiet="true" />
        <delete file="${working.dir}/combine_log.txt" quiet="true" />
        <delete file="${working.dir}/combine_verboselog.txt" quiet="true" />

        <offlineCombine
            sourceFile="${working.dir}/src.zip"
            destFile="${working.dir}/dest.zip"
            combinedInventoryFile="${working.dir}/combined.zip"
            changeManifestFile="${working.dir}/combine_cm.xml"
            logFile="${working.dir}/combine_log.txt"
            verboseLogFile="${working.dir}/combine_verboselog.txt"
        />
        <echo message="****** Finish: combine ******" />
    </target>
   
    <target name="combineWithPolicy" description="Combine two inventories using policy file">
        <echo message="****** Start: combine ******" />
        <delete file="${working.dir}/combined.zip" quiet="true" />
        <delete file="${working.dir}/combine_cm.xml" quiet="true" />
        <delete file="${working.dir}/combine_log.txt" quiet="true" />
        <delete file="${working.dir}/combine_verboselog.txt" quiet="true" />

        <offlineCombine
            sourceFile="${working.dir}/src.zip"
            destFile="${working.dir}/dest.zip"
            combinedInventoryFile="${working.dir}/combined.zip"
            policiesFile = "${working.dir}/policy.properties"
            changeManifestFile="${working.dir}/combine_cm.xml"
            logFile="${working.dir}/combine_log.txt"
            verboseLogFile="${working.dir}/combine_verboselog.txt"
        />
        <echo message="****** Finish: combine ******" />
    </target>

    <target name="combineWithScope" description="Combine two inventories using scope file">
        <echo message="****** Start: combine ******" />
        <delete file="${working.dir}/combined.zip" quiet="true" />
        <delete file="${working.dir}/combine_cm.xml" quiet="true" />
        <delete file="${working.dir}/combine_log.txt" quiet="true" />
        <delete file="${working.dir}/combine_verboselog.txt" quiet="true" />

        <offlineCombine
            sourceFile="${working.dir}/src.zip"
            destFile="${working.dir}/dest.zip"
            combinedInventoryFile="${working.dir}/combined.zip"
            scopeFile = "${working.dir}/singlescope.properties"
            changeManifestFile="${working.dir}/combine_cm.xml"
            logFile="${working.dir}/combine_log.txt"
            verboseLogFile="${working.dir}/combine_verboselog.txt"
        />
        <echo message="****** Finish: combine ******" />
    </target>
   
    <!-- OFFLINEVALIDATE TASK -->

    <target name="validateCombined" description="valid inventory, with no logging">
        <echo message="****** Start: validateCombined ******" />
        <delete file="${working.dir}/validateCombined_log.txt" quiet="true" />
        <delete file="${working.dir}/validateCombined_verboselog.txt" quiet="true" />

        <offlineValidate
            sourceFile="${working.dir}/combined.zip"
            logFile="${working.dir}/validateCombined_log.txt"
            verboseLogFile="${working.dir}/validateCombined_verboselog.txt"
        />
        <echo message="****** Finish: validateCombined ******" />
    </target>


    <!-- OFFLINEEXTRACT TASK -->

    <taskdef name="offlineExtract" classname="com.bea.propagation.ant.taskdefs.OfflineExtractTask">
        <classpath refid="offlineTask.classpath"/>
    </taskdef>

    <target name="extractCombined" description="gather resources from the combined inventory">
        <echo message="****** Start: extractCombined ******" />
        <delete file="${working.dir}/extract/extractCombined_export.properties" quiet="true" />
        <delete file="${working.dir}/extract/extractCombined_scope.properties" quiet="true" />
        <delete file="${working.dir}/extract/extractCombined_policy.properties" quiet="true" />
        <delete file="${working.dir}/extract/extractCombined_change.xml" quiet="true" />
        <delete file="${working.dir}/extract/extractCombined_log.txt" quiet="true" />
        <delete file="${working.dir}/extract/extractCombined_verboselog.txt" quiet="true" />
        <mkdir dir="${working.dir}/extract"/>

        <offlineExtract
            sourceFile="${working.dir}/combined.zip"
            exportFile="${working.dir}/extract/extractCombined_export.properties"
            policyFile="${working.dir}/extract/extractCombined_policy.properties"
            changeManifestFile="${working.dir}/extract/extractCombined_change.xml"
            logFile="${working.dir}/extract/extractCombined_log.txt"
            verboseLogFile="${working.dir}/extract/extractCombined_verboselog.txt"
        />
        <echo message="****** Finish: extractCombined ******" />
    </target>


    <!-- OFFLINEALGEBRA TASK -->

    <taskdef name="offlineAlgebra" classname="com.bea.propagation.ant.taskdefs.OfflineElectionAlgebraTask">
        <classpath refid="offlineTask.classpath"/>
    </taskdef>

    <target name="electionsAdd" description="add the two election lists">
        <echo message="****** Start: electionsAdd ******" />
        <delete file="${working.dir}/addedElections.xml" quiet="true" />

        <offlineAlgebra
            electionList1File="${working.dir}/elections1.xml"
            electionList2File="${working.dir}/elections2.xml"
            operation="add"
            outputFile="${working.dir}/addedElections.xml"
        />
        <echo message="****** Finish: electionsAdd ******" />
    </target>

    <target name="electionsSubtract" description="subtract the two election lists">
        <echo message="****** Start: electionsSubtract ******" />
        <delete file="${working.dir}/subtractedElections.xml" quiet="true" />

        <offlineAlgebra
            electionList1File="${working.dir}/elections1.xml"
            electionList2File="${working.dir}/elections2.xml"
            operation="subtract"
            outputFile="${working.dir}/subtractedElections.xml"
        />
        <echo message="****** Finish: electionsSubtract ******" />
    </target>


    <!-- OFFLINEINSERT TASK -->

    <taskdef name="offlineInsert" classname="com.bea.propagation.ant.taskdefs.OfflineInsertTask">
        <classpath refid="offlineTask.classpath"/>
    </taskdef>

    <target name="insertCombined" description="insert resources into the combined inventory">
        <echo message="****** Start: insertCombined ******" />
        <delete file="${working.dir}/newCombined.zip" quiet="true" />

        <offlineInsert
            sourceFile="${working.dir}/combined.zip"
            policyFile="${working.dir}/extractCombined_policy.properties"
            changeManifestFile="${working.dir}/extractCombined_change.xml"
            outputFile="${working.dir}/newCombined.zip"
        />
        <echo message="****** Finish: insertCombined ******" />
    </target>

    <!-- OFFLINE Check for manual elections -->
   
    <taskdef name="offlineCheckForManualElections" classname="com.bea.propagation.ant.taskdefs.OfflineCheckManualElectionsTask">
        <classpath refid="offlineTask.classpath"/>
    </taskdef>
   
    <target name="checkManualElections" description="check if there is manual elections in combined inventory or change manifest XML">
        <echo message="****** Start: checkManualElections ******" />
        <offlineCheckForManualElections
                changeManifestFile="${working.dir}/combine_cm.xml"/>
        <echo message="****** Finish: checkManualElections ******" />
    </target>
   
    <target name="checkManualElectionsC1" description="check if there is manual elections in combined inventory or change manifest XML">
        <echo message="****** Start: checkManualElectionsC1 ******" />
        <condition property="hasManualElections">
            <offlineCheckForManualElections
                sourceFile="${working.dir}/combined.zip"/>
        </condition>
        <antcall target="continuePropagation" />
        <echo message="****** Finish: checkManualElectionsC1 ******" />
    </target>
    <target name="continuePropagation" unless="hasManualElections">
        <echo message="We could continue propagation" />
    </target>

    <!-- ONLINEUPLOAD TASK -->

    <taskdef name="onlineUpload" classname="com.bea.propagation.ant.taskdefs.OnlineUploadTask">
        <classpath refid="onlineTask.classpath"/>
    </taskdef>

    <target name="uploadCombined">
        <echo message="****** Start: upload ******" />
        <onlineUpload
            servletURL="${dest.servlet.url}"
            username="${dest.admin.username}"
            password="${dest.admin.password}"
            allowHttp="${dest.allow.http}"
            sourceFile="${working.dir}/combined.zip"
        />
        <echo message="****** Finish: upload ******" />
    </target>

    <target name="uploadRemote">
        <echo message="****** Start: uploadRemote ******" />
        <onlineUpload
            servletURL="${dest.servlet.url}"
            username="${dest.admin.username}"
            password="${dest.admin.password}"
            allowHttp="${dest.allow.http}"
            readFromServerFileSystem="true"
            sourceFile="D:\TEMP\prop_test\src.zip"
        />
        <echo message="****** Finish: uploadRemote ******" />
    </target>

    <target name="uploadSrc">
        <echo message="****** Start: uploadSrc ******" />
        <onlineUpload
            servletURL="${dest.servlet.url}"
            username="${dest.admin.username}"
            password="${dest.admin.password}"
            allowHttp="${dest.allow.http}"
            sourceFile="${working.dir}/src.zip"
        />
        <echo message="****** Finish: uploadSrc ******" />
    </target>

    <target name="uploadDest">
        <echo message="****** Start: uploadDest ******" />
        <onlineUpload
            servletURL="${dest.servlet.url}"
            username="${dest.admin.username}"
            password="${dest.admin.password}"
            allowHttp="${dest.allow.http}"
            sourceFile="${working.dir}/dest.zip"
        />
        <echo message="****** Finish: uploadDest ******" />
    </target>

    <!-- ONLINECOMMIT TASK -->

    <taskdef name="onlineCommit" classname="com.bea.propagation.ant.taskdefs.OnlineCommitTask">
        <classpath refid="onlineTask.classpath"/>
    </taskdef>

    <target name="commit">
        <echo message="****** Start: commit ******" />
        <delete file="${working.dir}/commit.log" quiet="true" />
        <onlineCommit
            servletURL="${dest.servlet.url}"
            username="${dest.admin.username}"
            password="${dest.admin.password}"
            allowHttp="${dest.allow.http}"
            logFile="${working.dir}/commit.log"
        >
            <modifier name="differenceStrategy" value="pessimistic" />
            <modifier name="cm_checkinComment" value="My sample checkin comment." />
            <modifier name="allowMaintenanceModeDisabled" value="true"/>
            <modifier name="allowSecurityOutOfSync" value="true"/>
        </onlineCommit>
        <echo message="****** Finish: commit ******" />
    </target>

    <target name="commitOpt">
        <echo message="****** Start: commitOpt ******" />
        <delete file="${working.dir}/commitOpt.log" quiet="true" />
        <onlineCommit
            servletURL="${dest.servlet.url}"
            username="${dest.admin.username}"
            password="${dest.admin.password}"
            allowHttp="${dest.allow.http}"
            logFile="${working.dir}/commitOpt.log"
        >
            <modifier name="differenceStrategy" value="optimistic" />
            <modifier name="cm_checkinComment" value="My sample checkin comment." />
            <modifier name="allowMaintenanceModeDisabled" value="true"/>
        </onlineCommit>
        <echo message="****** Finish: commitOpt ******" />
    </target>

    <!-- set scope file in commit task -->
    <target name="commitWithScope">
        <echo message="****** Start: commitScope ******" />
        <delete file="${working.dir}/commitScope.log" quiet="true" />
        <onlineCommit
            servletURL="${dest.servlet.url}"
            username="${dest.admin.username}"
            password="${dest.admin.password}"
            allowHttp="${dest.allow.http}"
            scopeFile="${working.dir}/singlescope.properties"
            logFile="${working.dir}/commitScope.log"
        >
            <modifier name="differenceStrategy" value="pessimistic" />
            <modifier name="cm_checkinComment" value="My sample checkin comment." />
            <modifier name="allowMaintenanceModeDisabled" value="true"/>
        </onlineCommit>
        <echo message="****** Finish: commitOpt ******" />
    </target>
   
    <!-- ONLINEMAINTENANCEMODE TASK -->

    <target name="unlockSrc" description="disable maintenance mode on the src server">
        <echo message="****** Start: unlockSrc ******" />
        <onlineMaintenanceMode
            servletURL="${source.servlet.url}"
            username="${source.admin.username}"
            password="${source.admin.password}"
            allowHttp="${source.allow.http}"
            enable="false"
        />
        <echo message="****** Finish: unlockSrc ******" />
    </target>

    <target name="unlockDest" description="disable maintenance mode on the dest server">
        <echo message="****** Start: unlockDest ******" />
        <onlineMaintenanceMode
            servletURL="${dest.servlet.url}"
            username="${dest.admin.username}"
            password="${dest.admin.password}"
            allowHttp="${dest.allow.http}"
            enable="false"
        />
        <echo message="****** Finish: unlockDest ******" />
    </target>


    <target name="startProp"
        description="Starts the propagation operation.."
        depends="pingSrc, pingDest, downloadSrc, validateSrc, downloadDest, validateDest, combine, uploadCombined, commit">

        <echo message="****** Start: startProp ******" />
        <echo message="****** Start: startProp ******" />

        <echo message="****** Finish: startProp ******" />

    </target>

</project>

3. Create a folder called scopes under propagation.

4. In propagation.xml file. Make sure deploy.dir value is pointing to right BEA installation path on your local drive. For eg, C:\bea\wlserver_10.0"

5. Working.dir should point to propagation dir.

6. source.servlet.url is your source server. Where you copy the data from. For e.g, if you copy from INT box, then it should be http://source_server:7001/portlAppEARPropagation/inventorymanagement

7. Once you have all set up, run the following command from your propagation folder:
ant –f propagation.xml pingSrc
If the above command fails, source server is not running. re-start it.

8. Same thing goes with destination as well. try this command:
ant –f propagation.xml pingDest

9. Type to generate scopes file by generating sourcezip first: ant -f propagation.xml downloadSrc
then run this command: ant -f propagation.xml listScopes
This should create a file listScopes.properties under propagation/scopes folder. To know more about scopes, please visit BEA documentation.

10. Once source and destination server running run the propagation command:
ant –f propagation.xml startProp
It should propagate the data from source to destination.

Important links:
Propagation Ant Task Reference
Propagation Tips and Best Practices

What is the difference between streaming portal(desktop) and file based portal?

I have come across this question many times while working at client site from co-workers, clients and infrastructure folks - what is the difference between streaming portal and file based portal? Well, during portal development process we create .portal file in workshop. This is basically just a template in which more books, pages, portlets can be added. The .portal file is XML based and rendered as "single file mode". This file is mainly for development purpose and should not be used in the production though you can access it in production as well. You can not apply any entitlements or user customization as no data base involved in .portal template.

The streaming portal(desktop) is created out of .portal template using weblogic portal admin tool. A single portal template can have any number of desktops. A desktop contains all the portlets, content, shells, layouts, and look and feel elements necessary to create individual user views of a portal. For eg, assume I have a requirement from three different clients to show some functionality of a portal. I don't want to create a three .portal template though I could, but I would like to have three different desktops with similar functionality but with different "look-and-feel". So I go to weblogic portal admin tool create a desktop called sample1 for client 1. sample 2 for client 2 with different look-and-feel. sample 3 for client 3 again with different look & f. Oh yes! Look and feel can be applied at run time ie while creating desktop itself. Also I can add/remove portlets if I want to for any desktop. I can also add/remove any book/page at run time as well. So what I have done is created 3 different desktops but with a different look-and-feel per client.

When I create a desktop from a .portal template, the desktop is decoupled from the template, and modifications to the .portal file do not affect the desktop, and vice versa. For example, when you change a desktop's look and feel in the WebLogic Portal Administration Console, the change is made only to the desktop, not to the original .portal file. When you view a desktop with in a browser, the desktop is rendered in "streaming mode"  from data base.

P.S: If your portal application does not need any entitlements or personalizations and it is simple, static portal then file based portal is the best choice. File based portals give better peformance and propagation to other environments is also easy.

Weblogic as windows service error

There is a bug in BEA documentation for creating weblogic server instance as window service. The doumentation URL is here  

The example script (for creating weblogic as window service) in the documentation shows we need to have ADMIN_URL as below:

set ADMIN_URL=http://adminserver:7501

Actually we do NOT need to mention this url in the manual script. I had this URL mentioned and end up getting the error below.

java.rmi.NoSuchObjectException: The object identified by: '31' could not be found. Either it was has not been exported or it has been collected by the distributed garbage collector.

I removed this entry ran the script again. It worked.

To know more info on creating or installing weblogic as a window service,  please see this blog entry

How to implement breadcrumb in Weblogic Portal

Breadcrumbs is one of the cool features of weblogic portal framework for UI navigation. We have successfully implemented this functionality in one our portal applications. That was based on weblogic portal 10.2 version. I think it should work with weblogic portal 10.3 as well. Let me know if you are running into any issues with the code. This jsp should be included as part of page.jsp.

Breadcrumbs.jsp:
<%@ page language="java" contentType="text/html;charset=UTF-8"%>
<%@ page import="com.bea.netuix.servlets.controls.window.WindowPresentationContext,
                 com.bea.netuix.servlets.controls.window.TitlebarPresentationContext,
                 java.util.ArrayList,
                 java.util.Iterator,
                 com.bea.portlet.PageURL,
                 com.bea.netuix.servlets.controls.page.BookPresentationContext,
                 com.bea.netuix.servlets.controls.page.PagePresentationContext,
                 com.bea.netuix.servlets.controls.window.WindowCapabilities"
%>
<%@ page session="false"%>
<%@ taglib uri="http://www.bea.com/servers/portal/tags/netuix/render" prefix="render" %>

<%--
    This is the JSP for the showing breadcrumbs in XYZ Eagle portal.
    It is part of the skeleton file page.jsp.

    Implementation based on WebLogic Portal 10.2.

    Author ::      Ananth Kannan
--%>

<%
    ArrayList breadcrumbTitles = new ArrayList();
    ArrayList breadcrumbURLs = new ArrayList();
    boolean isHidden = false;

    BookPresentationContext book = BookPresentationContext.getBookPresentationContext(request);
    PagePresentationContext pageCtx = PagePresentationContext.getPagePresentationContext(request);

    if (!(book.getDefaultPage().equals(pageCtx.getDefinitionLabel())))
    {
        breadcrumbTitles.add(book.getTitle());
        breadcrumbURLs.add(PageURL.createPageURL(request,response,book.getDefaultPage()).toString());
    }
   
        PagePresentationContext parentPage = book.getParentPagePresentationContext();
        while (parentPage != null)
        {
            breadcrumbTitles.add(parentPage.getTitle());

            if (parentPage instanceof BookPresentationContext)
            {
                BookPresentationContext parentBook = (BookPresentationContext)parentPage;
                breadcrumbURLs.add(PageURL.createPageURL(request, response,  parentBook.getDefaultPage()).toString());
            }
            else
            {
                breadcrumbURLs.add(PageURL.createPageURL(request, response, parentPage.getDefinitionLabel()).toString());
            }
   
            parentPage = parentPage.getParentPagePresentationContext();
        }
%>
         

<%            
            //DO NOT SHOW BREADCRUMBS IN MAIN HOME PAGE and also in hidden page
            if (pageCtx.isHidden())
            {
            }
            else
            {               
%>
     <ul class="breadcrumbs">
<%
        for (int i = breadcrumbTitles.size() - 1; i >= 0; i--)
        {
            if (((String)breadcrumbTitles.get(i)).equalsIgnoreCase("My Main Book")) {
                    breadcrumbTitles.set(i, "My Home");
            }
           
%>
            <li class="first"><a href="<%=breadcrumbURLs.get(i) %>" ><%=breadcrumbTitles.get(i)%></a></li> <img src="<render:getSkinPath imageName="/arrow_right.gif" />" />&nbsp;  <%
        }
%>
<%
    }
%>
        </ul>

How to create weblogic domain template using weblogic template builder?

Domain templates are used to create(or extend weblogic server domains) with pre-configured resources such as JDBC, security realms, external libraries, log4j components. So when you create new domain you do not need to go to server console and create resources such as data source, etc.  While creating domain by using template you will have those resources configured already for you.

Lets say, you have a team of 10 people and you like everybody to have same configuration, then create a template share with the team. Even it is very much useful if you have new member in the team.

Domain templates can be built in many ways. This blog covers how to built using weblogic domain template builder.

Lets get started.

Step 1:

Go to Start Menu->All programs->weblogic10gR3->Tools->Domain Template Builder
or

go to c:\bea\wlserver_10.3\common\bin in command prompt. and type config_builder.cmd












Step 2:

Select create a domain template. If you are creating template for the first time.
Select create extension template if you are extending a existing template.

We will go with create domain template.

Step 3: Select a Template tab. Click on Basic Weblogic Server domain option. Click next











Step 4: Enter the name of template and other info. Click next.












Step 5:  Using Add Button, Select libraries you want to add under lib folder. copy jdbc data sources you would like to have under config/jdbc folder. If you want to have log4j configuration, copy log4j.xml under domain_root folder.

Click next










 Step 6: Select data base for the domain and click next.











Step 7: Enter Admin Server Name and port numbers. Click next.










Step 8: Enter username and password. Click next. Select No if you don want to add users/groups/roles











Step 9: Click next










Step 10: Click next












Step 11: Click next











Step 12: Click Create











Step 13: Click done.










This will create a domain template(jar file) which can be used to create domain.

When creating domain using domain config wizard, do select  2nd option which is "base this domain on existing template" as shown below and browse the template jar file and continue.











Good luck. Please let me know if you have any issues.