Create a runnable war with embedded tomcat or run a maven tomcat war project without maven and a tomcat installation

I know the title of this post is a bit of a contradiction, running a maven tomcat webapp without maven and a tomcat installation WTF?.

So before we begin let me clarify what I mean. You will need maven on your development environment and you will be using the tomcat7 maven plugin to deploy and run your application-.

When delivering a small to medium sized java web application it could be nice to have it as a self contained application allowing you to just drop-it anywhere and just run it without having to install/upgrade Maven, Apache Tomcat, etc. (of course you'll still need java :p )

What I would like to accomplish is to develop a web application using my usual tools and stack and then deliver the application in it's most simple way, without having to install and configure tomcat and maven on the target system.

Running a WAR project without a Tomcat installation is not very complicated you just use the maven tomcat plugin and run the appropriate goal (ex: tomcat7:run).

But running the app on a given system will require to have a local maven installation. Now this can avoid this by writing your own runner using the tomcat API(especially Tomcat Runner cli ) and including the appropriate tomcat JARs in your CLASSPATH.

Luckily, as often, there's an app plugin for that which honestly does pretty much all the job.

I'm talking of the tomcat7 maven plugin which you probably already use in some of your projects.Well as it turns out it has a very useful mojo that allows you to accomplish the task at hand.

The process of generating the runnable WAR is pretty simple (thank you Apache):

1. Add the tomcat plugin to your maven configuration





   com.ufasoli
    runnable-war
    1.0-SNAPSHOT
     war
...
   
     ...

     
        runnable-war
        
            
                
                    org.apache.tomcat.maven
                    tomcat7-maven-plugin
                    2.1
                    
                        
                            tomcat-run
                            
                                exec-war-only
                            
                            package
                            
                                /                               
                                exec-war
                                jar
                            
                        
                    
                

            
            
        
    

Here I'm configuring the generation of the runnable war inside a maven profile. If you do not want to do this just extract the build part of my runnable-war maven profile into your main maven configuration


2. Build your maven project with the optional profiles

Run the maven command in order to build your war and runnable JAR

  mvn clean package -Prunnable-war

This will generate 3 extra files on your target folder (additionally to your packaged war file) :

  • ${yourapp-version-war-exec}.jar : A runnable JAR file that contains the tomcat embedded runtime/li>
  • war.exec.manifest : a manifest file containing the main class to run
  • war-exec.properties : a properties file containing some tomcat config options and info

3. Run your WAR file

Once the project is packaged, you can go inside the target folder and run the following command to start the tomcat server


 java -jar ${yourapp-version-war-exec}.jar

I find this approach pretty useful as you can control your server environment and configuration directly from your app, but of course it's not applicable to all projects.

As usual you can find the code source for this project over at github

Multi-hop ssh tunnel - howto : Creating a SSH tunnel with port forwarding between multiple hosts

How to create a multi-hop ssh tunnel or how to chain multiple ssh tunnels. (or SSH inception)

For security reasons sometimes you need to jump through hoops in order to connect to a server in SSH and from that server SSH to another server and so on

Consider the following scenario :

  • An application is deployed on a tomcat server on the host3 and listens on the port 8080
  • From my local machine I need to access the tomcat server on the machine host3 but it's not reachable from my machine
  • I need to carry out some tests that need a graphical browser (Firefox, Chrome, etc.)
  • host3 is only accessible from host2which is only accessible from host1

SSH tunneling can help you in this scenario; you can find more information regarding here by forwarding requests on a given port to another port on another machine all through a (or in our case multiple)SSH connection(s)

Below is a graphical representation of what I'm trying to accomplish :

So without anymore delay let's get to it :

All of the following commands are issued from a single terminal, prompt, shell or whatever you want to call it, that needs to remain open to keep alive the tunnels.

1.Connect the local machine to host1 (create the first tunnel)

[ufasoli@local]> ssh -L38080:localhost:38080 ufasoli@host1

2.Connect to host2 from host1 (create the second tunnel)

[ufasoli@host1]>ssh -L38080:localhost:38080 ufasoli@host2

3.Connect to host3 from host2 (create the third and last tunnel)

[ufasoli@host2]>ssh -L38080:localhost:8080 ufasoli@host3

4.Checking the result

Now if everything went as expected you should be able to see your tomcat application by firing your favorite browser with the and entering the target remote URL as a localhost URL with the 38080 port, like for example http://localhost:38080/mywebapp

5.Bonus points

If you prefer you can do all of the above steps in one giant SSH command using the -t flag to chain commands( I also added the -v flag for a more verbose output)

[ufasoli@local]> ssh -v -L38080:localhost:38080 ufasoli@host1  -t ssh -v -L38080:localhost:38080 ufasoli@host2 -t ssh -v -L38080:localhost:8080 ufasoli@host3

Devops mode - first steps using puppet to automate environment configuration and installation

So it has been some time since I was at the DevoxxFR 2 years ago and had the chance to assist a few presentations regarding this "obscure movement" called DevOps and even tough I'm always interested in new stuff to play around with, coming out of the conference my feeling was "meh, I'll try it out sometime later"... and I never did...

But recently I got a task assigned : "install and configure a development and integration server"

The requirements were the following :

  • Java JDK7
  • Apache MAVEN
  • Apache ANT
  • GIT
  • Subversion (SVN)
  • Jenkins with the following plugins :
    1. Git plugin
    2. Apache MAVEN plugin
    3. Apache ANT plugin
  • Jenkins should run on a custom port namely port 9999

Now I've done this several times and there's nothing really complicated about it. But usually when I do something more than a few times I try to find a way to automate things (apparently we developers are lazy by nature)

As I'm no sysadmin or Linux expert and installing and configuring these tools may be slightly different from one Linux distribution to another, I was looking for an abstraction layer that will handle all these specifics for me.

It has been some time now that I've been hearing about DevOps and tools such as Puppet or Chef but never had the chance to use them.

So this time it was the perfect occasion for a Hello world in the DevOps universe, since this was a fairly small and simple configuration

After Googling a bit I decided to use Puppet instead of Chef this is a personal preference since I find it's JSON syntax easier to read, plus somewhere I read that there were more Puppet Forge modules than Chef recipes (these are pre-configured "plugins" for easier install) out there, but once again this criteria may depend on what you are attempting to install

After following the getting started tutorial available here I must say I was surprised on how easy some things can be done (granted this is a pretty basic tutorial, but we must begin somewhere) I encourage you to read it before checking the rest of the post.

There are 2 puppet versions the Free and the Enterprise version as well as a client-server or standalone approach

With the enterprise version you get a few nice things like a GUI console, a repository where you can manage your scripts, but I prefer the self-contained standalone approach and this is what I will be showing here.

Please note that this blog ticket is not meant to be an introduction to Puppet nor a fully configured production integration server but rather a simple use case based on a personal experience to get things started in the DevOps universe.

Below are the steps that I followed to achieve the task that was given to me :

1. Install Puppet

rpm -ivh http://yum.puppetlabs.com/el/6/products/i386/puppetlabs-release-6-7.noarch.rpm
yum install puppet

This step is distribution specific (I'm using CentOS)if you are not go check the install instructions for your Linux distribution

2. Install Puppet modules

2.1 Java

 puppet module install puppetlabs/java

2.2 Maven

puppet module install maestrodev/maven

2.3 Ant

 puppet module install maestrodev/ant

2.4 Git

 puppet module install puppetlabs/git

2.5 SVN

puppet module install maestrodev/svn

2.5 Jenkins

puppet module install rtyler/jenkins

3. Write your puppet script

include java
include maven
include ant
include git
include svn
include jenkins
jenkins::plugin{ "git" : ;}
jenkins::plugin{"ant": ;}

file_line{'jenkins_port':
        path => '/etc/sysconfig/jenkins',
        line => 'JENKINS_PORT="9999"',
        match => '^JENKINS_PORT=.*$',
        ensure => present
}

These pretty simple puppet script will install the different tools by including each one of the plugins we previously installed and in the end it will change the default Jenkins to the one required by using a puppet function file_line to manipulate a file and replace a line that matches the regular expression

So there you go I had some fun playing a bit with Puppet and will surely use it again in a similar situation..

Angular6 hiding component selector

It's sometimes useful to have angular's component selector not to be rendered in the page, as sometimes this can cause problems with...