weblogic

Weblogic Plugin to Set Deployment Order

WebLogic Server 12 has updates to the plugin that allow features such as being able to start/stop servers as well as run WLST scripting. The reason the WLST scripting is a beneficial feature is that the plugin is being used deploy all assets to a target environment (like wars, optional packages, and resources). In deploying all these resources through a build script, it becomes necessary to set the deployment order when assets have a dependency on a resource already being available prior to the asset being started during deployment or start-up of the managed server.

In order to modify the deployment order, a WLST script has to be used because the WebLogic Server 12 plugin does not support setting the deployment order through the maven script. So in order to utilize the newer WebLogic Server 12 maven plugin, it an install of WebLogic Server 12 so that it can utilize the install for running WLST scripts and other functioanility.

In the use case, the servers that exist within the environments is running 11g, however, in order to take advantage of this new feature, the build management system needs access to WebLogic Server 12c. As mentioned previously, this means that WebLogic Server 12 is installed on the build management box (in this case Hudson), so that the Hudson jobs have access to the install for WLST. The tests were ran utilizing the 12c version of the plugin to modify deployment orders on the 11g install and it worked. The only problem with running WLST scripts through Hudson builds is that doing multiple WLST scripts means opening a session with WebLogic Server and then closing that session, multiple times. This overhead is a memory hog and ultimately crashed the Hudson box. So the code/scripting is there to utilize the deployment order, but because of resource constraints, this functionality isn’t currently being used.

The following are the steps I took: 1) Installed WebLogic Server 12c to a local folder WLS_12C_MIDDLEWARE_PATH on the build server 2) Followed all steps from http://docs.oracle.com/cd/E24329_01/web.1211/e24368/maven.htm#CHEFAEBI for apache-maven-2.2.x. 3) Started the target Weblogic server 11g at (11g-IP-addr):7001 4) Edited a project pom.xml for deploying the war:

1
2
</p>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemalocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelversion>4.0.0</modelversion> <groupid>com.oracle.test</groupid> <artifactid>sample2</artifactid><packaging>war</packaging> <version>1.0-SNAPSHOT</version> <name>sample2 Maven Webapp</name> <url>http://maven.apache.org</url> <dependencies> <dependency> <groupid>junit</groupid> <artifactid>junit</artifactid> <version>3.8.1</version> <scope>test</scope> </dependency> </dependencies> <build> <finalname>sample-war</finalname><plugins><plugin> <groupid>org.apache.maven.plugins</groupid> <artifactid>maven-compiler-plugin</artifactid> <configuration> <source>1.6 <target>1.6</target> </configuration> </plugin><plugin> <groupid>com.oracle.weblogic</groupid> <artifactid>wls-maven-plugin</artifactid> <version>12.1.1.0</version> <configuration> <adminurl>t3://(local-IP):7001</adminurl> <user>weblogic</user><password>weblogic1</password> <upload>true</upload> <action>deploy</action> <remote>false</remote> <verbose>true</verbose> <source>target/sample-war-10.war <name>sample-war-10</name> </configuration> <executions> <execution><phase>install</phase> <goals> <goal>deploy</goal> <goal>undeploy</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </project>

5) Ran a maven command based on the pom for deploying sample-war-10.war:

1
 mvn wls:deploy -DmiddlewareHome=(WLS_12C_MIDDLEWARE_PATH)

I had to use -DmiddlewareHome because the element in pom.xml didn’t work. 6) Created the following WLST script for changing the deployment order (changeOrder.py):

1
2
3
4
5
6
 from java.util import * from javax.management import * import javax.management.Attribute
<p>
    print 'starting the script .... '
</p>
<p>
    connect('weblogic', 'weblogic1', "t3://(11g-IP-addr):7001") edit() startEdit() cd('AppDeployments') cd('sample') set ('DeploymentOrder', 115) save() activate() disconnect() exit()

7) Then incorporated that script within the wls-maven-plugin:

