Maven

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

Deploying applications to WebLogic with weblogic-maven-plugin

WebLogic has made the deployment of artifacts and resources significantly easier for Maven projects through the new plugin capabilities with weblogic-maven-plugin (WLS 11) and now the wls-maven-plugin (WLS 12). The newer version of the plugin has many additional features, but also has quite a few bugs and therefore I will use the capabilities of both plugins. The general usage of the plugins is to deploy our application resources (such as JDBC and JMS configurations), our optional packages, our web applications, and also to run wlst scripts against those deployments to change their deployment order.

The plugin is not something that can be downloaded directly, it is included within the installs for WebLogic Server 11 or WebLogic Server 12. So in order to get access to the plugin, I first install both servers locally. Once I do this, I can access the plugins:

1) With WebLogic Server 11, I can build the weblogic-maven-plugin using the wljarbuilder.jar

2) With WebLogic Server 12, I can find the plugin already available via out install directory at: $MIDDLEWARE_PATH_12C_ZIP/wlserver/server/lib/wls-maven-plugin.jar

Once I have access to these plugin jars, I will load them into our Maven repository manager (which is Nexus, but also could be Artifactory…for example). This way our plugin jars will be available to all our maven projects, and I will configure them through our plugin poms.

When using the plugin for deployments, I will need to gather some information such as what environments I will be deploying the resources to, what server names are, what cluster names are, what ports, what type of resource, the name I want the deployment to be, and other information. Since the deployments will change per environment, one beneficial strategy is to design a property file per environment. Once this is complete, I can use maven property substitution to derive our deployment information dynamically during the plugin runtime from the environment specific properties.

For more details on the Properties Maven Plugin. There is one nuance or issue with this plugin that you should be aware of, is it does not support properties within a jar file. If you follow this thread in stackoverflow.com, you will see a working plugin that uses the concepts of the “Properties Maven Plugin”, but allows the reading of properties from an external jar file: properties-ext-maven-plugin. This way I can run the external properties plugin prior to the weblogic-maven-plugin to read in our environment specific properties (one jar for each environment containing specific properties for that environment).

Now I can configure our weblogic-maven-plugin within our pom file:

1
2
</p>
<plugin> <groupid>com.oracle.weblogic</groupid> <artifactid>weblogic-maven-plugin</artifactid> <version>${weblogic.version}</version> <executions> <execution> <id>deploy</id><phase>compile</phase> <goals> <goal>deploy</goal> </goals> <configuration> <adminurl>t3://${deploy.hostname}:${deploy.port}</adminurl> <user>${deploy.userId}</user><password>${deploy.password}</password> <upload>true</upload> <action>deploy</action> <targets>${target.names}</targets> <remote>true</remote> <verbose>true</verbose> <source>${project.build.directory}/lib/${deployArtifact.name}.war <name>${deploy.library.name}</name> </configuration> </execution> </executions> </plugin>
  • deploy.hostname/deploy.port = properties that are read in per environment to point to different server targets
  • deploy.userId = the userid used to login to the weblogic server
  • deploy.password = the password used to login to the weblogic server
  • target.names = the target is usually the cluster name for the environment
  • deploy.library.name = This is the name of the deployment of the console, which I may want to name differently than the war itself, since the war might contain Maven version/classifiers within the name.

