I have a web app which in production I run on Tomcat. It uses the MySQL connector, however it is not bundled up with the war, rather it is included under Tomcat's common lib directory, so that I can access the data source through JNDI.
I would like to do something similar with Jetty (while developing), and more precisely Jetty + Maven. Is there a way for me to include the mysql-connector jar in the classpath when running Jetty through Maven (i.e. not have it bundled in the war file)?
Also I should note that I am using Maven for my build process and have the mysql-connector specified as "provided" scope.
Additinally to previous answer:
you have to add to your jetty plugin in maven config dependency:
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>${jetty.version}</version>
<configuration>
<stopKey>blah-blah-blah</stopKey>
<stopPort>9966</stopPort>
<webAppConfig>
<contextPath>/</contextPath>
</webAppConfig>
<jettyEnvXml>${basedir}/src/jetty-env.xml</jettyEnvXml>
</configuration>
<dependencies>
<dependency>
<groupId>postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>8.4-701.jdbc4</version>
</dependency>
</dependencies>
</plugin>
And then you can use provided scope at main project dependencies. I did it right now, and it works. Thank you for your question (and Nishant too)
Does not directly answer your question but since I love portability in webapps my war will contain the connector jar and a connection pool (e.g the super duper c3p0). That means that the container will not manage the database connection for me anymore nor will I use JNDI to describe the connection properties. But the webapp is now 100% portable and predictable on tomcat, jetty, resin, jboss etc.
<Configure class="org.mortbay.jetty.webapp.WebAppContext">
<New class="org.mortbay.jetty.plus.naming.Resource">
<Arg>hd-props</Arg>
<Arg>
<New class="java.util.Properties">
<Call name="load">
<Arg>
<New class="java.io.FileReader">
<Arg>cfg/dev-local.properties</Arg>
</New>
</Arg>
</Call>
</New>
</Arg>
</New>
It is a jetty-env.xml, which points to .properties file, which contains all the connect params to DB.
<bean id="jndi" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/hd-props"/>
</bean>
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="properties" ref="jndi"/>
</bean>
It is a spring config (i'm using spring too)
And then, I call mvn jetty:run, and it works fine...
Perhaps you could try using Maven .war overlays for this purpose, though I don't know if they work with other dependencies.
So basically your project would be
parent
|---- original-war
|---- new-war
Where your original-war project has the mysql dependency as <scope>provided</scope> but the the new-war module is just a pom that has a <packaging>war</packaging>, depends on the original war (for the overlay) has the mysql dependency with the compile scope, and runs the jetty plugin (leave the jetty plugin out of the original-war module). If this works, then you'll have to deal with the minor inconvenience of doing your development in one module but whatever testing you are doing in maven within another module.
Related
I'm using Arquillian and TomEE embedded adapter to test a WAR.
In my pom.xml I have the following entry
<dependency>
<groupId>org.apache.openejb</groupId>
<artifactId>arquillian-tomee-embedded</artifactId>
<version>1.7.2</version>
<scope>test</scope>
</dependency>
and in my arquillian.xml I have the following
<container qualifier="tomee" default="true">
<configuration>
[...]
<property name="javaVmArguments">-Xms2048m -Xmx2048m</property>
<property name="singleDumpByArchiveName">true</property>
<!--<property name="singleDeploymentByArchiveName">true</property>-->
[...]
</configuration>
</container>
Adding the property singleDumpByArchiveName I expected that, dumping only once the web archive for all the tests, there would be an improvement in terms of execution time, but that did not happen.
I also tried to add the Arquillian Suite Extension with the same goal
<dependency>
<groupId>org.eu.ingwar.tools</groupId>
<artifactId>arquillian-suite-extension</artifactId>
<version>1.1.2</version>
<scope>test</scope>
</dependency>
but I get the following error
java.lang.NoSuchMethodError: org.jboss.arquillian.test.spi.TestResult.setEnd(J)V
Do you have any tip on how to make these solutions work or can you suggest others to speed up the tests execution time?
first of all:
<property name="javaVmArguments">-Xms2048m -Xmx2048m</property>
is not a tomee configuration since tomee embedded doesn't fork a JVM, probably something copied/pasted from the net.
Then your error probably just means you have a dependency conflict (tomee brings an older version of arquillian). You need to fix that. You can need to use tomee 1.7.4 (or 7.x) which is compatible with arquillian > 1.1.11
I installed Spring Tool Suite and am now using it for a little sample project. However I keep having an error in my dispatcher-servlet.xml file:
Build path is incomplete. Cannot find class file for org/springframework/beans/factory/Aware
This error is highlighted here:
<bean
**class="org.springframework.web.servlet.view.InternalResourceViewResolver">**
<property name="prefix">
<value>/WEB-INF/pages/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
Any thought?
I think you may have some old jar files in your configuration. Try using the most current spring libraries.
I found my self in exactly the same case when I used incompatible maven spring-dependencies i.e check Spring Security Site on the right side where it explains what spring version should be used with what spring security version.
The project is missing the servlet-api jar and the error can be resolved by adding the dependency in the maven pom file
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
you can put this dependency with your spring version :
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring-version}</version>
<scope>compile</scope>
</dependency>
If you are using eclipse:
Right click on root project -> properties.
Click on Deployment Assembly.
Click add button.
Double click on Java Build Path Entries and Select build path
entries to include. (maybe if you are using maven, you need also
include those dependencies).
Finally clean and build.
This worked for me.
I'd like to have Jetty running on a production server and when I have a new code package to deploy I'd like to be able to do an "sbt package" to package up my code into a war file, then copy it over to the production machine's webapp folder.
Is that reasonable? If so, what is the best way to start Jetty as a daemon? Will it see the new file and automatically reload my app or do I need to restart it somehow?
The main problem with what you are suggesting is that the configuration required to have the server listen or monitor the webapps folder is that there will be a production hit.
While this type of configuration is great for development, it isn't recommended for production applications.
With that said, what you're looking for is a ContextDeployer, which can be configured in jetty.xml. See the Jetty documentation for your specific version of Jetty for the exact details:
<!-- =========================================================== -->
<!-- Configure the context deployer -->
<!-- A context deployer will deploy contexts described in -->
<!-- configuration files discovered in a directory. -->
<!-- The configuration directory can be scanned for hot -->
<!-- deployments at the configured scanInterval. -->
<!-- -->
<!-- This deployer is configured to deploy contexts configured -->
<!-- in the $JETTY_HOME/contexts directory -->
<!-- -->
<!-- =========================================================== -->
<Call name="addLifeCycle">
<Arg>
<New class="org.mortbay.jetty.deployer.ContextDeployer">
<Set name="contexts"><Ref id="Contexts"/></Set>
<Set name="configurationDir"><SystemProperty name="jetty.home" default="."/>/contexts</Set>
<Set name="scanInterval">5</Set>
</New>
</Arg>
</Call>
The "scanInterval" is what tells the server to monitor the contexts folder. Every 5 seconds, it checks to see if the files changed.
Finally, to start Jetty as a daemon, just use the scripts they provide you in the /bin folder:
./jetty.sh start
To stop Jetty, run:
./jetty.sh stop
And to restart Jetty, run:
./jetty.sh restart
Again, see The Jetty Documentation or The Webtide Website for the exact documentation for whatever version of Jetty you're running. Different versions can differ drastically in terms of how the server is configured.
Here's the problem: we build webapps for clients. We also have an "admin" webapp that modifies some client data structures. Because of the nature of the data, both webapps have to run in the same JVM.
This is no problem in production; you just put two webapps in the same app server.
We've recently switched to a Mavenish way of laying out webapps, though, and Maven wants one webapp per project. In Eclipse it's a problem, because if you run the different webapps independently, they'll be in separate JVMs.
We're trying to use the jetty-maven-plugin to do webapp testing, but could switch to something else if it would solve this problem.
Yes, you can :) It's done by identifying one WAR module as the primary, copying all the other WARs into the primary's target dir, making a jetty.xml and telling Maven Jetty Plugin to use the jetty.xml. Here's how to copy the other WARs using Maven dependency plugin:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy</id>
<phase>package</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>com.foo</groupId>
<artifactId>bar</artifactId>
<version>${project.version}</version>
<type>war</type>
<overWrite>true</overWrite>
<outputDirectory>target/</outputDirectory>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
You'll need to have the com.foo:bar dependency defined in the POM as well. Here's the contents of jetty.xml:
<?xml version="1.0"?>
<!-- =========================================================== -->
<!-- Set handler Collection Structure -->
<!-- =========================================================== -->
<Set name="handler">
<New id="Handlers" class="org.eclipse.jetty.server.handler.HandlerCollection">
<Set name="handlers">
<Array type="org.eclipse.jetty.server.Handler">
<Item>
<New class="org.eclipse.jetty.server.handler.ContextHandlerCollection"
id="Contexts">
<Set name="handlers">
<Array type="org.eclipse.jetty.server.Handler">
<Item>
<New id="FooWebHandler"
class="org.eclipse.jetty.webapp.WebAppContext"/>
</Item>
</Array>
</Set>
</New>
</Item>
</Array>
</Set>
</New>
</Set>
<Ref id="FooWebHandler">
<Set name="contextPath">/foo</Set>
<Set name="war">
target/bar-${project.version}.war
</Set>
</Ref>
And here's how to tell Maven Jetty plugin to use the new jetty.xml:
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>${jetty.version}</version>
<configuration>
<jettyConfig>${basedir}/jetty.xml</jettyConfig>
</configuration>
Now kick off jetty:run-war goal from Eclipse and you should see all WARs deploying in one Maven Jetty plugin instance. I run this from command line and it works there, YMMV with Eclipse.
You can do this via the jetty-maven-plugin directly, without modifying jetty.xml:
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<configuration>
<scanIntervalSeconds>5</scanIntervalSeconds>
<webApp>
<contextPath>/</contextPath>
</webApp>
<contextHandlers>
<contextHandler implementation="org.eclipse.jetty.maven.plugin.JettyWebAppContext">
<war>${project.basedir}/../secondProject.war</war>
<contextPath>/cc</contextPath>
</contextHandler>
</contextHandlers>
</configuration>
<executions>
...
</executions>
</plugin>
You don't have to modify jetty.xml file(s) at all to use this successfully, and you don't need to copy the war file either. (although you may wish to build the second war as part of this build, see maven-invoker-plugin)
Documentation here: http://www.eclipse.org/jetty/documentation/9.2.2.v20140723/jetty-maven-plugin.html#running-more-than-one-webapp
Here's to give an example for ccleve's answer.
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.HandlerCollection;
import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.xml.XmlConfiguration;
...
public static void main(String[] args) throws Exception {
...
Server server = new Server(port);
HandlerCollection handlers = new HandlerCollection();
WebAppContext frontEndWebappContext = new WebAppContext(
"src/main/webapp", "/test"
);
handlers.addHandler(frontEndWebappContext);
String serviceWebappBasePath = {absolute_path_to_other_webapp};
WebAppContext serviceWebappContext = new WebAppContext(
serviceWebappBasePath + "/main/webapp", "/"
);
handlers.addHandler(serviceWebappContext);
XmlConfiguration conf = new XmlConfiguration(new File(
serviceWebappBasePath + "test/webapp/WEB-INF/jetty-web.xml")
.toURI().toURL().openStream());
conf.configure(serviceWebappContext);
server.setHandler(handlers);
server.start();
...
In this case there is front-end webapp that is mounted to "/test" and a service webapp that is mounted on "/". We also include jetty-web.xml of the service app.
In your case, that launcher that you would create should be located in the "src/test" folder since it shouldn't be included in your war because you use want it for test purposes only.
You may also have to add dependency to the service webapp in scope test in the pom file of the front end webapp :
<dependency>
<groupId>{service_group}</groupId>
<artifactId>{service_artifact_id}</artifactId>
<version>{service_version}</version>
<scope>test</scope>
</dependency>
or/and
<dependency>
<groupId>{service_group}</groupId>
<artifactId>{service_artifact_id}</artifactId>
<type>test-jar</type>
<version>{service_version}</version>
<scope>test</scope>
</dependency>
I don't have that much experience with Maven/Jetty; but I do have experience with Tomcat on Eclipse; so we're both at least doing something with servlets on Eclipse.
At any rate, I don't know if you've made projects or not using any of the project templates in Eclipse, but I made mine using the Dynamic Web Project template. I haven't done two web apps before; but if you were to make two of these projects, and then in the Eclipse servers tab, make a new server and add both projects to it, you might be able to accomplish your goals.
When you do Run As...you're basically just running the default run configuration that Eclipse has for your project setup. But if you deploy both of your projects to one server in your dev environment, and then select that server and hit start and it should just start it on the one JVM; similar to your production environment.
Like I said though; I'm not using Jetty and I've never used the server setup guide with Jetty so I wouldn't know if this would work for you or not. So I hope this is helpful - but I won't be too terribly surprised if it isn't.
Answering my own question:
It appears that this just isn't possible. The workaround that we've come up with is to write a little embedded jetty code and launch it from within our app. Jetty allows you to add multiple webapps programmatically. It also allows you to create multiple resource bases, that is, directories, per webapp, which enables overlays. So far, it works great.
I am trying to configure a Jetty (6.x) WebAppContext with a custom subclass of WebAppClassLoader. In code (Scala), it's simply this:
val context = new WebAppContext()
val cwacl = new CustomWebAppClassLoader(context)
context.setClassLoader(cwacl)
...
This works fine when embedding Jetty. In production, however, I just deploy a war file to a stand-alone jetty instance, so there's no opportunity to configure things in code like this.
I can't figure out how to do the same thing via Jetty's configuration files. Any help is appreciated.
Bonus: How would you configure maven-jetty-plugin to use the CustomWebAppClassLoader :)
You could use the context config files. There are examples in the contexts/ directory.
This would be something along these lines:
<Configure id="mycontext1" class="org.mortbay.jetty.webapp.WebAppContext">
<Set name="classLoader">
<New class="f.q.n.CustomWebAppClassLoader">
<Arg><Ref id="mycontext1"/></Arg></New>
</Set>
</Configure>
(See the Jetty XML Syntax configuration reference for more details.)
As an alternative to using a context config file, you can set the classloader attributes in the pom.xml file, for jetty >= 8.x e.g. not scanning any class within WEB-INF for faster startup:
<plugins>
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>${jetty.version}</version>
<configuration>
<webApp>
<webInfIncludeJarPattern>^$</webInfIncludeJarPattern>
</webApp>
<stopKey>foo</stopKey>
<stopPort>9999</stopPort>
</configuration>
</plugin>
</plugins>
Reference: Jetty plugin webapp configuration