1
2
3
4
5
6
7
</p>
<plugin> <groupid>com.oracle.weblogic</groupid> <artifactid>wls-maven-plugin</artifactid> <executions> <execution><phase>package</phase> <goals> <goal>wlst</goal> </goals> </execution> </executions> <configuration>  from java.util import * from javax.management import * import javax.management.Attribute
<p>
    print 'Updating deployment order .... '
</p>
<p>
    connect(System.getProperty("deploy.user"), System.getProperty("deploy.password"), System.getProperty("deploy.admin")) edit() startEdit() cd(System.getProperty("deploy.mbean")) cd(System.getProperty("deploy.library.name")) set ('DeploymentOrder', System.getProperty("deploy.order")) save() activate() disconnect()

8) Then ran the WLST call from the maven plugin:

1
 mvn wls:wlst -DfileName=changeOrder.py -DmiddlewareHome=(WLS_12C_MIDDLEWARE_PATH)

Properties are fed into the python script from Maven properties (based on a profile which is different for applications, resources, and optional packages).

This is because within the JNDI hierarchy through WLST, these assets get different Types, different versions, and different name. We can see this by logging into the server through a WLST command window and simply running an ls() command on the application or library directory. For instance, the following is an example of running the ls() command on the war. We can see that the type is AppDeployment and that the Identifier and Name are similar.

1
 wls:/sandbox/serverConfig/AppDeployments/sample-war-10> ls() dr--   SubDeployments dr--   Targets -r--   AbsoluteInstallDir                           null -r--   AbsolutePlanDir                              null -r--   AbsolutePlanPath                             null -r--   AbsoluteSourcePath                           /domains/sandbox/servers/sandboxAdminServer/upload/sample-war-10/app/sample-war.war -r--   ApplicationIdentifier                        sample-war-10 -r--   ApplicationName                              sample-war-10 -r--   CompatibilityName                            null -r--   DeploymentOrder                              102 -r--   DeploymentPlan                               null -r--   DeploymentPlanExternalDescriptors            null -r--   DeploymentPrincipalName                      null -r--   InstallDir                                   null -r--   ModuleType                                   war -r--   Name                                         sample-war-10 -r--   Notes                                        null -r--   PlanDir                                      null -r--   PlanPath                                     null -r--   SecurityDDModel                              DDOnly -r--   SourcePath                                   servers/sandboxAdminServer/upload/sample-war-10/app/sample-war.war -r--   StagingMode                                  null -r--   Type                                         AppDeployment -r--   ValidateDDSecurityData                       false -r--   VersionIdentifier                            null -r-x   freezeCurrentValue                           Void : String(attributeName) -r-x   isSet                                        Boolean : String(propertyName) -r-x   unSet                                        Void : String(propertyName)

anabolic steroids for sale

Now we will run the same command, but this time on an Optional Package, like our cxfFull that we created with Apache Shade. We can see here that the type is Library instead of AppDeployment, and that the ApplicationIdentifier includes the Manifest versions identified for this Optional Package. Therefore we need to feed in different properties when attempting to change the deployment order for an application asset as opposed to a library asset.

1
 wls:/sandbox/serverConfig/Libraries/cxfFull#2.4.5@2.4.5> ls() dr--   SubDeployments dr--   Targets -r--   AbsoluteInstallDir                           null -r--   AbsolutePlanDir                              null -r--   AbsolutePlanPath                             null -r--   AbsoluteSourcePath                           /domains/sandbox/servers/sandboxAdminServer/upload/cxfFull/2.4.5@2.4.5/app/cxf-full.jar -r--   ApplicationIdentifier                        cxfFull#2.4.5@2.4.5 -r--   ApplicationName                              cxfFull -r--   CompatibilityName                            null -r--   DeploymentOrder                              95 -r--   DeploymentPlan                               null -r--   DeploymentPlanExternalDescriptors            null -r--   DeploymentPrincipalName                      null -r--   InstallDir                                   null -r--   ModuleType                                   null -r--   Name                                         cxfFull#2.4.5@2.4.5 -r--   Notes                                        null -r--   PlanDir                                      null -r--   PlanPath                                     null -r--   SecurityDDModel                              DDOnly -r--   SourcePath                                   servers/sandboxAdminServer/upload/cxfFull/2.4.5@2.4.5/app/cxf-full.jar -r--   StagingMode                                  null -r--   Type                                         Library -r--   ValidateDDSecurityData                       false -r--   VersionIdentifier                            2.4.5@2.4.5 -r-x   freezeCurrentValue                           Void : String(attributeName) -r-x   isSet                                        Boolean : String(propertyName) -r-x   unSet                                        Void : String(propertyName)

