Cleanest Jetty Configuration for Development? - servlets

EDIT: I think I should clarify my intent...
I'm trying to simplify the development iteration cycle of write-code >> build WAR >> deploy >> refresh >> repeat. I'd like to be relatively independent of IDE (i.e., I don't want Eclipse or IntelliJ plug-ins doing the work). I want to be able to edit code/static files and build as needed into my WAR source directory, and just have run/debug setup as a command line call to a centralized Jetty installation.
Later I'd like to be able to perform the actual deployment using generally the same setup but with a packaged up WAR. I don't want to have my app code specific to my IDE or Jetty.
So perhaps a better way to ask this question is What have you found is the cleanest way to use Jetty as your dev/debug app server?
Say I want to have a minimal Jetty 7 installation. I want as minimal of XML configuration as possible, I just need the raw Servlet API, no JSP, no filtering, etc. I just want to be able to have some custom servlets and have static files served up if they exist. This will be the only WAR and it will sit as the root for a given port.
Ideally, for ease of deployment I'd like to have the Jetty directory just be the standard download, and my WAR / XML config be separate from these standard Jetty files. In my invocation of Jetty I'd like to pass in this minimal XML and go.
I'm finding that the documentation is all over the place and much of it is for Jetty 6 or specific to various other packages (Spring, etc.). I figure if I have this minimal configuration down then adding additional abstractions on top will be a lot cleaner. Also it will allow me to more cleanly deal with embedded-Jetty scenarios.
This SO question is an example scenario where this XML would be useful Jetty Run War Using only command line
What would be the minimal XML needed for specifying this one WAR location and the hosts/port to serve it?
Thanks in advance for any snippets or links.

Jetty has migrated to Eclipse. There is very subtle info on this. This also led in change in package name, which is another level of nuance. They did publish a util to convert Jetty6 setting to Jetty 7 setting, but again -- not very popular. I am dissapointed from Eclipse Jetty forum. Here is where you should look for documentation on Jetty 7 onwards http://wiki.eclipse.org/Jetty/Starting
I think this is the minimal jetty.xml taken from http://wiki.eclipse.org/Jetty/Reference/jetty.xml
<?xml version="1.0"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">\
<Configure id="Server" class="org.eclipse.jetty.server.Server">
</Configure>
But, I would rather like to start from a copy of $JETTY_HOME/etc/jetty.xml and would modify from there.
If you are Okay with $JETTY_HOME/webapps directory, you can set up the port by modifying this part
<Configure id="Server" class="org.eclipse.jetty.server.Server">
...
<Call name="addConnector">
<Arg>
<New class="org.eclipse.jetty.server.nio.SelectChannelConnector">
<Set name="host"><Property name="jetty.host" /></Set>
<Set name="port"><Property name="jetty.port" default="7777"/></Set>
<Set name="maxIdleTime">300000</Set>
<Set name="Acceptors">2</Set>
<Set name="statsOn">false</Set>
<Set name="confidentialPort">8443</Set>
<Set name="lowResourcesConnections">20000</Set>
<Set name="lowResourcesMaxIdleTime">5000</Set>
</New>
</Arg>
</Call>
....
</Configure>
Else, I will modify context.xml the way explained here (for Jetty 7) How to serve webbapp A from portA and webapp B from portB
Also refer these pages:
http://wiki.eclipse.org/Jetty/Reference/jetty.xml
http://wiki.eclipse.org/Jetty/Reference/jetty.xml_syntax
http://communitymapbuilder.org/display/JETTY/JNDI
....
Edit#1: sorry for wrong URL for webapp per connector. I have updated the link to How to serve webbapp A from portA and webapp B from portB to point to the doc that is meant for Jetty 7.
Update on 'how you deal with Jetty on various environments?'
Dev
We use Maven, so embeded Jetty works for us. We just run mvn clean install run:jetty and the port is configured in Maven's config file, namely pom.xml. This is not IDE dependent plus Jetty can easily be embedded using ANT, but I never tried.
Test
We have stand-alone Jetty running. I've configured port and tuned parameters, removed default apps (e.g. root.war etc) and created a context.xml with app specific ports and deployment directory. (Unfortunately, I have asked this question on Eclipse Jetty's mailing list and no one bothered to answer). This is one time setting.
For test builds/deployments, we have a build script that builds the WAR as per test env specs and then uploads it to test environment. After, that we invoke a shell script that (1)stops Jetty, (2) copies war file to myApp's webapp direactory and (3) restarts Jetty.
However, easier way to do this is by using Maven's Cargo plugin. The bad luck was that I was using Jetty 7.1.6 which was incompatible with Cargo. Later they fixed it, but I had got my job done by custom script.
Prod
Prod has almost same procedure as test, except. The tunings are done for higher security and load-balancing. But from deployment POV, there is nothing different from Test case to Prod.
Notice that I have not bothered about what XML files are and how many must be there. I have just used the ones that are my concerns -- jetty.xml and context.xml. Plus, I found it's much cleaner to use jetty.conf and jetty.sh for passing JVM params, custom XMLs and for starting and stopping.
Hope this helps.
On hot deployment:
Now, if you use Maven and use embedded Jetty. It just knows when the code is changed -- like "gunshot sniffer". In dev envt, you run Jetty, make changes, refresh page, and see your changes -- hot deployment. Find more here http://docs.codehaus.org/display/JETTY/Maven+Jetty+Plugin look for scanIntervalSeconds