Once I deploy this war, I may have the need to undeploy (which can be done via the console our through our plugin again:

1
2
</p>
<plugin> <groupid>com.oracle.weblogic</groupid> <artifactid>weblogic-maven-plugin</artifactid> <version>${weblogic.version}</version> <execution> <id>undeploy</id><phase>clean</phase><goals><goal>undeploy</goal> </goals><configuration><adminurl>t3://${deploy.hostname}:${deploy.port}</adminurl><user>${deploy.userId}</user><password>${deploy.password}</password><upload>true</upload><action>undeploy</action><targets>${target.names}</targets><remote>true</remote><verbose>true</verbose><name>${deploy.library.name}</name></configuration> </execution> </plugin>

This configuration isn’t really much different. I just don’t need to supply the source and need to change the action to undeploy.

Another feature that I may want to do and can just become tedious based on the size of our deployments is to change the deployment order. This is not something that is capable through the WebLogic Server 11 plugin, so in this case I will utilize the WebLogic Server 12 plugin. The main difference is that now I am using the WebLogic Server 12 plugin, it has the capabilities to create domains, run wlst scripting, and other features that require an installation of WebLogic Server 12. This does not necessarily mean you have to install a WebLogic Server 12 in your environments, it just means that if you are using this plugin locally or via a CI Tool such as Hudson, you will need to install a WebLogic Server 12 into that environment so that the plugin can utilize the wlst shell and other scripts in order to use the plugin. This could be an issue for developers running the scripts locally, so in this case, I utilize profiles to run plugin configurations that use WebLogic Server 12 plugin so that developers can do deployments via the WebLogic Server 11 (which has no additional dependencies) and advanced features via WebLogic Server 12.

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()

  • deploy.user = the userid used to login to the weblogic server
  • deploy.password = the password use to login to the weblogic server
  • deploy.admin = the admin url for logging into the weblogic domain
  • deploy.mbean = AppDeployments or Libraries based on whether this is a war or something like an Optional Package
  • deploy.library.name = the exact name as it appears through JMX tree or console, for Optional Packages, this includes the version in a format such as deployName#deploySpecVersion@deployImplVersion

The space and indentation are important when including the script inline within the pom as opposed to having the wlst script as an external file. Another thing to mention is that the capability to open wlst shell, change the deployment order, and close the wlst shell appears to consume some resources and if I need to do this for multiple resources, I should do this in one connection. Otherwise I have run into issues where running this wlst plugin per resource (10+ resources) will crash our Hudson instance.

This plugin (and all the WebLogic Server 12 plugin goals) have to be run with a command line parameter to supply the installation directory for the WebLogic Server 12:

-DmiddlewareHome=%INSTALL_PATH%\Oracle\Middleware

In another post, I will explain how I utilize this plugin to deploy our Optional Packages as well as deploy our JMS/JDBC resources.

buy dianabol uk

modafinilstar

Share and Enjoy

Custom Maven Plugin for Drools Rules

When I start developing business rules with Drools, I can utilize Guvnor as a repository for storing those assets. This application will allow us to add and create rules or functions within the product, or to upload those to the server. I can then use Guvnor to create packages that I can deploy with our applications that will use these rules. The packages are usually compiled into a pkg file that is then included into a war, for instance, a war that utilizes a Spring context file with a bean definition to register a KnowledgeSession that imports the pkg file. There are multiple ways to configure the KnowledgeSeesion with a pkg file, either by pulling a pkg file from the classpath or by pulling a pkg file from a URL.

One of the complexities that occurs when dealing with rules and the concept of the Guvnor, is treating Guvnor as not just a repository but as the main build system for rules. This hinders the potential for rapid development as it complicates build/run/test by introducing an Application Server which will be used as the main source for compilation of the rules for verification that they were designed correctly. If developers are not familiar with JBoss Application Server or in the case I have been familiar with (don’t have access to the server), when rules fail to compile, they have no way to search the log files for why rules failed to compile. Also, I ran into situations with the product poorly performing because it was installed as a simplistic development server and then doesn’t match the required performance capabilities.

To move past this, I decided to utilize the capabilities of Maven to create a custom plugin that could load rule files and compile those into a pkg file, by doing this locally and not having to rely on Guvnor for doing developmental builds. The plugin would need to scan a maven resources directory, compile a list of all the files, and then process those files through a KnowledgeSession, and then compile them into the binary package. The next step is to utilize a better deployment unit than a pkg. Since I am using Nexus (like Artifactory), I want to be able to deploy the pkg without having to create a customized dependency type. I can do this by jaring the pkg file, since as long as the jar file is on the classpath of the war I am deploying (which uses our rules), the configured KnowledgeSession will be able to resolve the pkg file within the jar. So once our pkg is complete, I will jar the pkg file with the same name as the pkg.

In this case, I am going to write a Maven Mojo. In order to do this, I really need to understand the Maven properties I have available to us. Maven runs on Plexus and as IOC, it has the great ability to inject property values into class level fields that are configured via Java Annotations (those that match Maven Properties or configurations within the pom file). I find some of these properties through the following resources:

Sonatype Maven Reference – Properties
Maven Properties Guide

In order to begin doing the Mojo development and use some of the more advanced capabilities that Plexus gives us, I will need to add to our Maven POM file for the plugin:

1
2
3
4
5
6
7
8
9
10
11
12
<dependency>
    <groupId>org.apache.maven</groupId>
    <artifactId>maven-plugin-api</artifactId>
</dependency>
<dependency>
        <groupId>org.apache.maven</groupId>
        <artifactId>maven-project</artifactId>
</dependency>
<dependency>
        <groupId>org.codehaus.plexus</groupId>
        <artifactId>plexus-utils</artifactId>
</dependency>

Sample Maven Properties

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
    /**
     * This will inject the MavenProject object that exists in the current
     * POM in which the plugin is running.  We can access all the information
     * we need from this single object.
     *
     * @parameter default-value="$"
     * */

    private MavenProject mavenProject;

    /**
     * This is where the .pkg files are written.  This is the project outputDirectory
     * and we technically don't need this field since we have the mavenProject field.
     *
     * @parameter expression="${project.build.outputDirectory}"
     */

    private File targetDirectory;

    /**
     * This is the project resource directory (not test).  This way we don't have to
     * hard-code a path in our plugin to access the resources, and we will have the
     * unique path even if a resources/resource configuration is used to modify the
     * default location of resources.  We technically don't need this field since
     * we have the mavenProject field.
     *
     * @parameter expression="${project.resources}"
     * @required
     */

    private List resources;

    /**
     * This gives us the artifactId for the project so that we can use this to name
     * we will give the pkg as well as the jar file.  This can also be retrieved from
     * the mavenProject.
     *
     * @parameter expression="${project.artifactId}"
     * @required
     */

    private String artifactId;

    /**
     * This parameter will automatically map the excludes/exclude listings from the
     * configuration segment of the plugin.
     *
     * @parameter
     */

    private List<String> excludes;

    /**
     * This parameter will automatically map the includes/include listings from the
     * configuration segment of the plugin.
     *
     * @parameter
     */

    private List<String> includes;

I can then access the Resources by calling the mavenProject.getResources(). I also need to get the list of possible includes/excludes, but these must first be converted from a List to a comma separated list of values (in order for us to take advantage of Maven’s path wildcarding). One of the features I also add is to set a default include list incase one is not set through the plugin:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
private static final String DEFAULT_INCLUDES_TYPES = "**/*.drl,**/*.xls,**/*.rf";

   private String getExcludesList() {
        if (CollectionUtils.isNotEmpty(excludes)) {
            return convertListToCsv(excludes);
        } else {
            return null;
        }
    }

    private String getIncludesList() {
        if (CollectionUtils.isNotEmpty(includes)) {
            return convertListToCsv(includes);

        } else {
            return DEFAULT_INCLUDES_TYPES;
        }
    }

    private String convertListToCsv(List<String> includeList) {
        StringBuilder nameBuilder = new StringBuilder();
        for (String includeItem : includeList) {
            nameBuilder.append(includeItem).append(",");
        }

        nameBuilder.deleteCharAt(nameBuilder.length() - 1);
        return nameBuilder.toString();
    }

I will use the class from the Plexus API.

When then utilize one of the helper methods to build the list of files that I will loop through and add the rule file to the KnowledgeBuilder:

1
List<File> listOfFiles = org.codehaus.plexus.util.FileUtils.getFiles(new File(resource.getDirectory()), getIncludesList(), getExcludesList(), true);

I will then loop get the KnowledgePackages and then stream those packages out to the pkg file:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
String targetPath = mavenProject.getBuild().getDirectory() + "/classes/";
Collection<KnowledgePackage> kpkgs = kbuilder.getKnowledgePackages();
for (KnowledgePackage kpkg : kpkgs) {
    Collection<Rule> rules = kpkg.getRules();
    FileOutputStream out = null;

    try {
        File targetFile = new File(targetPath);
        if (!targetFile.exists()) {
            FileUtils.forceMkdir(new File(targetPath));
        }
        File outFilePath = new File(targetPath + mavenProject.getArtifactId() + ".pkg");
        out = new FileOutputStream(outFilePath);
        DroolsStreamUtils.streamOut(out, ((KnowledgePackageImp) kpkg).pkg);
    } catch (IOException ex) {
        throw new RuntimeException(ex);
    } finally {
        IOUtils.closeQuietly(out);
    }

}

Once I complete this Mojo, I can then install it and configure the plugin through a master POM. When can then create Maven Projects and store our rules assets (like xls, drl, or rf) into the src/main/resources directory.

I will configure the master pom of our rules projects to reconfigure the jar plugin so that it will ignore all our rules files and just compile the built pkg file into the jar:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
    <build>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-jar-plugin</artifactId>
                    <configuration>
                        <includes>
                            <include>**/${project.artifactId}.pkg</include>
                        </includes>
                    </configuration>
                    <executions>
                        <execution>
                            <goals>
                                <goal>jar</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>

I can then configure our plugin and the types of files I want to exclude (for example) as well as the dependencies I need to include in order to compile the rules.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
        <plugins>
            <plugin>
                <groupId>com.foo.tools</groupId>
                <artifactId>foo-rules-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>**/sample.xls</exclude>
                        <exclude>**/*.drl</exclude>
                    </excludes>
                </configuration>
                <dependencies>
                    <dependency>
                        <groupId>com.foo.services</groupId>
                        <artifactId>core-foo-service</artifactId>
                        <version>1.0.0-SNAPSHOT</version>
                    </dependency>
                </dependencies>
            </plugin>
        </plugins>

When I am all said and done…the completed Mojo looks like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

import java.util.Collection;
import java.util.Iterator;
import java.util.List;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.maven.model.Resource;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.project.MavenProject;

import org.codehaus.plexus.util.FileUtils;

import org.drools.builder.KnowledgeBuilder;
import org.drools.builder.KnowledgeBuilderConfiguration;
import org.drools.builder.KnowledgeBuilderFactory;
import org.drools.builder.ResourceType;
import org.drools.compiler.DroolsParserException;
import org.drools.core.util.DroolsStreamUtils;
import org.drools.decisiontable.InputType;
import org.drools.decisiontable.SpreadsheetCompiler;
import org.drools.definition.KnowledgePackage;
import org.drools.definition.rule.Rule;
import org.drools.definitions.impl.KnowledgePackageImp;
import org.drools.io.ResourceFactory;

public class DroolsRulesMojo extends AbstractMojo {

    private static final String DEFAULT_INCLUDES = "**/*.drl,**/*.xls,**/*.rf";

    /**
     * Maven Project
     *
     * @parameter default-value="$"
     * */

    private MavenProject mavenProject;

    /**
     * @parameter
     */

    private List<String> excludes;

    /**
     * @parameter
     */

    private List<String> includes;

    /**
     * Setup the options to pass to the code generator.
     *
     * @return the configured options.
     */

    public void execute() throws MojoExecutionException, MojoFailureException {
        try {
            compileRules(mavenProject);
        } catch (Exception e) {
            // Normally don't log when an exception is thrown.
            // This just helps debugging more quickly for rules errors.
            getLog().error(e);
            throw new RuntimeException(e);
        }

    }

    public void compileRules(MavenProject mavenProject) throws DroolsParserException, IOException {
        ClassLoader classLoader = null;
        KnowledgeBuilderConfiguration kbuilderConf = KnowledgeBuilderFactory.newKnowledgeBuilderConfiguration(null,
                classLoader);
        KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder(kbuilderConf);

        // This is the target directory for where the rules will be placed during
        // the build.
        String targetPath = mavenProject.getBuild().getDirectory() + "/classes/";

        // Depending on how the project is checked out or the maven pom
        // sometimes the getDirectory() will not have the name of the project/pom
        // but unnamed since it cannot determine the correct name.
        if (StringUtils.contains(targetPath, "Unnamed")) {
            throw new RuntimeException("The project was incorrectly checked out so that maven cannot determine the"
                    + " project name, therefore it creates a directory with Unnamed.  Fix the project or add the name"
                    + " property into the Maven pom.xml");
        }

        // Ask the mavenProject for all it's resource locations.
        List resources = mavenProject.getResources();
        getLog().debug("Target directory to write output file - " + targetPath);

        // Loop through the collection, even though we really could lock this down
        // to just be the /src/main/resources. We could also change the plugin
        // to differentiate between running against test rules and production
        // rules.
        for (Iterator i = resources.iterator(); i.hasNext();) {
            Resource resource = (Resource) i.next();
            getLog().debug("Resource directory to pull rules from - " + resource.getDirectory());

            // The following method call allows us to use the capabilities of
            // wildcarding like we see in most maven plugins. Where we can do
            // things such as **/*.xls. This call will also resolve any conflicting
            // includes and excludes.
            List<File> listOfFiles = org.codehaus.plexus.util.FileUtils.getFiles(new File(resource.getDirectory()),
                    getIncludesList(), getExcludesList(), true);

            if (CollectionUtils.isEmpty(listOfFiles)) {
                getLog().warn("No files were found to compile into package");
            } else {
                for (File file : listOfFiles) {

                    if (file.isFile()) {
                        String fileName = file.getName();

                        // Store the suffix so we can determine the rules type
                        String fileSuffix = StringUtils.substringAfterLast(fileName, ".");

                        if (StringUtils.endsWith(fileSuffix, "drl")) {
                            getLog().info("- Adding DRL: " + fileName + " to package");
                            kbuilder.add(ResourceFactory.newFileResource(file.getAbsolutePath()), ResourceType.DRL);
                        } else if (StringUtils.endsWith(fileSuffix, "xls")) {
                            // Decision tables have an extra step, so we provide additional
                            // output information.
                            SpreadsheetCompiler sc = new SpreadsheetCompiler();
                            String drlstr = sc.compile(ResourceFactory.newFileResource(file.getAbsolutePath())
                                    .getInputStream(), InputType.XLS);
                            getLog().debug("--- XLS compile details = " + drlstr);
                            getLog().info("- Adding Decision Table: " + fileName + " to package");
                            kbuilder.add(ResourceFactory.newFileResource(file.getAbsolutePath()), ResourceType.DTABLE);
                        } else if (StringUtils.endsWith(fileSuffix, "rf")) {
                            getLog().info("- Adding Rule Flow: " + fileName + " to package");
                            kbuilder.add(ResourceFactory.newFileResource(file.getAbsolutePath()), ResourceType.DRF);
                        }

                    }
                }
            }
        }

        // If any errors have occurred in the KnowledgeBuilder, then throw
        // the errors and stop the plugin process.
        if (kbuilder.hasErrors()) {
            getLog().error("Errors " + kbuilder.getErrors().toString());
            throw new RuntimeException(kbuilder.getErrors().toString());
        }

        int pkgCount = 0;
        Collection<KnowledgePackage> kpkgs = kbuilder.getKnowledgePackages();
        for (KnowledgePackage kpkg : kpkgs) {
            Collection<Rule> rules = kpkg.getRules();
            for (Object element : rules) {
                org.drools.definitions.rule.impl.RuleImpl rule = (org.drools.definitions.rule.impl.RuleImpl) element;
               
                //Providing additional debug information for rules within the KnowledgeBuilder
                getLog().debug(
                        "<RuleName> : <Activation-Group (null=non-existent)> : <Agenda-group>:   " + rule.getName()
                                + " : " + rule.getRule().getActivationGroup() + " : "
                                + rule.getRule().getRuleFlowGroup());
            }

            if (++pkgCount > 1) {
                getLog().warn(
                        "Your rules are being built into multiple packages, this is most likely an issue.");
            }

            //Create the pkg on the file system.
            FileOutputStream out = null;

            try {
                File targetFile = new File(targetPath);
                if (!targetFile.exists()) {
                    FileUtils.forceMkdir(new File(targetPath));
                }
                File outFilePath = new File(targetPath + mavenProject.getArtifactId() + ".pkg");
                out = new FileOutputStream(outFilePath);
                DroolsStreamUtils.streamOut(out, ((KnowledgePackageImp) kpkg).pkg);
                long filesize = outFilePath.length();
                long filesizeInKB = filesize / 1024;

                //Log information about the create package.
                getLog().info(
                        "- Package " + mavenProject.getArtifactId() + " built, putting pkg: " + targetPath
                                + mavenProject.getArtifactId() + ".pkg");

                getLog().info("- Size of " + mavenProject.getArtifactId() + ".pkg is: " + filesizeInKB + " KB");
            } catch (IOException ex) {
                throw new RuntimeException(ex);
            } finally {
                IOUtils.closeQuietly(out);
            }

        }
    }

    /**
     * Create the exclude list. If the maven plugin was configured with excludes, then convert the list into a Csv since
     * the Plexus utility needs a comma separated list, else return a null String.
     *
     * @return String containing the list of excludes.
     */

    private String getExcludesList() {
        if (CollectionUtils.isNotEmpty(excludes)) {
            return convertListToCsv(excludes);
        } else {
            return null;
        }
    }

    /**
     * Create the include list. If the maven plugin was configured with includes, then convert the list into a Csv since
     * the Plexus utility needs a comma separated list, else return the list of default rules types that will be
     * compiled.
     *
     * @return String containing the list of excludes.
     */

    private String getIncludesList() {
        if (CollectionUtils.isNotEmpty(includes)) {
            return convertListToCsv(includes);

        } else {
            return DEFAULT_INCLUDES;
        }
    }

    /**
     * Looks through a list of Strings and creates a comma separated String.
     *
     * @param includeList
     *            List of String values for include/exclude.
     * @return String that is a Csv of values.
     */

    private String convertListToCsv(List<String> includeList) {
        StringBuilder nameBuilder = new StringBuilder();
        for (String includeItem : includeList) {
            nameBuilder.append(includeItem).append(",");
        }

        nameBuilder.deleteCharAt(nameBuilder.length() - 1);
        return nameBuilder.toString();
    }
}

viagra uden recept

Share and Enjoy