You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tomcat.apache.org by Philippe Busque <pb...@mediagrif.com> on 2016/03/02 23:12:52 UTC

Context PreResources configuration question

Hello,

I've been struggling with use case which I could use some advice.
I'm migrating a multi domain, CDS published static file instance.

In short, Tomcat is deployed with a  bare minimum war containing the jar dependencies for the JSP  and the web.xml.  All the other content, we used a CMS do deploy inside the unpacked war webapps folder of a particular site.

The drawback of that approach was that, if I needed to redeploy a new war, I had to unpack it manually (as an automatic unpack would delete the files deployed through the CMS along with the file from the previously unpacked WAR).

With Tomcat 8, I was  hoping to use the new PreResources and PostResource to move the static content away from the webapps, into it's own droppath.

On my first attempt, I had this setup for my context
----------
    <Host name="www.example1.com<http://www.example1.com>" appBase="webapps/example1" unpackWARs="true" autoDeploy="false">
          <Context path="" reloadable="false" workDir="work/example1">
              <JarScanner scanBootstrapClassPath="false"/>
              <Resources>
                  <PreResources className="org.apache.catalina.webresources.DirResourceSet"  readOnly="true" webAppMount="/"  base="/home/tomcat/CMS/example1.com" />
              </Resources>
          </Context>
    </Host>
-------------------

This worked fine to access static resources (images, css, js) deployed into "/home/tomcat/CMS/example1.com" .
However, for some reason, any JSP file deployed inside that folder would crash, unable to access the dependencies Jar unpacked inside the appBase.  I thought, from reading the documentation, that the classpath from WEB-INF/lib and WEB-INF/class was always available. But from the NoClassDefFound errors, I got, it doesn't seem to be the case.

-------------------
SEVERE: Servlet.service() for servlet [jsp] in context with path [] threw exception [The absolute uri: http://java.sun.com/jsp/jstl/core cannot be resolved in either web.xml or the jar files deploy
ed with this application] with root cause
org.apache.jasper.JasperException: The absolute uri: http://java.sun.com/jsp/jstl/core cannot be resolved in either web.xml or the jar files deployed with this application
-------------------


So I tried adding the folder of my appBase manually as a PostResources.

-------------------
    <Host name="www.example1.com<http://www.example1.com>" appBase="webapps/example1" unpackWARs="true" autoDeploy="false">
          <Context path="" reloadable="false" workDir="work/example1">
              <JarScanner scanBootstrapClassPath="false"/>
              <Resources>
                  <PreResources className="org.apache.catalina.webresources.DirResourceSet"  readOnly="true" webAppMount="/"  base="/home/tomcat/CMS/example1.com" />
                  <PostResources className="org.apache.catalina.webresources.DirResourceSet" readOnly="true" webAppMount="/" base="${catalina.base}/webapps/example1" />
              </Resources>
          </Context>
    </Host>
-------------------


With this setup, the JSP deployed inside /home/tomcat/CMS/example1.com are able to access the web.xml and library from the appBase,  I would no longer receive the error and the pages would display.

However, Tomcat is validating the Resources *BEFORE* unpacking the War file into the appBase. As a result, if I start Tomcat from an undeployed state  (example1.war exists under ${catalina.base}/webapps/), tomcat crash saying that the folder "${catalina.base}/webapps/example1" does not exist.  If I create the folder and deploy the war manually, tomcat work.  But that leave me to the same point as I was with Tomcat 7: I need to manually unpack my war.

