Other XP Bloggers

Thursday, June 25, 2009

Maven And Weblogic

Goal

This post is a follow-up to a previous entry on running Weblogic Ant tasks without calling setDomainEnv. The purpose is to perform the same actions from Maven. Fortunately, the weblogic-maven-plugin does not have the same requirement for setting environment variables from outside the build script. Unfortunately, development on the mojos appears to be a few versions behind the latest release of Weblogic. The code and examples here demonstrate how to use this Maven plug-in to run goals for deloying a WAR, building a web service skeleton and generating a web service client for Weblogic 10.3.

Listing the Applications Deployed to Weblogic

We can begin by creating an m2eclipse Maven project, timezra.blog.maven.weblogic, with the webapp-jee5 archetype. The Wizard materializes a simple hello world application that will be packaged as a WAR.

In order to list the applications deployed to Weblogic, we first need to setup a Weblogic domain if we do not already have one. For this example, we can create one called maven_example using the defaults provided by the Configuration Wizard.There is already a good starting point for configuring the weblogic-maven-plugin in our pom.xml, but for 10.3 these instructions are incomplete. One problem becomes evident when we compose an Eclipse Run Configuration for the weblogic:listapps goal (being sure to use the External Maven 2.10 Runtime).

In our console, we would see a stack trace.

java.lang.NoClassDefFoundError: weblogic/utils/Debug at weblogic.Deployer.(Deployer.java:23) at org.codehaus.mojo.weblogic.DeployMojoBase.executeDeployer(DeployMojoBase.java:509) at org.codehaus.mojo.weblogic.ListAppsMojo.execute(ListAppsMojo.java:51) at org.apache.maven.plugin.DefaultPluginManager.executeMojo(DefaultPluginManager.java:483) at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoals(DefaultLifecycleExecutor.java:678) at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeStandaloneGoal(DefaultLifecycleExecutor.java:553) at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoal(DefaultLifecycleExecutor.java:523) at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoalAndHandleFailures(DefaultLifecycleExecutor.java:371) at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeTaskSegments(DefaultLifecycleExecutor.java:332) at org.apache.maven.lifecycle.DefaultLifecycleExecutor.execute(DefaultLifecycleExecutor.java:181) at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:356) at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:137) at org.apache.maven.cli.MavenCli.main(MavenCli.java:356) 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:597) at org.codehaus.classworlds.Launcher.launchEnhanced(Launcher.java:315) at org.codehaus.classworlds.Launcher.launch(Launcher.java:255) at org.codehaus.classworlds.Launcher.mainWithExitCode(Launcher.java:430) at org.codehaus.classworlds.Launcher.main(Launcher.java:375)Caused by: java.lang.ClassNotFoundException: weblogic.utils.Debug at java.net.URLClassLoader$1.run(URLClassLoader.java:200) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:188) at java.lang.ClassLoader.loadClass(ClassLoader.java:307) at org.codehaus.classworlds.RealmClassLoader.loadClassDirect(RealmClassLoader.java:195) at org.codehaus.classworlds.DefaultClassRealm.loadClass(DefaultClassRealm.java:255) at org.codehaus.classworlds.DefaultClassRealm.loadClass(DefaultClassRealm.java:274) at org.codehaus.classworlds.RealmClassLoader.loadClass(RealmClassLoader.java:214) at java.lang.ClassLoader.loadClass(ClassLoader.java:252) at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:320) ... 21 more

We must manually install a few libraries in addition to those the Wiki entry lists into our local Maven repository.

The output from our Eclipse weblogic:listapps launcher should now show

There is no application to list.

Deploying a WAR

Our Maven archetype has already configured the packaging for our application, and building the WAR is not Weblogic-specific. Deploying to the AdminServer is, however.If we were to create another Eclipse Run Configuration, here called full_deploy, which calls the package and deploy goals, we would see an error.

check that the following section of the pom.xml is present and correct:

