How to specify jetty-env.xml file for Maven Cargo plugin for Jetty?
Asked Answered
P

4

6

I am migrating from Maven's jetty plugin to the Cargo plugin (cargo-maven2-plugin) because Cargo will happily run WARs from dependent Maven modules. Within out web-app we have taken great pains to externalize all configuration through JNDI. These JNDI definitions are web-app specific and therefore are placed in a jetty-env.xml file that is outside the WAR. Using the Jetty plugin, we specified this file as follows:

        <plugin>
            <groupId>org.mortbay.jetty</groupId>
            <artifactId>maven-jetty-plugin</artifactId>
            <configuration>
                <jettyEnvXml>${basedir}/target/config/jetty-env.xml</jettyEnvXml>
            </configuration>
        </plugin>

How does one go about specifying this within the Cargo Plugin? Here's the configuration I have so far. It is, of course, failing because of the absent JNDI configuration:

        <plugin>
                <groupId>org.codehaus.cargo</groupId>
                <artifactId>cargo-maven2-plugin</artifactId>
                <configuration>
                    <container>
                        <containerId>jetty6x</containerId>
                        <type>embedded</type>
                    </container>
                    <configuration>
                        <deployables>
                            <deployable>
                                <groupId>com.mycompany</groupId>
                                <artifactId>my-war-module</artifactId>
                                <type>war</type>
                                <properties>
                                   <context>/</context>
                                </properties>
                            </deployable>
                        </deployables>
                    </configuration>
                    <wait>false</wait>
                </configuration>
                <executions>
                           ......
                </executions>
        </plugin>
Psid answered 28/10, 2010 at 4:5 Comment(0)
P
1

Mond's answer sparked an idea that perhaps I could use the configuration of Cargo to deposit my (renamed and slightly modified) jetty-env.xml into the "contexts" directory. To my amazement it Just Worked. Here what I did:

To my cargo configuration I added the following:

<configfiles>  
  <configfile>  
      <file>${basedir}/../config/jetty-env.xml</file>
    <todir>contexts</todir>
     <tofile>${jetty6.context}.xml</tofile>
   </configfile>
</configfiles>

But in order to turn my jetty-env.xml into a real context.xml I added the following:

<!-- Activates the Jetty-Plus feature so we can create/share JNDI resources -->
<Array id="plusConfig" type="java.lang.String">
    <Item>org.mortbay.jetty.webapp.WebInfConfiguration</Item>
    <Item>org.mortbay.jetty.plus.webapp.EnvConfiguration</Item>
    <Item>org.mortbay.jetty.plus.webapp.Configuration</Item>
    <Item>org.mortbay.jetty.webapp.JettyWebXmlConfiguration</Item>
    <Item>org.mortbay.jetty.webapp.TagLibConfiguration</Item>
</Array>

<!-- Miscellaneous properties that were take from the CARGO version of this file that is created automatically
    (and then replaced by this file). If you ever upgrade Cargo you may need to change these. -->
<Set name="contextPath">/${jetty6.context}</Set>
<Set name="war">
    <SystemProperty name="config.home" default="."/>/webapps/${jetty6.context}.war</Set>
<Set name="extractWAR">true</Set>
<Set name="defaultsDescriptor">
    <SystemProperty name="config.home" default="."/>/etc/webdefault.xml</Set>
<Set name="ConfigurationClasses">
    <Ref id="plusConfig" />
</Set>

I was worried that CARGO would dump its own context file AFTER it copied mine there, but it was smart enough to copy mine last.

Psid answered 11/12, 2010 at 4:42 Comment(2)
the solution is cool but when I am trying to implement, I am facing some even more fundamental problem: Cargo is not generating the context xml. It will be great if you can share some experience with me. #10171449Execration
Just a quick note for people found this solution: This solution does not work with embedded jetty. You need installed one. For automated installation please refer to HDave's update in the link in previous comment.Execration
I
3

According to CARGO-804, Cargo's Jetty deployer now supports embedding a jetty-env.xml inside your war (as of version 1.0.3).

And in order to keep the jetty-env.xml outside your "real" war, my suggestion would be to create an additional war module to host the jetty-env.xml file and configure Cargo to merge WAR files (pay a special attention to the <extensions>true</extensions> element which is important, as mentioned in CARGO-524).