-------------------
SEVERE: A child container failed during start
java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to initialize component [StandardEngine[Catalina].StandardHost[www.example1.com<http://www.example1.com>].StandardContext[]]
....
Caused by: java.lang.IllegalArgumentException: The directory specified by base and internal path [/home/tomcat/apache-tomcat-8.0.32/webapps/example1]/[] does not exist.
        at org.apache.catalina.webresources.DirResourceSet.checkType(DirResourceSet.java:253)
        at org.apache.catalina.webresources.AbstractFileResourceSet.initInternal(AbstractFileResourceSet.java:145)
        at org.apache.catalina.webresources.DirResourceSet.initInternal(DirResourceSet.java:261)
        at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:102)
        ... 12 more

-------------------

At this point, I'm not sure where to look. I don't know why my PreResources JSP are not seeing the lib from my appBase, nor how to configure Tomcat to set them without a manual intervention,.


Tomcat Version 8.0.32
OS: Red Had 6.5
Java 1.8.0_65

Thanks

--

Philippe Busque
1111, rue St-Charles Ouest,
Tour Est, bureau 255
Longueuil (Québec) Canada J4K 5G4
Tél. : 450-449-0102 ext. 3017
Télec. : 450-449-8725

Ce message et les fichiers d’accompagnement transmis avec celui-ci s’adressent expressément au(x) destinataire(s) et peuvent contenir des renseignements confidentiels et privilégiés. Si vous recevez ce message par erreur, veuillez en aviser immédiatement l’expéditeur par courrier électronique. Veuillez également ne pas en prendre connaissance et en supprimer toutes les copies immédiatement. Technologies Interactives Mediagrif Inc. et ses filiales n’acceptent aucune responsabilité à l’égard des opinions exprimées dans le message ou des conséquences de tout virus informatique qui pourrait être transmis avec ce message. Ce message fait également l’objet d’un copyright. Il est interdit d’en reproduire, adapter ou transmettre quelque partie que ce soit sans le consentement écrit du détenteur du copyright.

This email and any files transmitted with it are solely intended for the use of the addressee(s) and may contain information that is confidential and privileged. If you receive this email in error, please advise us by return email immediately. Please also disregard the contents of the email, delete it and destroy any copies immediately. Mediagrif Interactive Technologies Inc. and its subsidiaries do not accept liability for the views expressed in the email or for the consequences of any computer viruses that may be transmitted with this email. This email is also subject to copyright. No part of it should be reproduced, adapted or transmitted without the written consent of the copyright owner.

Re: Context PreResources configuration question

Posted by Mark Thomas <ma...@apache.org>.
On 03/03/2016 20:37, Mark Thomas wrote:
> On 03/03/2016 17:08, Philippe Busque wrote:
> 
> <snip/>
> 
>> Is it normal that the context is initialized BEFORE the host is started,
>> while expecting the host to create the structure, but failing because
>> the structure is not present?
>>
>> Should the expand be executed after the host created the proper
>> structure for the context to expand it wars?
> 
> Generally, the expectation is the the appBase already exists. I'm fairly
> sure I didn't test the case you describe and I can easily imagine it
> failing.
> 
> I'll take a look. It should be possible to get this fixed before the
> next release.

Fixed. Will be in the next releases of 9.0.x, 8.0.x and 7.0.x. 6.0.x
doesn;t have the "create missing appBase" feature.

Mark


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Context PreResources configuration question

Posted by Mark Thomas <ma...@apache.org>.
On 03/03/2016 17:08, Philippe Busque wrote:

<snip/>

> Is it normal that the context is initialized BEFORE the host is started,
> while expecting the host to create the structure, but failing because
> the structure is not present?
> 
> Should the expand be executed after the host created the proper
> structure for the context to expand it wars?

Generally, the expectation is the the appBase already exists. I'm fairly
sure I didn't test the case you describe and I can easily imagine it
failing.

I'll take a look. It should be possible to get this fixed before the
next release.

Mark

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Context PreResources configuration question

Posted by Philippe Busque <pb...@mediagrif.com>.
The Wed, 02 Mar 2016 22:29:35, Mark Thomas wrote :

That was pretty much a perfect question. A clear problem statement. A
clear description of what you expected to happen vs. what actually
happened. A clear description of what you tried. If only all posts to
the users list were like this.

This is an easy fix. The problem is that with no docBase defined and a
path of "", tomcat is going to use a docBase of "ROOT". That means
Tomcat is going to look for these files in "work/example1/ROOT" not in
"work/example1".

Generally, I'd recommend a slightly different directory structure.
Something like:
webapps-example1/ROOT.war
which auto expands into
webapps-example1/ROOT

Mark

Thank you. I know how it is when someone stop at your desk for help, but not giving you any details on what the problem is :)



I followed your advices. I created separated webapps under our ${catalina.base} folder webapps-example1, webapps-example2 and so on, with a ROOT.war in each of them (what we usually do with single webapps deployment).

It work... partially. I'm getting random crash with the same error as when it couldn't find the libraries.

org.apache.jasper.JasperException: The absolute uri: <http://java.sun.com/jsp/jstl/core> http://java.sun.com/jsp/jstl/core cannot be resolved in either web.xml or the jar files deployed with this application

I first thought it was browser cache, but after testing a few time with wget on Tomcat itself and still getting the error, I have the feeling I'm hitting a cache inside tomcat. Why it's random, I have no clue.



Next I tried the docBase approach I totally forgot about that setting  after we removed them when they got a behaviour change midway in Tomcat 7 and it was recommended not to used them.

With webapps-example1 and webapps-example2, everything and a configured docBase, everything worked. Multiple refresh did not cause random class not found without the docBase.  However, since I have a dozen webapps, leaving 12 extra webapps folders under ${catalina.base} fell  a bit cumbersome.