<distributionManagement> <!-- use the following if you're not using a snapshot version. --> <repository> <id>repo</id> <name>Repository Name</name> <url>scp://host/path/to/repo</url> </repository> <!-- use the following if you ARE using a snapshot version. --> <snapshotRepository> <id>repo</id> <name>Repository Name</name> <url>scp://host/path/to/repo</url> </snapshotRepository></distributionManagement>

For this example, it is sufficient for the distribution manager to point to our local repository and to hook into the weblogic:deploy goal in our pom.xml.

The output from our Eclipse weblogic:listapps launcher should now show

timezra.blog.maven.weblogic Number of Applications Found : 1

If we open http://localhost:7001/timezra.blog.maven.weblogic/ in a browser, we will see Hello World!

Compile A Web Service

The trial-and-error process for deploying a Web Service is very similar to publishing our packaged WAR: setup project dependencies, implement the service in Java, call the weblogic:jwsc goal, work out any unresolved dependencies and deploy the application.Our web service will depend on annotations from the javax.jws library, which is provided by Weblogic. We can install this JAR, as above.

Now we can run a new Eclipse launcher that calls weblogic:jwsc in the same way that we setup launchers for weblogic:listapps. We see that the web service artifacts are correctly generated in the target directory, and the URL for the new web service is correctly merged into the target/timezra.blog.maven.weblogic/WEB-INF/web.xml. Unfortunately, if we package and deploy the application, this merging of information in the web.xml will be overwritten with the contents of src/main/webapp/WEB-INF/web.xml (Try it if you do not believe me, if you did not follow or if you would like to discover for yourself why this is the case!). Fortunately, there is a way to automate the generation of web service and the correct packaging of the artifacts and compiled sources with some extra configuration in the pom.xml.

We can view the published WSDL in a browser at address http://localhost:7001/timezra.blog.maven.weblogic/Echo?WSDL and we can use our favorite web service client application (here, I use soapUI) to run a few tests.

Generate a Web Service Client

Now that we have a deployment infrastructure and a working web service, we can create a client for that service. The current version of the weblogic-maven-plugin (2.9.2-SNAPSHOT) supports two goals for generating a web service client, weblogic:clientgen and weblogic:clientgen9. Unfortunately, neither works with Weblogic 10. If we were to call weblogic:clientgen9, for example, we would see an error similar to this:

The only remedy I have seen to this issue is to modify the weblogic-maven-plugin and to install it in a local repository. After importing the project into Eclipse, we can simply apply this patch to the project root.

NB: This patch has been submitted as a bug report. Please comment or vote on this bug to get it pushed through.We will deploy this update to the plug-in (here, with version number 2.9.3-SNAPSHOT) by simply running the goal as Maven install from Eclipse.

Now that we have a working client generation goal in our updated and installed plug-in, again, we will need to register a few more Weblogic libraries for our project.

We can add these new project and plug-in dependencies, along with necessary configuration parameters to the pom.xml. Generally, I do not automate client generation, as published WSDLs infrequently change. You may have different project requirements, however.

@OverrideprotectedvoiddoGet(finalHttpServletRequestreq,finalHttpServletResponseresp)throwsServletException,IOException{finalStringecho=newEchoService().say("Is there anybody in there?");req.setAttribute("echo",echo);req.getRequestDispatcher("echo.jsp").forward(req,resp);}}

Our view, src/main/webapp/echo.jsp, will simply show the result of calling the service.

Now, when we run full_deploy and open http://localhost:7001/timezra.blog.maven.weblogic/IsAnybodyThere in a browser, we will see the message "Is there anybody in there? ... there? ... there?".

Conclusion

While it certainly would have been possible to hook the Maven Ant plugin to the build script presented in a previous post for executing tasks that disguise the need to run the setDomainEnv script, this post provides a different approach through the existing weblogic-maven-plugin and thus eliminates the need for manipulating setDomainEnv entirely with a manageable amount of configuration in the pom.xml.

30 comments:

Tim,Thank you for the detailed explanation. I tried to follow it but ended up with the exception while running weblogic:jwsc. Here it is: java.lang.RuntimeException: Unknown javadoc problem: result=1, root=null:JAM: error - In doclet class com.bea.util.jam.internal.javadoc.JavadocRunner_150, method languageVersion must return LanguageVersion.