This doesn't fully answer your question, but in case it helps, here's some pretty minimal code using embedded Jetty 7 to fire up a server with one root servlet:
HandlerCollection handlers = new HandlerCollection();
ServletContextHandler root = new ServletContextHandler(handlers, "/", ServletContextHandler.NO_SESSIONS|ServletContextHandler.NO_SECURITY);
root.addServlet(new ServletHolder(new MyServlet()), "/*");
Server server = new Server(8080);
server.setHandler(handlers);
server.start();
See of course http://wiki.eclipse.org/Jetty/Tutorial/Embedding_Jetty.

If you are building with maven (which is IDE independent) then you should debug with the maven jetty plugin. Basically you run the app as "mvn jetty:run" on the commandline it all just works without having to do any redeployment. Most good IDEs how have maven support built in and lets you run/debug the app as a maven; meaning that maven is run which starts the jetty plugin which starts the app and you can debug it. Since everything is running out of the IDE source and bin folders you don't even need a jetty server install.
Here is a demo project which runs that way https://github.com/simbo1905/ZkToDo2/blob/master/commandline.build.and.run.txt and here is how to run it under eclipse https://github.com/simbo1905/ZkToDo2/blob/master/eclipse.indigo.build.and.debug.txt but any IDE which understands maven should work. Take a look at the pom.xml where it sets up the maven jetty plugin.

I would use Gradle and scan the build output folder every few seconds for changes in the build.
In a build.gradle file:
apply plugin: 'jetty'
...
jettyRun.doFirst {
// set system properties, etc here for bootstrapping
}
jettyRun {
httpPort = 8989
reload = 'automatic'
scanIntervalSeconds = 3
daemon = false
}
That's it. You can choose to have the IDE auto-build for you, and point at that directory. But you can also choose not to. This solution is not tied at all to an IDE.

I thought I'd update with what I now do. I've written a tiny command line app / Maven archetype which works like how I thought this all should have in the first place. The bootstrap app lets you launch your servlet container of choice (Jetty, Tomcat, GlassFish) by just passing it the path to the WAR and your port.
Using Maven, you can create and package your own instance of this simple app:
mvn archetype:generate \
-DarchetypeGroupId=org.duelengine \
-DarchetypeArtifactId=war-bootstrap-archetype \
-DarchetypeVersion=0.2.1
Then you launch it like this:
java -jar bootstrap.jar -war myapp.war -p 8080 --jetty
Here's the source for the utility and the archetype: https://bitbucket.org/mckamey/war-bootstrap

Related

Apache Karaf - bundle starts but does nothing?