Isopiestic answered 28/10, 2010 at 5:0 Comment(8)
It certainly looks like I could put the jetty-env.xml in the WEB-INF directory, but I wouldn't want to ship a WAR to customers with that file in there. I was hoping to avoid the creation of another Maven module whose existence was only to act as a server for integration test other Maven modules. Thought maybe some combination of system properties or command line arguments or something could have avoided it.Psid
@HDave: Yes, I understand that you want to keep the jetty-env.xml outside the WAR which is why I suggested the merge approach. But I also understand that creating another module just for the purpose of Cargo might not be desired. That's the only solution I could think of though. Let's see if you find something better.Isopiestic
@Pascal - After some limited, but careful study, I believe your work-around of creating another Maven module is the only approach that can work at this time. I have created a enhancement request here, which summarizes the details:Psid
@HDave Voted up and watching the issue. Maybe someone will post a better alternative...Isopiestic
@Pascal - I have just discovered that the patch associated with CARGO-861 was only for the Jetty Installed deployer (Jetty6xInstalledLocalDeployer) and not the embedded deployer (Jetty6xEmbeddedLocalDeployer). The result being that putting the jetty-env.xml file in the WAR file does not work unless I switch over to the installed deployer. I was trying to avoid this. In order to keep to a totally portable build environment, I'll need to use cargo to install Jetty locally before running. I created another issue for this jira.codehaus.org/browse/CARGO-862Psid
@HDave: Ah, yes, I missed that point. As a side note, you could maybe use the <zipUrlInstaller>, see the Tips, to avoid loosing portability (never tried with Jetty). Of course, fixing your issue would be nicer.Isopiestic
@Pascal - Used zipUrlInstaller and it worked. Note however that I was getting a UserTransaction class not found error until I added the JTA 1.1 depenedency to the container within cargo. I really have no idea why I had to do this, but once I got passed that error everything Just Worked.Psid
@HDave: Good! Not sure about the JTA dependency but I guess it's the way to have Cargo putting it on the classpath when starting Jetty. Maybe a bit overcomplicated, but at least it works.Isopiestic
C
1

I share the same problem and desire to have a clean install. I was not attracted by the merging of WAR files. Instead I use an assembly to maintain a ZIP file of all external properties. As a separate module I can then deploy the contents of the ZIP file to the JETTY environment. In turn, I leverage how Jetty uses the name of the web app to load a complimentary environment file (for webapps/foo.war Jetty uses contexts/foo.xml for configuration). So, whilst it's not as compact as a pure Cargo solution I prefer it since the WAR file is unadulterated in its progress throughout the promotion process. The solution is also a general mechanism to manage all configuration activities. I can point to more details if anyone is interested.

Crwth answered 6/12, 2010 at 23:31 Comment(3)
Sounds interesting. I knew tomcat looked for contexts/foo.xml but I didn't know Jetty did. Are you saying your solution works in conjunction with cargo or replaces it? Can you put JNDI resources into foo.xml?Psid
Actually you can, but that turned out to be an unstable option. It gets overwritten on re-deploys. The solution works in conjunction with Cargo. I am discussing the point with the Jetty folks and hope to obtain a solid solution. Using properties looks interesting...Crwth
Hey HDave you solved a mystery for me ... so Cargo was generating the config file rather than Jetty! So yes, your new answer is ideal. My only issue now is how to enable properties so that the same xml file can be used in every environment...Crwth
P
1

Mond's answer sparked an idea that perhaps I could use the configuration of Cargo to deposit my (renamed and slightly modified) jetty-env.xml into the "contexts" directory. To my amazement it Just Worked. Here what I did:

To my cargo configuration I added the following:

<configfiles>  
  <configfile>  
      <file>${basedir}/../config/jetty-env.xml</file>
    <todir>contexts</todir>
     <tofile>${jetty6.context}.xml</tofile>
   </configfile>
</configfiles>

But in order to turn my jetty-env.xml into a real context.xml I added the following:

<!-- Activates the Jetty-Plus feature so we can create/share JNDI resources -->
<Array id="plusConfig" type="java.lang.String">
    <Item>org.mortbay.jetty.webapp.WebInfConfiguration</Item>
    <Item>org.mortbay.jetty.plus.webapp.EnvConfiguration</Item>
    <Item>org.mortbay.jetty.plus.webapp.Configuration</Item>
    <Item>org.mortbay.jetty.webapp.JettyWebXmlConfiguration</Item>
    <Item>org.mortbay.jetty.webapp.TagLibConfiguration</Item>
