Showing posts with label maven. Show all posts
Showing posts with label maven. Show all posts

Friday, April 19, 2013

Hosting Ivy or Maven repository on Github with Gradle

If you don't have access to any public repo, but want to host libraries - then Github can be a solution.
Unfortunately, it does not provide proper interfaces for the client applications, but this is still possible.

Lets say that local root folder of your git project is /test.
First, you need to create all necessary poms and jars. To do it, you have to add this to your build.gradle file:

uploadArchives {
  repositories {
    mavenDeployer {
      repository(url: "file:///test/repo")
    }
  }
}

URL property is for proper Maven repository - for now unfortunately, Github is not, so you will have to enter some local folder. After this is added, run Gradle task uploadArchives, then commit and push all output files with git.

Unfortunately, this is not all, as SHA signature is wrong, because your git URL is not same as local. So you will need to find out proper SHA, and until you want to calculate it yourself, one easy way to do it is find some talkative Maven client, for example Grape. Luckily it is part of normal Groovy installation.

Then, you need to add new repo into Grape configuration, open ${user.home}/.groovy/grapeConfig.xml file and add your new repo like

<ibiblio name="myrepo" root="https://raw.github.com/me/mymodule/master/repo" m2compatible="true"/>

And, to get dependencies, just run Grape in verbose mode, for example like:

grape -V install my.group mymodule 0.1

It will fail, but you will get one great error message like:

...-0.1.pom: invalid sha1: expected=7f1089041d63ce7eaa5d6a35ddda3aaa606042e3 computed=8a941ef40645d449b0740023624c2f8b67b84c59 (516ms)

8a941ef40645d449b0740023624c2f8b67b84c59 is what we were looking for.
Just find file whose signature was incorrect, for example for pom it can be mymodule.pom.sha1, update it with new signature and push into git.

That is all, you have new great Maven repository with root under https://raw.github.com/me/mymodule/master/repo.


Tuesday, September 20, 2011

Running ant task in maven

Sometimes you have some task that you just need to execute: without attaching to build phase, or any process - just run. Unfortunately maven is not very flexible about it. Fortunately, it is still possible. To do it, you need use antrun plugin with custom profile. For example, like this:

<profiles>
  <profile>
     <id>deploy</id>
     <build>
        <plugins>
          <plugin>
            <artifactId>maven-antrun-plugin</artifactId>
            <version>1.3</version>
            <configuration>
              <tasks>
                <property file="user.properties" prefix="user"/>
                <scp file="target/target.war" todir="${user.login}:${user.password}@${user.server}:/home/user/" trust="true"/>
                <sshexec host="${user.server}" username="${user.login}" password="${user.password}" command="sudo ./redeploy.sh" trust="true" />
              </tasks>
            </configuration>
            <dependencies>
                <dependency>
                    <groupId>org.apache.ant</groupId>
                    <artifactId>ant-jsch</artifactId>
                    <version>1.7.1</version>
                </dependency>
                <dependency>
                    <groupId>com.jcraft</groupId>
                    <artifactId>jsch</artifactId>
                    <version>0.1.42</version>
                </dependency>
            </dependencies>
          </plugin>
        </plugins>
     </build>
  </profile>
...

</profiles>

Later, you can run this script like:


mvn antrun:run -Pdeploy

Of course you can have different scripts in several profiles.

This approach even has advantages over having separate Ant's build.xml - you don't need to have separate Ant installation, or for instance, with example above, you don't need to download jsch plugin separately - it is all done by Maven.

Saturday, June 25, 2011

Executable WAR and jetty:run

After creating executable WAR I have noticed that when I run application with jetty:run, there is conflict between jetty libs from maven plugin and application dependencies:

2011-06-26 00:54:14.067:INFO::jetty-8.0.0.M2
2011-06-26 00:54:15.779:WARN::Failed startup of context JettyWebAppContext@5a347448@5a347448/myexecutable,file:/
java.lang.IllegalArgumentException: Object is not of type class org.eclipse.jetty.webapp.WebAppContext
        at org.eclipse.jetty.xml.XmlConfiguration.configure(XmlConfiguration.java:204)
        at org.eclipse.jetty.plus.webapp.EnvConfiguration.configure(EnvConfiguration.java:98)
        at org.eclipse.jetty.webapp.WebAppContext.configure(WebAppContext.java:473)
        at org.eclipse.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1174)
        at org.eclipse.jetty.server.handler.ContextHandler.doStart(ContextHandler.java:598)
        at org.eclipse.jetty.webapp.WebAppContext.doStart(WebAppContext.java:496)
        at org.mortbay.jetty.plugin.JettyWebAppContext.doStart(JettyWebAppContext.java:175)
        at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:55)
        at org.eclipse.jetty.server.handler.HandlerCollection.doStart(HandlerCollection.java:226)
        at org.eclipse.jetty.server.handler.ContextHandlerCollection.doStart(ContextHandlerCollection.java:164)
        at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:55)
        at org.eclipse.jetty.server.handler.HandlerCollection.doStart(HandlerCollection.java:226)
        at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:55)
        at org.eclipse.jetty.server.handler.HandlerWrapper.doStart(HandlerWrapper.java:93)
        at org.eclipse.jetty.server.Server.doStart(Server.java:244)
        at org.mortbay.jetty.plugin.JettyServer.doStart(JettyServer.java:67)
        at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:55)
        at org.mortbay.jetty.plugin.AbstractJettyMojo.startJetty(AbstractJettyMojo.java:447)
        at org.mortbay.jetty.plugin.AbstractJettyMojo.execute(AbstractJettyMojo.java:387)
        at org.mortbay.jetty.plugin.JettyRunMojo.execute(JettyRunMojo.java:555)
        at org.apache.maven.plugin.DefaultPluginManager.executeMojo(DefaultPluginManager.java:490)
        at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoals(DefaultLifecycleExecutor.java:694)
        at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeStandaloneGoal(DefaultLifecycleExecutor.java:569)
        at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoal(DefaultLifecycleExecutor.java:539)
        at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoalAndHandleFailures(DefaultLifecycleExecutor.java:387)
        at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeTaskSegments(DefaultLifecycleExecutor.java:348)
        at org.apache.maven.lifecycle.DefaultLifecycleExecutor.execute(DefaultLifecycleExecutor.java:180)

I have found that this problem can be quickly solved by using maven profiles.
All that is needed to do is to define new profile, and move all dependencies there:

<profiles>
  <profile>
      <id>myexecutablewar</id>
      <activation>
        <property>
          <name>myexecutablewar</name>
          <value>true</value>
        </property>
      </activation>
    <dependencies>

        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-server</artifactId>
            <version>8.0.0.M2</version>
        </dependency>

        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-jndi</artifactId>
            <version>8.0.0.M2</version>
        </dependency>

        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-plus</artifactId>
            <version>8.0.0.M2</version>
        </dependency>

        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-start</artifactId>
            <version>8.0.0.M2</version>
        </dependency>

        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-webapp</artifactId>
            <version>8.0.0.M2</version>
        </dependency>

        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-servlet</artifactId>
            <version>8.0.0.M2</version>
        </dependency>

        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-util</artifactId>
            <version>8.0.0.M2</version>
        </dependency>

        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-jmx</artifactId>
            <version>8.0.0.M2</version>
        </dependency>

        <dependency>
            <groupId>org.mortbay.jetty</groupId>
            <artifactId>jsp-2.1-glassfish</artifactId>
            <version>2.1.v20100127</version>
        </dependency>
    </dependencies>

  </profile>
</profiles>

Now, when you simply run

mvn jetty:run

it runs without using dependencies, but when you run

mvn install -Dmyexecutablewar=true
it uses dependencies and creates executable package.

Executable WAR