I'm new to Karaf. I have a jar that has a class App with a method main. When I drop the jar in the The Karaf log service console says the bundle is started but nothing seems to happen. The first thing (the jar) does is a simple database write so I can see if it's running (no log file is generated although one is expected).
The jar depends on lots of other jars. Our sysadmin will not install Maven on the production servers. Where does one put helper jars (like mysql-connector-java-[version].jar)?
Does Karaf use the Manifest file to find the main class? Do I have to implement some special interface or something?
thanks for any help.
As Karaf is a OSGi Container, you should first read some stuff on how to write proper OSGi bundles.
First of all you'll need a Activator that'll start your bundle (just like a main). A Main Class is never interpreted. Yes Karaf, as it is a OSGi container, does "read" the Manifest, but to make sure first it's a proper OSGi bundle second how the resolving should take place by reading Package-Import/-Export.
Regarding the "Packaging" - using lot's of other jar's/bunldes - , you'd either can built a custom Karaf (read the Karaf documentation on how to do this) or create a KAR for your Bundles containing your bundles and a feature.xml (again take a look at the documentation at Karaf)

How do I deploy application classes and Spring config files to Tomcat as a single jar?

Currently I create a new war file for each change but the changes are taking place in only a few classes and the Spring applicationContext.xml.
I would like to just update a jar file that contains these classes and not continually re-deploy hundreds of files that have not changed. I can create the jar easily enough but where do I put it and do I have to tell Spring to look in a specific jar for its' config files?
It is quite impossible to hot-redeploy code in Tomcat without using extra tools like JRebel or custom JVM agents.
But it is possible to modularize you application by:
1: Putting JARs to $TOMCAT_HOME/lib. Never do this, this solution is good only for simple cases.
2: Tune context.xml, putting Loader in it, like below:
<Context antiJARLocking="true" path="/">
<Loader className="org.apache.catalina.loader.VirtualWebappLoader" virtualClasspath="${catalina.base}/my-app-plugins/*.jar"/>
</Context>
This will enable you putting JAR file in $TOMCAT_HOME/my-app-plugins and thet will be added to the classpath of you app. You should put context.xml to the src/main/webapp/META-INF folder (Maven layout). However, restart is still needed.
3: Use OSGi. May be an overkill.

Log4j in Websphere

I recently take over a web application project using websphere and log4j running under AIX. To create a development environment, I setup all the components in windows, using eclipse to compile a WAR file and deploy it.
All is working fine except that log file is not created.
I changed the log file in log4j.properties from something like in below and and give everyone full access permission to the directory:
log4j.appender.F1.File=/abc/def/logs/admin.log
to
log4j.appender.F1.File=c:/logs/admin.log
What else can I check?
I create a simple standalone testapp which use the same log4j.properties and it can create the log file, but when the servlet deployed to websphere, it doesn't work. Please help! Thanks!
Ok, I think this article should help you. It seems that WebSphere CE uses log4j by default and controls it with a global properties file. There is a section on how to use application-specific properties files.
Here is what I try and do to troubleshoot similar issues.
Turn on log4j debugging to see where it actually picks up the file from. You need evidence of which file is picked up (so turning the debug on is a worthwhile activity) This provides you information with what log4j is trying to do to locate the configuration file.
-Dlog4j.debug=true
I would not hardcode the log4j location in the code. Instead I
would use the log4j.configuration System property and state that in
the JVM arguments. This way even I don't need to touch my code.
-Dlog4j.configuration=file:///home/manglu/log4j.properties
I would use this approach irrespective of the runtime server that I use (be it Tomcat or WAS CE or WAS)
Hope this helps
I suggest you use environment variables set on your server like this :
You must access the admin console of your server.
Under custom properties
Server_path=/abc/def/logs
In your log4j, use this : {$server_path}/log.txt
Make sure the user running the app has access to that directory.

Problem with Team Build 2010 and web.config transformation