Of course, this can be easily done through the console, but the ability to do it through the usage of the Maven Plugin can speed up the deployment process. One of the ways that we could have sped up the utilization of this plugin would be to open a WLST session, modify the deployment order of all the assets we were deploying and then closed the WLST session. Instead of trying to open, modify, close a session for each asset that was being deployed.

Top Downloaded Mp3s

Share and Enjoy

Hibernate and JPA 2.0 with WebLogic Server

I talked a little about utilizing Hibernate/JPA 2 with WebLogic Server in my blog about (Multiple persistence.xml files and JPA). First off, the idea was to utilize JPA 2 and use Hibernate as the provider so that all the persistence logic could be written against JPA. Long-term, this was a mistake, since Hibernate has such advanced features such as their Filters and Interceptors that Hibernate’s API began to slowly creep into the core persistence classes we developed. So even though the initial concept seemed ideal to have this separation where the persistence provider would be hidden from application logic, that quickly changed and it became apparent that much time and effort would have been saved in just using Hibernate as opposed to coupling it with JPA 2.

That being said, in order to get Hibernate to work in WebLogic Server, one of the simplest things to do is create a preclasspath directory that we can place in front of WebLogic libraries in the WebLogic Server startup script. Then additional libraries can be added to this folder that are necessary to implement features where library collisions occur with WebLogic Server weblogic.jar and other default jars (such as saaj-impl.jar). Since the weblogic.jar contains many 3rd party libraries, and older versions than we like to use, we have to place the antlr jar in this preclasspath directory (along with other ones such as commons-lang.jar and saaj-impl.jar). Once we start our WebLogic Server, we start getting errors related to this Oracle Forum post (Thread: Hibernate 3.6 Final (JPA 2.0) + WL 10.3.x :Unable to deploy sample appn) and Can not deploy 3.5 to Weblogic 10.3 server. The error is basically:

1
java.lang.Throwable: java.lang.NoSuchMethodError: javax.persistence.spi.PersistenceUnitInfo.getValidationMode()Ljavax/persistence/ValidationMode;

The way to simply resolve this is by putting the “hibernate-jpa-2.0-api-1.0.1.Final.jar” into the preclasspath folder in WebLogic Server and restart the server. This appeared to fix the issue, until we actually started doing testing later on in other environments related to the Validation Framework. The following error began to appear (ignore the jar names, I use Apache Shade to combine the multiple hibernate jars into a single jar):

1
2
3
4
5
6
7
8
9
10
11
java.lang.AbstractMethodError: null        
at javax.persistence.Persistence$1.isLoaded(Persistence.java:93) ~[hibernate-jpa-2.0-api-1.0.1.Final.jar:1.0.1.Final]        
at org.hibernate.validator.engine.resolver.JPATraversableResolver.isReachable(JPATraversableResolver.java:61) ~[hibernate-full.jar:3.6.9]        
at org.hibernate.validator.engine.resolver.DefaultTraversableResolver.isReachable(DefaultTraversableResolver.java:131) ~[hibernate-full.jar:3.6.9]        
at org.hibernate.validator.engine.resolver.SingleThreadCachedTraversableResolver.isReachable(SingleThreadCachedTraversableResolver.java:46) ~[hibernate-full.jar:3.6.9]
at org.hibernate.validator.engine.ValidatorImpl.isValidationRequired(ValidatorImpl.java:1242) ~[hibernate-full.jar:3.6.9]        
at org.hibernate.validator.engine.ValidatorImpl.validateConstraint(ValidatorImpl.java:448) ~[hibernate-full.jar:3.6.9]        
at org.hibernate.validator.engine.ValidatorImpl.validateConstraintsForDefaultGroup(ValidatorImpl.java:397) ~[hibernate-full.jar:3.6.9]        
at org.hibernate.validator.engine.ValidatorImpl.validateConstraintsForCurrentGroup(ValidatorImpl.java:361) ~[hibernate-full.jar:3.6.9]        
at org.hibernate.validator.engine.ValidatorImpl.validateInContext(ValidatorImpl.java:313) ~[hibernate-full.jar:3.6.9]        
at org.hibernate.validator.engine.ValidatorImpl.validate(ValidatorImpl.java:139) ~[hibernate-full.jar:3.6.9]