So I tried again with the following directory structure :
webapps/example1/ROOT
webapps/example2/ROOT


It worked like a charm too, but I noticed something that may be a priority order issues between ContextConfig and HostConfig.

With this configuration:

------
    <Host name="www.example1.com<http://www.example1.com>" appBase="webapps/example1" unpackWARs="true" autoDeploy="false">
          <Context path="" reloadable="false" workDir="work/sourcesuite" docBase="/home/tomcat/wars/example1.war">
              <JarScanner scanClassPath="false" scanBootstrapClassPath="false"/>
              <Resources>
                  <PreResources className="org.apache.catalina.webresources.DirResourceSet"  readOnly="true" webAppMount="/"
                  base="/home/tomcat/CMS/example1.com" />
              </Resources>
          </Context>
    </Host>
------


if I create ${catalina.base}/webapps and none of it's host appBase, I get the following error:

------
Mar 03, 2016 11:19:07 AM org.apache.catalina.startup.ContextConfig beforeStart
SEVERE: Exception fixing docBase for context []
java.io.IOException: Unable to create the directory [/vol0/home/cda/servers/CDA1/webapps/mediagrif/ROOT]
        at org.apache.catalina.startup.ExpandWar.expand(ExpandWar.java:115)
        at org.apache.catalina.startup.ContextConfig.fixDocBase(ContextConfig.java:617)
        at org.apache.catalina.startup.ContextConfig.beforeStart(ContextConfig.java:753)
        at org.apache.catalina.startup.ContextConfig.lifecycleEvent(ContextConfig.java:307)
        at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:95)
        at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:90)
        at org.apache.catalina.util.LifecycleBase.setStateInternal(LifecycleBase.java:394)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:144)
        at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1408)
        at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1398)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        at java.lang.Thread.run(Thread.java:745)


        // Create the new document base directory
        if(!docBase.mkdir() && !docBase.isDirectory()) {
            throw new IOException(sm.getString("expandWar.createFailed", docBase));
        }

------

The source reveal that ExpandWar try to do a mkdir but not a mkdirs  . Since the parent is absent, it fail and crash.

BUT, some moment later, the HostConfig class is creating those exact parents, recursively.

-----
        if (host.getCreateDirs()) {
            File[] dirs = new File[] {host.getAppBaseFile(),host.getConfigBaseFile()};
            for (int i=0; i<dirs.length; i++) {
                if (!dirs[i].mkdirs() && !dirs[i].isDirectory()) {
                    log.error(sm.getString("hostConfig.createDirs",dirs[i]));
                }
            }


        at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1528)
        at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:286)
        at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:95)
        at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:90)
        at org.apache.catalina.util.LifecycleBase.setStateInternal(LifecycleBase.java:394)
        - locked <0xa00e6120> (a org.apache.catalina.core.StandardHost)
        at org.apache.catalina.util.LifecycleBase.setState(LifecycleBase.java:339)
        - locked <0xa00e6120> (a org.apache.catalina.core.StandardHost)
        at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:933)
        - locked <0xa00e6120> (a org.apache.catalina.core.StandardHost)
        at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:871)
        - locked <0xa00e6120> (a org.apache.catalina.core.StandardHost)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:147)
        - locked <0xa00e6120> (a org.apache.catalina.core.StandardHost)
        at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1408)
        at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1398)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        at java.lang.Thread.run(Thread.java:745)

-----

Is it normal that the context is initialized BEFORE the host is started, while expecting the host to create the structure, but failing because the structure is not present?

Should the expand be executed after the host created the proper structure for the context to expand it wars?


Thanks
--

Philippe Busque
1111, rue St-Charles Ouest,
Tour Est, bureau 255
Longueuil (Québec) Canada J4K 5G4
Tél. : 450-449-0102 ext. 3017
Télec. : 450-449-8725






Ce message et les fichiers d’accompagnement transmis avec celui-ci s’adressent expressément au(x) destinataire(s) et peuvent contenir des renseignements confidentiels et privilégiés. Si vous recevez ce message par erreur, veuillez en aviser immédiatement l’expéditeur par courrier électronique. Veuillez également ne pas en prendre connaissance et en supprimer toutes les copies immédiatement. Technologies Interactives Mediagrif Inc. et ses filiales n’acceptent aucune responsabilité à l’égard des opinions exprimées dans le message ou des conséquences de tout virus informatique qui pourrait être transmis avec ce message. Ce message fait également l’objet d’un copyright. Il est interdit d’en reproduire, adapter ou transmettre quelque partie que ce soit sans le consentement écrit du détenteur du copyright.

