Showing posts with label tomcat. Show all posts
Showing posts with label tomcat. 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)


Thursday, February 13, 2014

Storing sessions in Redis with Spring Boot

Tomcat has nice support to use Redis for session replication with this awesome library. However Spring Boot launches embedded Tomcat, so there is no traditional XML configuration, it is still super easy to change default manager to use Redis for session replication, just define containerCustomizer bean, like:

@Configuration
@EnableAutoConfiguration
@ComponentScan
public class App {
  public App() {
  }

  @Bean
  public EmbeddedServletContainerCustomizer containerCustomizer(){
    return factory -> {
      TomcatEmbeddedServletContainerFactory containerFactory = (TomcatEmbeddedServletContainerFactory) factory;
      containerFactory.addContextValves(new RedisSessionHandlerValve());
      containerFactory.setTomcatContextCustomizers(Arrays.asList(context -> {
        context.setSessionTimeout(30);
        context.setManager(new RedisSessionManager(){{
          setHost("redis.server.com");
        }});
      }));
    };
  }

  public static void main(String[] args) throws Exception {
    SpringApplication.run(App.class, args);
  }
}

(this is syntax with new shiny Java 8 lambdas, but with few additional boring types it should compile in old Javas too).

Friday, November 1, 2013

Traffic redirection to https in Grails behind load balancer

Grails security plugin has nice feature that allows automatically redirect queries for specific pages to https. For example, you can put this code into Config.groovy to redirect all requests:


grails.plugins.springsecurity.secureChannel.definition = [
    '/**':         'REQUIRES_SECURE_CHANNEL'
]

Unfortunately this does not work when your Tomcat is behind load balancer that does all encryption. To do it requires a little more work.

First, it is needed to specify how to detect either connection is secure or not. Standard way to do it with load balancers is to use X-Forwarded-Proto header. So it needs to be specified in Config.groovy like:

grails.plugins.springsecurity.secureChannel.useHeaderCheckChannelSecurity = true
grails.plugins.springsecurity.portMapper.httpsPort = 443

Worst part, is that it requires Tomcat reconfiguration, so it is needed to update Connector element in server.xml, like:

<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443"  proxyName="yourserver.com" proxyPort="443" secure="true" scheme="https"  />

Good part is that it works nicely locally and across multiple environments, no need for fake certificates or different builds.


Wednesday, August 28, 2013

Jenkins kills Tomcat or other Java process after job ends

Recently, I was adding new application deployment to Tomcat server that was started by Jenkins. Process was starting nicely, but was stopping at the end of the job. The only clue was log record:

Service exit with a return value of 143

This issue can be easily solved by adding -Xrs to JAVA_OPTS. Option description can be found at http://docs.oracle.com/javase/6/docs/technotes/tools/windows/java.html.


Thursday, March 21, 2013

How to kill Tomcat server running from standalone plugin

I have demo application which is running from Grails standalone plugin and wanted to automate deployment from Jenkins. Starting such application is well documented and easy, but there is nothing about stopping it.
After quick digging plugin's code, I found that it has undocumented feature to do it. It creates server on application server port + 1, and as soon as there is connection - shuts server. So if your server port is 8080, this command from same computer will kill server:

telnet localhost 8081

Friday, January 25, 2013

grails-coffeescript-resources is not working after deploying war in production

There is great Grails plugin that allows to work with CoffeeScript very easily, compiles .coffee files on the fly and does all dirty work.
However, once I tried to deploy my application to test environment, all CoffeeScript files became available in browser as is, without compilation. After some investigation I found out that problem is that it does not supports applications deployed as packed WAR files (with unpackWARs="false" in server.xml), it was pretty easy to fix by modifying plugin script grails-app/resourceMappers/CoffeeScriptResourceMapper.groovy by changing:
 
      File input = grailsApplication.parentContext.getResource(resource.sourceUrl).file

to this

      File input
      try {
        input = grailsApplication.parentContext.getResource(resource.sourceUrl).file
      } catch (FileNotFoundException e) {
        input = new File(original.absolutePath)
      }


and it should work.
One problem is that this change is inside plugin, so you can't do change in your code, and should change plugin itself. I submitted fix with pull request on GitHub, hopefully it will be merged. Until then it is possible to compile your own version from here, or just replace this one line on build server.


Friday, January 18, 2013

Working around grails.serverURL redirect in Grails 2

The most annoying issue with Grails 2 migration is that it requires redirection to grails.serverURL when it is specified. This property is needed if there are absolute links in application (in emails, for example).
First problem that I had with it, was after deploying application to test environment. We deploy production version, so all redirects became redirects to production, this could be solved by externalizing Grails configuration.
Second problem was more severe. We have following setup: load balancer with two nodes behind it. Our deployment script takes first node down, deploys, runs smoke tests, releases first node, takes second node down, deploys, smoke tests, releases.
So basically, production URL is load balancer's entry point, and when smoke tests run on node which is down it is never redirected to tested server (because it is down and it is behind load balancer), so every redirect (after spring security login, for example), breaks tests flow.
After some digging around, I found the best option is to abandon grails.serverURL - which is totally unusable now, and add to email link generation my own parameter from externalized Grails configuration (for each environment). This is sad as createLink with absolute parameter was great function and it didn't required dragging custom parameters.
That is how it is now.
What I would love to see in the future is grails.serverURL is used ONLY in all links generated with absolute:true and nowhere else, but all redirects work as if grails.serverURL not specified at all.

Thursday, January 17, 2013

"Cannot find any VM in Java Home ..." error in Tomcat

During migration from JDK 6 to 7, I found strange issue: Tomcat was working fine when starting via catalina.sh, but was failing when starting via jsvc with just this error:

Cannot find any VM in Java Home /usr/lib/jvm/jdk1.7.0_10/

Jsvc recompilation or any other measure was not helping, but finally I found out that it was running flawless with specific x64 version of JDK instead of i586 version.

Tuesday, September 18, 2012

Javamelody SQL monitoring with Grails plugin

Javamelody is amazing tool for live monitoring. It has great Grails plugin which makes it very easy to use. Only issue I had with it is SQL monitoring configuration.
According to documentation there are several ways to configure data sources:
  1. magic - you don't have to do anything, it just works
  2. javamelody.datasources property in GrailsMelodyConfig.groovy - you just specify datasources
  3. replacing JDBC driver with Javamelody proxy
  4. specifying java option - javamelody.datasources
Unfortunately, all internal configuration options (1, 2, 3) didn't worked. As I investigated (quickly) it looks like there is no dataSource bean available for BeanPostProcessor and it tries to proxy after all connections were already picked by application.
So only specifying java command line option worked for me. Otherwise - great tool. It is also possible to specify multiple data sources with command line like:


-Djavamelody.datasources=java:comp/env/ds1,java:comp/env/ds2

Tuesday, December 20, 2011

Too many idle database connections with Tomcat

I recently had problem when there were too many open database connections in Tomcat. Everything was right, but number is far more then is defined in Tomcat resources.
After some investigation, I have found that problem was that datasources were defined in wrong place - conf/context.xml, and when they are defined there, they are picked for every Web application that is defined in this Tomcat instance (including management and utility), therefore you will have all your connections multiplied by number of applications you have.
Fortunately, it is easy to fix by defining resources under conf/Catalina/localhost/ROOT.xml (ROOT if application is defined under root, otherwise, name of your application), in which case, resources will be provided only for specified application.