The next step was to upgrade the Hibernate Validator framework jars and also attempt to upgrade the Hibernate jars, but this did not seem to alleviate our issues. Plus, the phase of the project did not allow the upgrade from a Hibernate 3.6.0 to the newer Hibernate 4.* without some serious regression. So with some additional research, the issue seemed to really resolve around what implementation classes were being forced down the WebLogic Server classpath, as opposed to the libraries that were being supplied within the WAR. The following two links were discussions that related to this issue:

@Valid annotation gives java.lang.AbstractMethodError
AbstractMethodError in WebLogic 10.3.4
Validator fails when a non-Hibernate persistence layer is in the classpath

So through these discussions as well as a few other threads that I cannot seem to find now, the resolution was to get rid of the preclasspath library of hibernate-jpa-2.0-api-1.0.1.Final.jar and replace that jar with another spec reference from Geronimo called geronimo-jpa_2.0_spec-1.1.jar. With this replacement, the JPA 2.0 functionality continued to work because of the provided interfaces within the Geronimo API, and the AbstractMethodError disappeared when utilizing the Validator Framework functionality.

Share and Enjoy

Resolving Durable Duplicate Client ID Issues

Once I completed the previous blog post: Spring and WebLogic Durable Subscriber, the configurations were deployed to a multiple domain cluster (with some Managed Servers running on a separate physical machines). Errors started to occur within the cluster based on the use of the SingleConnectionFactory configuration. What appeared to be happening was when the subscribe war was deployed out to WebLogic Server, the 1st Managed Server started and created a durable session with the configured clientId. The problem was when the war started on the 2nd Managed Server, it attempted to create a durable session with that same configured clientId and we started receiving errors such as this:

[JMSClientExceptions:055083]Cannot set clientid to sampleSubscribeService. The client ID is already set to sampleSubscribeService
2012-12-28 12:40:12,604 THREAD:[143] WARN ID:[] org.springframework.jms.listener.DefaultMessageListenerContainer – Could not refresh JMS Connection for destination ‘jmsServer1@com/foo/dest/SampleTopic’ – retrying in 3600000 ms. Cause: [JMSClientExceptions:055083]Cannot set clientid to sampleSubscribeService. The client ID is already set to sampleSubscribeService

The following configuration existed (as shown in the other blog) for the subscribe service:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<bean id="sampleDurableTopicConnectionFactory"
    class="org.springframework.jms.connection.SingleConnectionFactory"
    p:targetConnectionFactory-ref="sampleMessagingConnectionFactory"
    p:clientId="sampleSubscribeService"/>

<bean id="sampleSubscribeServiceListenerContainer"  
    class="org.springframework.jms.listener.DefaultMessageListenerContainer"
    p:connectionFactory-ref="sampleDurableTopicConnectionFactory"
    p:destinationName="jmsServer1@com/foo/dest/SampleTopic"
    p:destinationResolver-ref="sampleDestinationResolver"
    p:messageListener-ref="sampleSubscribeServiceMessageListener"
    p:pubSubDomain="true"
    p:subscriptionDurable="true"
    p:durableSubscriptionName="sampleSubscribeService"
    p:transactionManager-ref="GlobalDataTransactionManager"/>

