3

I want to assemble a war file w/o any jar files (I copied them to my /opt/tomcat8/lib dir already).

I read about -nojars options, but it's not available for Grails 3.1.7.

Then I tried customizing my build.gradle:

war{
  rootSpec.exclude "**/*.jar"
}

and the resulting war indeed became very small ~1 MB. Although when I deploy it into a tomcat and call the http://host:8080/, I'm getting

javax.servlet.ServletException: Could not resolve view with name '/error' in servlet with name 'grailsDispatcherServlet' org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1229) org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1029) org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:973) org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:895) org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:967)

What's the proper way to build the slim war's?

SIDE NOTE:

The application contains only of a couple of domain classes and scaffolded controllers. No views were modified after grails create-app

injecteer
  • 20,038
  • 4
  • 45
  • 89
  • did you try this solution: http://stackoverflow.com/a/24831624/4769188 ? This method described here: https://srinatha.wordpress.com/2010/02/22/reducing-grails-deployment-size/ – Taras Kohut Jun 09 '16 at 07:52
  • basically this is exactly what I did so far – injecteer Jun 09 '16 at 09:13

2 Answers2

3

First in your build.gradle you have to change scope of all compile dependencies to provided. For some reason runtime dependencies must be kept for Grails to work (i don't have explanation for that yet).

For example compile "org.grails:grails-core" will be changed to provided "org.grails:grails-core"

This will stop gradle to package libs to WEB-INF/lib, but it will now create new folder WEB-INF/lib-provided with all dependencies. These libs should not be visible to 'external' application server, but are required for archive (in this case war) execution. This is done by bootRepackage task.

You can disable bootRepackage task by adding this command to your build.gradle:

bootRepackage.enabled = false

Now your war task should create archive without any jars.

Loucher
  • 316
  • 3
  • 11
  • please elaborate on `set scope of all dependencies to provided` – injecteer Jun 14 '16 at 10:08
  • I've modified my answer for clarification – Loucher Jun 14 '16 at 16:13
  • should I put `bootRepackage.enabled = false` to some specific task, or simply to the root? – injecteer Jun 14 '16 at 22:46
  • so, I tried the `provided` trick, and got a war file of ~ 1 MB (with all jars stripped, as in my original attempt). Upon calling the index, I'm getting `ERROR org.springframework.boot.context.web.ErrorPageFilter - Forwarding to error page from request [/] due t o exception [Could not resolve view with name '/index' in servlet with name 'grailsDispatcherServlet']` – injecteer Jun 14 '16 at 22:56
  • it looks like you have to keep `runtime` dependencies in war and only `compile` can be removed. For your project it should be only `asset-pipeline` and `h2`, so still significant war size reduction. – Loucher Jun 16 '16 at 11:59
  • I left `runtime 'com.bertramlabs.plugins:asset-pipeline-grails:2.8.2'` (I don't use `h2`) and changed `compile` to `provided`. I'm still getting the exception though... – injecteer Jun 16 '16 at 12:41
  • now I've noticed, that my grails project is not 3.1.7 but 3.1.4 (i have 3.1.7 installed but 3.1.4 was set as default). 3.1.4 works fine, but when i now created 3.1.7 I'm getting same exception. Looks like there could be a bug in new version of asset plugin – Loucher Jun 16 '16 at 16:46
  • that's a nice hint! I'll try it out – injecteer Jun 16 '16 at 18:14
  • switching back to 3.1.4 and using `provided` or `rootSpec.exclude "**/*.jar"` did help – injecteer Jun 17 '16 at 09:08
0

As a follow-up, I created an issue, and as Graeme couldn't reproduce the behavior, the ticket was closed. Although for me it still didn't work.

So I came up with a simple workaround, which is not that elegant as my original wish, but is very straight-forward:

  1. unzip the slim .war-file into ~/ROOT/

  2. copy all Grails 3.1.11 + plugins dependency jars into ~/ROOT/WEB-INF/lib

Note: sym-link DID NOT work...

  1. move the ~/ROOT folder to /opt/tomcat/webapps

Thus, the war file I create on my build-machine and send over to prod remains thin

injecteer
  • 20,038
  • 4
  • 45
  • 89