</Array>

<!-- Miscellaneous properties that were take from the CARGO version of this file that is created automatically
    (and then replaced by this file). If you ever upgrade Cargo you may need to change these. -->
<Set name="contextPath">/${jetty6.context}</Set>
<Set name="war">
    <SystemProperty name="config.home" default="."/>/webapps/${jetty6.context}.war</Set>
<Set name="extractWAR">true</Set>
<Set name="defaultsDescriptor">
    <SystemProperty name="config.home" default="."/>/etc/webdefault.xml</Set>
<Set name="ConfigurationClasses">
    <Ref id="plusConfig" />
</Set>

I was worried that CARGO would dump its own context file AFTER it copied mine there, but it was smart enough to copy mine last.

Psid answered 11/12, 2010 at 4:42 Comment(2)
the solution is cool but when I am trying to implement, I am facing some even more fundamental problem: Cargo is not generating the context xml. It will be great if you can share some experience with me. #10171449Execration
Just a quick note for people found this solution: This solution does not work with embedded jetty. You need installed one. For automated installation please refer to HDave's update in the link in previous comment.Execration
C
1

Something else I want to do is to filter properties. So far I have this:

    <profile>
        <id>deploy-properties</id>
        <activation>
            <activeByDefault>false</activeByDefault>
        </activation>
        <properties>
            <deployable.classifier>properties</deployable.classifier>
            <deployable.type>zip</deployable.type>
            <ys.imq.user>UserFromDeploymentPom</ys.imq.user>
            <ys.imq.password>PasswordFromDeploymentPom</ys.imq.password>
        </properties>
        <dependencies>
            <dependency>
                <groupId>${project.groupId}</groupId>
                <artifactId>${deployable.artifactId}</artifactId>
                <classifier>${deployable.classifier}</classifier>
                <type>${deployable.type}</type>
                <version>${project.version}</version>
            </dependency>
        </dependencies>
        <build>
            <plugins>
                <plugin>
                    <artifactId>maven-dependency-plugin</artifactId>
                    <executions>
                        <execution>
                            <phase>process-resources</phase>
                            <goals>
                                <goal>unpack</goal>
                            </goals>
                        </execution>
                    </executions>
                    <configuration>
                        <artifactItems>
                            <artifactItem>
                                <groupId>${project.groupId}</groupId>
                                <artifactId>${deployable.artifactId}</artifactId>
                                <classifier>${deployable.classifier}</classifier>
                                <version>${project.version}</version>
                                <type>${deployable.type}</type>
                                <overWrite>true</overWrite>
                                <outputDirectory>/tmp/${deployable.artifactId}</outputDirectory>
                            </artifactItem>
                        </artifactItems>
                    </configuration>
                </plugin>
                <plugin>
                    <artifactId>maven-resources-plugin</artifactId>
                    <version>2.4.3</version>
                    <executions>
                        <execution>
                            <id>copy-resources</id>
                            <phase>package</phase>
                            <goals>
                                <goal>copy-resources</goal>
                            </goals>
                            <configuration>
                                <outputDirectory>${deploy.jettyHome}</outputDirectory>
                                <overwrite>true</overwrite>
                                <resources>
                                    <resource>
                                        <directory>/tmp/${deployable.artifactId}</directory>
                                        <filtering>true</filtering>
                                    </resource>
                                </resources>
                            </configuration>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </build>
    </profile>

Its a bit more complicated than I like but allows me to filter properties whilst adding them to Jetty. This enables passwords and other confidential data to be overriden using system properties. We are using Bamboo (I guess Hudson is similar) and one can adjust plans per environment. Plans can be subject to access control. This allows us to have one place to set all deployment properties, so no more admins hacking on the Unix boxes.

Crwth answered 13/12, 2010 at 23:36 Comment(2)
This is nice, in order to reduce complexity I was copying them directly from the other project module with a hard coded path. I prefer your approach because mine breaks build portability. I believe we have now achieved perfection on this!!Psid
FYI I gave up on JNDI. Instead I decided to use properties. These can be loaded in Spring via the CLASSPATH. The only trick is to add those files to the resources directory in JETTY which, it turns out, is on the CLASSPATH by default. We also added a directory under the resources directory and added a context.xml with the extraClassPath option to add that so that we could support multiple apps in one Jetty instance.Crwth

© 2022 - 2024 — McMap. All rights reserved.