Thank you for the feedback and the question.From a cursory glance I would ask what version your $JAVA_HOME points to? From the error, I would guess 1.5. If this is the case, could you try using a 1.6 JDK?I have not seen that particular error, but for the weblogic:jwsc goal, Weblogic is using some internal com.sun javadoc APIs.I hope this helps! Let me know either way.

It doesn't seem to be the weblogic plugin problem. I tried to invoke the jwsc task via antrun plugin and got the same error. However, if I just call the ant script from the antrun plugin, everything works fine.Paul

Thanks for the feedback! I will be setting something similar up for a customer as a spike for an eventual transition from Ant to Maven. Fortunately, I have Nexus setup, so the manual installation of weblogic libraries in the local repository should be eliminated for the rest of my team. If you are setting up Maven and Weblogic for a team, you might consider using Nexus or Artifactory to make things slightly easier.

Hi Jon,Thanks for the feedback. In fact, the bug and patch (http://jira.codehaus.org/browse/MWEBLOGIC-3) were submitted to jira at the time this blog entry was originally posted.Let me know if you need anything else,---Tim---

We submitted a patch for 2.9.3-SNAPSHOT. there is also a perl script in the apt source you can use that will get all of the weblogic artifacts setup for you so you don't have to go through too much pain.

Thanks Tim. I am using Maven component in Hudson to build code checked in to SVN repository.I was searching for a solution to this error: [ERROR] BUILD ERROR[INFO] ------------------------------------------------------------------------[INFO] Failed to configure plugin parameters for: org.apache.maven.plugins:maven-deploy-plugin:2.4

check that the following section of the pom.xml is present and correct:

repo Repository Name scp://host/path/to/repo

repo Repository Name scp://host/path/to/repo

Your pom.xml file helped me resolve it. The url tag as you mentioned below fixed the issue and the build was successful again!

I have tried the same by using Nexus repository. I have downloaded the weblogic plugin and tried running JWSC task I am geting the following error.

Can you please look into this error.BUILD FAILED/wls_domains/CIT/cruisecontrol-bin-2.8.3/util/temp/build.xml:235: Deployment descriptor: /wls_domains/CIT/cruisecontrol-bin-2.8.3/util/temp/temp/_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: /wls_domains/CIT/cruisecontrol-bin-2.8.3/util/temp/temp/_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: /wls_domains/CIT/cruisecontrol-bin-2.8.3/util/temp/temp/_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)

I uploaded file on one of my online storage: http://chomikuj.pl/sebekk23/Java/WLS1035/WebServicesMaven/pom,1115580899.xml. If anyone find error please send me email and I upadte this pom for others ;).

I have a problem with WebService client generated by weblogic:clientgen. When i'm trying to invoke him i getting following errorjava.rmi.RemoteException: unable to set value on the holder class; nested exception is: java.lang.NoSuchFieldException: value at pl.nbp.mailsms.client.Mailsmsservice_PortType_Stub.test(Mailsmsservice_PortType_Stub.java:29) at pl.nbp.mailsms.client.TestClient.main(TestClient.java:21)Caused by: java.lang.NoSuchFieldException: value at java.lang.Class.getField(Class.java:1520) at weblogic.webservice.core.rpc.StubImpl._setHolderValue(StubImpl.java:358) at weblogic.webservice.core.rpc.StubImpl._invoke(StubImpl.java:323) at pl.nbp.mailsms.client.Mailsmsservice_PortType_Stub.test(Mailsmsservice_PortType_Stub.java:27) ... 1 more

Another question:How to force maven to include all resources (like weblogic.xml, wsdl etc.) to jar when packaging multimodule project ?I have structure like this:POM project- EAR - project- WAR - project with JSF and other stuff- JAR (here i want to put all of WebServices)

Did you put all the resources that you want to put in the JAR into the src/main/resources directory of the JAR project? I am not sure offhand why this approach would not work. Or am I misunderstanding your requirement?