Showing posts with label jetty. Show all posts
Showing posts with label jetty. Show all posts

Wednesday, April 30, 2014

Launching Spring Boot in Groovy with Grab

Since launch of Spring Boot I was wondering why it needs separate CLI, especially for Groovy where there is already Grab. Of course CLI provides some additional features, like reloading and out of the box dependencies, but why no one runs Boot with vanilla Groovy? So I tried it myself, and it looks like problem is that there is conflict with default Groovy libs, because standard installation includes servlet-api-2.4.jar which does not work with current Tomcat or Jetty, and as there is no anything like fork mode in Grails, there is only one way to avoid it - not to load this jar (delete it or use custom load conf).

Otherwise this works fine for me:

@Grab("org.springframework.boot:spring-boot-starter-web:1.0.2.RELEASE")
@Grab("org.springframework.boot:spring-boot-starter-actuator:1.0.2.RELEASE")
import org.springframework.boot.SpringApplication
import org.springframework.boot.autoconfigure.EnableAutoConfiguration
import org.springframework.web.bind.annotation.*

@RestController
@EnableAutoConfiguration
class ThisWillActuallyRun {

  @RequestMapping("/")
  String home() {
    "Hello World!"
  }
}
SpringApplication.run(ThisWillActuallyRun, args)


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>

Thursday, May 27, 2010

"There is no Action mapped" error for Struts 2 in Jetty

Recently I was trying to configure Struts 2 with Jetty. Everything was running smooth untill I tried to setup Convention plugin.

This plugin provides configuration by convention rather than XML files and has several nice features like annotation mappings for methods and reasonable default mappings. Nice plugin overall but somehow it didn't wanted to work with Jetty. It was finding JSP files without problems, but totally ignored my Actions.

I had this error:

There is no Action mapped for namespace / and action name ########. - [unknown location]
    at com.opensymphony.xwork2.DefaultActionProxy.prepare(DefaultActionProxy.java:178)
    at org.apache.struts2.impl.StrutsActionProxy.prepare(StrutsActionProxy.java:61)
...


After experimenting for some time, I found that there is some mess with Jetty class loaders and to solve it there is nice configuration property for plugin itself. If you have the same issue you can fix it by adding

  <constant name="struts.convention.exclude.parentClassLoader" value="false" />

to your struts.xml file.
Ironically, good old configuration solved convention plugin issues.