Wednesday, July 30, 2008

Run Weblogic Ant Tasks Without setDomainEnv

Suppose we need to run one of the Weblogic ant tasks for deployment of an application, such as wldeploy, or for webservice support, such as clientgen, jwsc or wsdlc (or any task that requires the environment to be set previously by executing the setDomainEnv script). Suppose we need to execute such an ant task in one command without having set the domain environment previously with this script, say from inside Eclipse. The problem turned out to be more frustrating than I would have preferred, especially since calling the .cmd and then calling ant from another .bat file was problematic. The solution is straightforward, and we can walk through it using the wldeploy example.

The first step is to setup some properties describing your environment, i.e., the location of the weblogic installation, the weblogic domain installation and the weblogic classpath. Assuming we are using weblogic 10 with a domain called aDomain, those properties will look something like this:

<?xml version="1.0"?>
<project ....>
    ....
    <property name="my.home" location="C:/bea" />
    <property name="my.domain" location="${my.home}/user_projects/domains/aDomain" />
    <path id="weblogic.classpath">
        <fileset dir="${my.home}/wlserver_10.0/server/lib">
            <include name="*.jar" />
        </fileset>
    </path>
    ....
</project>



Next, we define the wldeploy task:

<project ....>
    ....
    <taskdef name="wldeploy" 
        classname="weblogic.ant.taskdefs.management.WLDeploy">
        <classpath refid="weblogic.classpath" />
    </taskdef>
    ....
</project>



Now we can create a macro for running any weblogic ant task that requires the environment be set through the setDomainEnv script:

<project ....>
    ....
    <macrodef name="run-domain-task">
        <attribute name="task.name" />
        <sequential>
            <property name="runner" location="${my.domain}/bin/run_domain_task.cmd" />
            <copy file="${my.domain}/bin/setDomainEnv.cmd" tofile="${runner}" overwrite="true" />
            <concat append="true" destfile="${runner}">
                  ant -f "${ant.file}" @{task.name}</concat>
            <exec executable="${runner}" />
        </sequential>
    </macrodef>
    ....
</project>



This macro takes as input a target, such as deploy-to-domain below. It copies the setDomainEnv.cmd to a runner script and appends a command to call the input target from ant. In this way, the domain environment will be set properly before the weblogic-specific task runs.

We can now create a target to be called from the runner deployed in the macro:

<project ....>
    ....
    <target name="deploy-to-domain">
      <wldeploy action="deploy" .... />
    </target>
    ....
</project>



Finally, we add a public target that we call directly or that our Continuous Integration system can run when it has finished building our enterprise application.

<project ....>
    ....
    <target name="deploy">
        <run-domain-task task.name="deploy-to-domain" />
    </target>
    ....
</project>



Ideally, I would prefer to set the environment directly through Ant instead of through the script. As a quick solution, and because setDomainEnv is generated based on a particular installation of a domain, the solution works well in the general case. If anyone is aware of a generic, fully Ant-based solution to this problem, I would certainly like to hear about it.
I would also recommend moving away from Ant and towards Maven2 when at all possible. These instructions should be a good starting point for migrating toward a Maven2 build and deployment solution for Weblogic.

17 comments:

Sanjay said...

Great post. Saved me a lot of grief.

Tim Myer said...

Hi Sanjay,
Thank you for the feedback, and I am glad the post helped.
---Tim---

Per said...

Hi,
Your post also helped me a lot. I am still struggeling with getting the errorcode from the exec task though. I have tried failonerror="true", but always gets "Build Successful" even if the ant task run from run-domain-task failes. Any advice regarding this would really be appreciated.

Tim Myer said...

Hi Per,
Have you tried evaluating the "errorproperty" attribute of the "exec" task? For example, if you were to replace the line
....
<exec executable="${runner}" />
....
with
....
<exec executable="${runner}" errorproperty="error_property" />
<condition property="error_occurred">
    <matches string="${error_property}" pattern="BUILD\s+FAILED" />
</condition>
<fail if="error_occurred"/>
....
would that give the result that you need?
I hope that helps. Let me know.
---Tim---

Santosh said...

Thanks Tim,

Very good Post.
BTW, Do you have maven version of it?..

Tim Myer said...

Hi Santosh,
Thanks for the feedback. I have not put together a post for doing this in Maven but you have gotten the gears in my head turning, and I thank you for that.... If you get to it before I do, let me know what you come up with :)
---Tim---

Santosh said...

Sure Tim,

Will give it a shot.

Tim Myer said...

Hi Santosh,
It was not as straightforward as I would have hoped, but if you look here, you will find the Maven instructions:

http://timezra.blogspot.com/2009/06/maven-and-weblogic.html

I hope that helps, and any feedback is much appreciated.
Thanks.

---Tim---

Brian said...

Hi Tim,

Great post. I was able to get it workig from Eclipse with the examples you've provided.

Now according to your post, you're using the setDomainEnv.cmd defined in your domain. But in the Weblogic Ant documentation, they say to use the setWLSEnv.cmd defined in {weblogic home}/wlserver_10.3/server/bin

Question then. Which should I be using and when?