This email and any files transmitted with it are solely intended for the use of the addressee(s) and may contain information that is confidential and privileged. If you receive this email in error, please advise us by return email immediately. Please also disregard the contents of the email, delete it and destroy any copies immediately. Mediagrif Interactive Technologies Inc. and its subsidiaries do not accept liability for the views expressed in the email or for the consequences of any computer viruses that may be transmitted with this email. This email is also subject to copyright. No part of it should be reproduced, adapted or transmitted without the written consent of the copyright owner.

Re: Context PreResources configuration question

Posted by Mark Thomas <ma...@apache.org>.
On 02/03/2016 22:12, Philippe Busque wrote:

<snip/>

> In short, Tomcat is deployed with a  bare minimum war containing the jar
> dependencies for the JSP  and the web.xml.  All the other content, we
> used a CMS do deploy inside the unpacked war webapps folder of a
> particular site.
> 
> The drawback of that approach was that, if I needed to redeploy a new
> war, I had to unpack it manually (as an automatic unpack would delete
> the files deployed through the CMS along with the file from the
> previously unpacked WAR).
> 
> With Tomcat 8, I was  hoping to use the new PreResources and
> PostResource to move the static content away from the webapps, into it's
> own droppath.
> 
> On my first attempt, I had this setup for my context
> ----------
>    <Host name="www.example1.com<http://www.example1.com>"
> appBase="webapps/example1" unpackWARs="true" autoDeploy="false">
>          <Context path="" reloadable="false" workDir="work/example1">
>              <JarScanner scanBootstrapClassPath="false"/>
>              <Resources>
>                  <PreResources
> className="org.apache.catalina.webresources.DirResourceSet" 
> readOnly="true" webAppMount="/"  base="/home/tomcat/CMS/example1.com" />
>              </Resources>
>          </Context>
>    </Host>
> -------------------
> 
> This worked fine to access static resources (images, css, js) deployed
> into "/home/tomcat/CMS/example1.com" .
> However, for some reason, any JSP file deployed inside that folder would
> crash, unable to access the dependencies Jar unpacked inside the
> appBase.  I thought, from reading the documentation, that the classpath
> from WEB-INF/lib and WEB-INF/class was always available. But from the
> NoClassDefFound errors, I got, it doesn't seem to be the case.

<snip/>

> So I tried adding the folder of my appBase manually as a PostResources.
> 
> -------------------
>    <Host name="www.example1.com<http://www.example1.com>"
> appBase="webapps/example1" unpackWARs="true" autoDeploy="false">
>          <Context path="" reloadable="false" workDir="work/example1">
>              <JarScanner scanBootstrapClassPath="false"/>
>              <Resources>
>                  <PreResources
> className="org.apache.catalina.webresources.DirResourceSet" 
> readOnly="true" webAppMount="/"  base="/home/tomcat/CMS/example1.com" />
>                  <PostResources
> className="org.apache.catalina.webresources.DirResourceSet"
> readOnly="true" webAppMount="/" base="${catalina.base}/webapps/example1" />
>              </Resources>
>          </Context>
>    </Host>
> -------------------
> 
> 
> With this setup, the JSP deployed inside /home/tomcat/CMS/example1.com
> are able to access the web.xml and library from the appBase,  I would no
> longer receive the error and the pages would display.
> 
> However, Tomcat is validating the Resources *BEFORE* unpacking the War
> file into the appBase. As a result, if I start Tomcat from an undeployed
> state  (example1.war exists under ${catalina.base}/webapps/), tomcat
> crash saying that the folder "${catalina.base}/webapps/example1" does
> not exist.  If I create the folder and deploy the war manually, tomcat
> work.  But that leave me to the same point as I was with Tomcat 7: I
> need to manually unpack my war.

<snip/>

> At this point, I'm not sure where to look. I don't know why my
> PreResources JSP are not seeing the lib from my appBase, nor how to
> configure Tomcat to set them without a manual intervention,.
> 
> 
> Tomcat Version 8.0.32
> OS: Red Had 6.5
> Java 1.8.0_65
> 
> Thanks

That was pretty much a perfect question. A clear problem statement. A
clear description of what you expected to happen vs. what actually
happened. A clear description of what you tried. If only all posts to
the users list were like this.

This is an easy fix. The problem is that with no docBase defined and a
path of "", tomcat is going to use a docBase of "ROOT". That means
Tomcat is going to look for these files in "work/example1/ROOT" not in
"work/example1".

Generally, I'd recommend a slightly different directory structure.
Something like:
webapps-example1/ROOT.war
which auto expands into
webapps-example1/ROOT

Mark


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org