This included the configuration for the WebLogic Server ConnectionFactory:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<connection-factory name="SampleConnectionFactory">
    <default-targeting-enabled>true</default-targeting-enabled>
    <jndi-name>com/foo/SampleConnectionFactory</jndi-name>
    <client-params>
        <client-id-policy>Restricted</client-id-policy>
        <subscription-sharing-policy>Exclusive</subscription-sharing-policy>
        <messages-maximum>15</messages-maximum>
    </client-params>
    <transaction-params>
        <xa-connection-factory-enabled>true</xa-connection-factory-enabled>
    </transaction-params>
    <security-params>
        <attach-jmsx-user-id>false</attach-jmsx-user-id>
    </security-params>
</connection-factory>

So in order to resolve this issue, there were a few necessary changes. The first change dealt with moving the clientId configuration out of Spring (which required the SingleConnectionFactory) and moving the clientId configuration into the WebLogic Server ConnectionFactory. It also required the modification of how the ConnectionFactory was configured with clientId properties. The configuration needed to change to add the clientId, allow the clientId to be duplicated, and change the subscription sharing policy. The JMS resource configuration changed the the following.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<connection-factory name="SampleConnectionFactory">
    <default-targeting-enabled>true</default-targeting-enabled>
    <jndi-name>com/foo/SampleConnectionFactory</jndi-name>
    <client-params>
                <client-id>sampleClientId</client-id>
            <client-id-policy>Unrestricted</client-id-policy>
            <subscription-sharing-policy>Sharable</subscription-sharing-policy>
                <messages-maximum>15</messages-maximum>
    </client-params>
    <transaction-params>
        <xa-connection-factory-enabled>true</xa-connection-factory-enabled>
    </transaction-params>
    <security-params>
        <attach-jmsx-user-id>false</attach-jmsx-user-id>
    </security-params>
</connection-factory>

Also changed the forwarding-policy for Topics from Replicated to Partitioned.

There was one last item that needed to be configured because of the use of UDTs in WebLogic Server as opposed to default Topics. UDTs do not inherently support durable subscribes unless the WAR subscribes to an individual member of the cluster. This requires the WAR to subscribe to a specific jmsServer instance. The problem is when there is a multiple machine cluster (jmsServer1, jmsServer2, etc) and a WAR is deployed to the cluster, how do we specify the individual jmsServer instance in the Spring configuration. This approach would be solved by supplying a system level property in the domain scripts of WebLogic Server (there is a start script per Managed Server) and so each Managed Server script would export a system property of the name of the jmsServer.

1
2
3
4
5
JMS_SERVER_NAME=jmsServer1
export JMS_SERVER_NAME

EXTRA_JAVA_PROPERTIES="$ $ $ $ -DjmsServer.Name=$ -Dweblogic.debug.DebugDeploy -Dweblogic.debug.MasterDeployer -Dweblogic.debug.ApplicationContainer -Dcom.sun.management.jmxremote.authenticate=false"
export EXTRA_JAVA_PROPERTIES

Then, the Spring configuration for the DefaultMessageListenerContainer could simply inject that system property into the JMS destinationName property, as such:

1
2
3
4
5
6
7
8
9
10
<bean id="sampleSubscribeServiceListenerContainer"  
    class="org.springframework.jms.listener.DefaultMessageListenerContainer"
    p:connectionFactory-ref="sampleMessagingConnectionFactory"
    p:destinationName="${jmsServer.Name:jmsServer1}@com/foo/dest/SampleTopic"
    p:destinationResolver-ref="sampleDestinationResolver"
    p:messageListener-ref="sampleSubscribeServiceMessageListener"
    p:pubSubDomain="true"
    p:subscriptionDurable="true"
    p:durableSubscriptionName="sampleSubscribeService"
    p:transactionManager-ref="GlobalDataTransactionManager"/>

This resolved the duplicate clientId issues, allowed the WARs to work in a cluster against UDTs, and also correctly allowed the UDTs to load balance incoming messages to each instance in the cluster.

Share and Enjoy