I'm struggling to get web.config transformations working with automated builds.
We have a reasonably large solution, containing one ASP.NET web application and eight class libraries. We have three developers working on the project and, up to now, each has "published" the solution to a local folder then used file copy to deploy to a test server. I'm trying to put an automated build/deploy solution in place using TFS 2010.
I created a build definition and added a call to msdeploy.exe in the build process template, to get the application deployed to the test server. So far, so good!
I then tried to implement web.config transforms and I just can't get them to work. If I build and publish locally on my PC, the "publish" folder has the correct, transformed web.config file.
Using team build, the transformation just does not happen, and I just have the base web.config file.
I tried adding a post-build step in the web application's project file, as others have suggested, similar to:
<target name="AfterBuild">
<TransformXml Source="Web.generic.config"
Transform="$(ProjectConfigTransformFileName)"
Destination="Web.Config" />
</target>
but this fails beacuse the source web.config file has an "applicationSettings" section. I get the error
Could not find schema information for the element 'applicationSettings'.
I've seen suggstions around adding arguments to the MSBuild task in the build definition like
/t:TransformWebConfig /p:Configuration=Debug
But this falls over when the class library projects are built, presumably because they don't have a web.config file.
Any ideas? Like others, I thought this would "just work", but apparently not. This is the last part I need to get working and it's driving me mad. I'm not an msbuild expert, so plain and simple please!
Thanks in advance.
Doug
I just went through this. Our build was a bit more complicated in that we have 8 class libraries and 9 web applications in one solution. But the flow is the same.
First off get rid of your after build target. You won't need that.
You need to use the MSDeployPublish service. This will require that it be installed and configured properly on the destination server. Check the following links for info on this part:
Note that the server in question MUST be configured properly with the correct user rights. The following sites helped me get that properly set up.
http://william.jerla.me/post/2010/03/20/Configuring-MSDeploy-in-IIS-7.aspx
http://vishaljoshi.blogspot.com/2010/11/team-build-web-deployment-web-deploy-vs.html
How can I get TFS2010 to run MSDEPLOY for me through MSBUILD?
The next part requires that your build definition have the correct MSBuild parameters set up to do the publish. Those parameters are entered in the Process > 3.Advanced > MS Build Arguments line of the build definition. Here's a hint:
(don't change the following for any reason)
/p:DeployOnBuild=True
/p:DeployTarget=MsDeployPublish
/p:CreatePackageOnPublish=False
/p:MSDeployPublishMethod=WMSVC
/p:SkipExtraFilesOnServer=True
/p:AllowUntrustedCertificate=True
(These control where it's going)
/p:MSDeployServiceUrl="https://testserver.domain:8172/msdeploy.axd"
/p:UserName=testserver\buildaccount
/p:Password=buildacctpassword
/p:DeployIisAppPath="MyApp - TESTING"
Obviously the user will have to be configured in IIS on the target server to be allowed access to that axd (see previous links). And the IisAppPath is the name of the website on the target server.
You won't have to do anything special for the config transformations as the build itself will take care of that for you. Just have the correct setting in the line at Process > 1. Required > Items to Build > Configurations To Build.
Instead of trying to do the deploy by adding tasks myself into the build process template, I followed advice in Vishal Joshi's blog post here.
Now the entire project is built and deployed and the web.config transformations work also. Brilliant!
I now have another problem to solve! The web application references web services and the build process results in an XmlSerializers dll. However, although this is built OK, it does not get deployed to the web host. I think this needs a new post!
Doug

How to make an application client jar file for IBM's launchclient

Hi I'm facing with a bug in old ejb application which is deployed on IBM Websphere 6.1. Previously it ran but now it stopped for some reason which I have to investigate.
I'm trying to get it to run locally on my desktop, and I'm trying to access the session bean with IBM's launchclient application. I pass in the ear as the argument (yes that's IBM specific) and the ears contains both the ejb-jar and the ejb-client.jar (also IBM specific).
Launchclient fails with the message: myear does not contain an Application Client jar file. Which may be true, but it does contain the client-ejb jar file, which I even bothered to address with -CCjar=MyEjbClient.jar.
My question is how can I make an application client jar file?
I cant find much information on the launchclient thing, I do have RAD 7.x or something, but to be honest I want to stay away from it as much as possible and it's getting really frustrating.
regards,
PS someone knows a nice NO IBM job?
It is not sufficient to have an ejb-client-jar, you need an application client JAR. Also, -CCjar can only be specified for an application jar (and it's not necessary if you only have one).
To add an application client JAR to an EAR, you need to:
Create a Java class with a traditional main method.
Package the class in a JAR in the EAR.
Add a Main-Class to the META-INF/MANIFEST.MF in the JAR.
Add a META-INF/application-client.xml file to the JAR.
Add the module to application.xml in the EAR:
<module>
<java>MyClient.jar</java>
</module>

Resources