And one more question. When running in a Linux environment, would I be using the same type of macrodef to execute the setWLSEnv.sh or could I just run the setWLSEnv.sh script before the Ant script is executed?

Thanks again for your post.

Tim Myer said...

Hi Brian,

Interesting questions. The setDomainEnv.cmd referenced in the post sets environment variables for a specific WebLogic domain. The setWLSEnv.cmd is global for the WebLogic installation. Since the post describes a way to deploy a web application to a specific domain, I chose to use the setDomainEnv.cmd route. I would be curious to hear about your experience using the setWLSEnv.cmd.

Also, I would imagine that, if you were to use the setWLSEnv.sh, it would just be a matter of changing the path in the macro call. If you were to run setWLSEnv.sh outside of Ant, you would encounter the same problem I had when running setDomainEnv.cmd and the Ant script separately (from inside Eclipse, for example).

I hope that helps and would be interested to hear what you discover.
---Tim---

Halwa Raj said...

Hey great resource. This is actually a time saver.

Saved me a lot of grief as well.

Thanks alot for the guide.

Tim Myer said...

Thanks for the feedback, Halwa! If you come across any improvements, please let me know.

---Tim---

shekar said...

can i how do you do without giving a bea home..... as bea is not installed in my local system. I need to deploy into remote system from my local.
I need to generate war file from JWSC task.
All the other tasks can be declared with the weblogic.jar task but JWSC task need weblogic.jar and also some other jars like xbean and webservices.jar.
Anyway i added all those jar into my ant classpath but still I getting error.

[AntUtil.deleteDir] Deleting directory /var/tmp/_927vxb

BUILD FAILED
/wls_domains/CIT/cruisecontrol-bin-2.8.3/util/Ivy/build.xml:231: Deployment descriptor: /var/tmp/_927vxb/web.xml does not exist.
at weblogic.wsee.tools.anttasks.JwscTask.execute(JwscTask.java:184)
at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:288)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:105)
at org.apache.tools.ant.Task.perform(Task.java:348)
at org.apache.tools.ant.Target.execute(Target.java:357)
at org.apache.tools.ant.Target.performTasks(Target.java:385)
at org.apache.tools.ant.Project.executeSortedTargets(Project.java:1329)
at org.apache.tools.ant.Project.executeTarget(Project.java:1298)
at org.apache.tools.ant.helper.DefaultExecutor.executeTargets(DefaultExecutor.java:41)
at org.apache.tools.ant.Project.executeTargets(Project.java:1181)
at org.apache.tools.ant.Main.runBuild(Main.java:698)
at org.apache.tools.ant.Main.startAnt(Main.java:199)
at org.apache.tools.ant.launch.Launcher.run(Launcher.java:257)
at org.apache.tools.ant.launch.Launcher.main(Launcher.java:104)
Caused by: Deployment descriptor: /var/tmp/_927vxb/web.xml does not exist.
at org.apache.tools.ant.taskdefs.War.setWebxml(War.java:95)
at weblogic.wsee.tools.anttasks.JwscTask.jar(JwscTask.java:397)
at weblogic.wsee.tools.anttasks.JwscTask.pkg(JwscTask.java:331)
at weblogic.wsee.tools.anttasks.JwscTask.execute(JwscTask.java:166)
... 17 more
--- Nested Exception ---
Deployment descriptor: /var/tmp/_927vxb/web.xml does not exist.
at org.apache.tools.ant.taskdefs.War.setWebxml(War.java:95)
at weblogic.wsee.tools.anttasks.JwscTask.jar(JwscTask.java:397)
at weblogic.wsee.tools.anttasks.JwscTask.pkg(JwscTask.java:331)
at weblogic.wsee.tools.anttasks.JwscTask.execute(JwscTask.java:166)
at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:288)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:105)
at org.apache.tools.ant.Task.perform(Task.java:348)
at org.apache.tools.ant.Target.execute(Target.java:357)
at org.apache.tools.ant.Target.performTasks(Target.java:385)
at org.apache.tools.ant.Project.executeSortedTargets(Project.java:1329)
at org.apache.tools.ant.Project.executeTarget(Project.java:1298)
at org.apache.tools.ant.helper.DefaultExecutor.executeTargets(DefaultExecutor.java:41)
at org.apache.tools.ant.Project.executeTargets(Project.java:1181)
at org.apache.tools.ant.Main.runBuild(Main.java:698)
at org.apache.tools.ant.Main.startAnt(Main.java:199)
at org.apache.tools.ant.launch.Launcher.run(Launcher.java:257)
at org.apache.tools.ant.launch.Launcher.main(Launcher.java:104)

Tim Myer said...

Hi shekar,

Thank you for the question. As I do not have experience with how cruise or Ivy manage dependencies, I am not sure exactly what might be causing the problem that you are seeing.
Perhaps you might have more luck using Maven: http://timezra.blogspot.com/2009/06/maven-and-weblogic.html

I hope that helps,
---Tim---

ceaserme said...

Great Post. Saw this after 4 hours of grief :( but a happy ending

Tim Myer said...

Awesome! Thanks for the feedback, ceaserme.

Krishnanunni B said...

thank buddy..