Recently I created very small and lightweight web application. It supposed to be using web sockets, so I decided to use Jetty as application server, but instead of using it like container, I decided to save on project and configuration folders and scripts and deploy it as executable WAR.
It was surprisingly easy to do. Basically, only thing that is needed is maven with Shade plugin. This plugin allows to pack all dependencies together in single JAR. Also it allows to modify manifest, and comes with simple examples.
So, all you need to do is to add jetty dependencies to pom.xml, for example:

        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-server</artifactId>
            <version>8.0.0.M2</version>
        </dependency>

        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-jndi</artifactId>
            <version>8.0.0.M2</version>
        </dependency>

        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-plus</artifactId>
            <version>8.0.0.M2</version>
        </dependency>

        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-start</artifactId>
            <version>8.0.0.M2</version>
        </dependency>

        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-webapp</artifactId>
            <version>8.0.0.M2</version>
        </dependency>

        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-servlet</artifactId>
            <version>8.0.0.M2</version>
        </dependency>

        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-util</artifactId>
            <version>8.0.0.M2</version>
        </dependency>

        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-jmx</artifactId>
            <version>8.0.0.M2</version>
        </dependency>

        <dependency>
            <groupId>org.mortbay.jetty</groupId>
            <artifactId>jsp-2.1-glassfish</artifactId>
            <version>2.1.v20100127</version>
        </dependency>

And Shade plugin configuration:

            <plugin>
              <groupId>org.apache.maven.plugins</groupId>
              <artifactId>maven-shade-plugin</artifactId>
              <version>1.4</version>
            <executions>
              <execution>
                <phase>package</phase>
                <goals>
                  <goal>shade</goal>
                </goals>
                <configuration>
                  <artifactSet>
                    <includes>
                      <include>org.eclipse.jetty:*</include>
                      <include>org.mortbay.jetty:*</include>
                      <include>net.sourceforge.jtds:jtds</include>
                      <include>org.slf4j:*</include>
                      <include>log4j:*</include>
                      <include>c3p0:c3p0</include>
                    </includes>
                  </artifactSet>
                  <transformers>
                    <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                      <manifestEntries>
                        <Main-Class>org.eclipse.jetty.start.Main</Main-Class>
                        <Build-Number>123</Build-Number>
                      </manifestEntries>
                    </transformer>
                  </transformers>
                </configuration>
              </execution>
            </executions>
            </plugin>


And as output you should get nice, executable WAR web application, that is ready to be launched as easy as:

java -jar myexecutable.war jetty.xml

Of course it is good idea to externalize logging or jetty configuration in separate jetty.xml file, so you can change it without creating new deployment.
It can be as simple as:

<?xml version="1.0"?>
<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://jetty.mortbay.org/configure.dtd">
<Configure id="FileServer" class="org.eclipse.jetty.server.Server">

    <Call name="addConnector">
      <Arg>
          <New class="org.eclipse.jetty.server.nio.SelectChannelConnector">
            <Set name="port">8080</Set>
            <Set name="Host">localhost</Set>
          </New>
      </Arg>
    </Call>

    <Set name="handler">
      <New class="org.eclipse.jetty.server.handler.HandlerList">
        <Set name="handlers">
          <Array type="org.eclipse.jetty.server.Handler">
            <Item>
              <New class="org.eclipse.jetty.webapp.WebAppContext">
                <Set name="contextPath">/myexecutable</Set>
                <Set name="war">myexecutable.war</Set>
              </New>
            </Item>
          </Array>
        </Set>
      </New>
    </Set>

  <New id="onewalletDS" class="org.eclipse.jetty.plus.jndi.Resource">
    <Arg>myDS</Arg>
    <Arg>
      <New class="com.mchange.v2.c3p0.ComboPooledDataSource">
         <Set name="driverClass">net.sourceforge.jtds.jdbcx.JtdsDataSource</Set>
         <Set name="user">user</Set>
         <Set name="password">password</Set>
         <Set name="jdbcUrl">jdbc:jtds:sqlserver://localhost/myds</Set>
     </New>
    </Arg>
  </New>

</Configure>