5

Tomcat logs:

java.io.IOException: Unable to create the file [/usr/local/tomcat/webapps/mywebapp/META-INF/war-tracker]
    at org.apache.catalina.startup.ExpandWar.expand(ExpandWar.java:180)
    at org.apache.catalina.startup.ContextConfig.fixDocBase(ContextConfig.java:609)
    at org.apache.catalina.startup.ContextConfig.beforeStart(ContextConfig.java:742)
    at org.apache.catalina.startup.ContextConfig.lifecycleEvent(ContextConfig.java:301)
    at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:123)
    at org.apache.catalina.util.LifecycleBase.setStateInternal(LifecycleBase.java:424)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:182)
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:743)
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:719)
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:695)
    at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:986)
    at org.apache.catalina.startup.HostConfig$DeployWar.run(HostConfig.java:1858)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75)
    at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:112)
    at org.apache.catalina.startup.HostConfig.deployWARs(HostConfig.java:772)
    at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:426)
    at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1585)
    at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:308)
    at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:123)
    at org.apache.catalina.util.LifecycleBase.setStateInternal(LifecycleBase.java:424)
    at org.apache.catalina.util.LifecycleBase.setState(LifecycleBase.java:367)
    at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:972)
    at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:831)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1432)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1422)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75)
    at java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:134)
    at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:944)
    at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:261)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
    at org.apache.catalina.core.StandardService.startInternal(StandardService.java:422)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
    at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:801)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
    at org.apache.catalina.startup.Catalina.start(Catalina.java:695)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:350)
    at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:492)

Suddenly the server does not work, Not extracted The WAR file in webapps, can not work with API requests,

Context file :

<Context>
    <WatchedResource>WEB-INF/web.xml</WatchedResource>
    <WatchedResource>${catalina.base}/conf/web.xml</WatchedResource>
</Context>

I tried to deploye from the manager on TOMCAT's page and again it was not successful.

find in logs : Unable to create the file [/usr/local/tomcat/webapps/mywebapp/META-INF/war-tracker]

I looked for solutions and did not find, anyone there that happened to him?

Tomcat : apache-tomcat-9.0.13
openjdk version "1.8.0_171"

StackzOfZtuff
  • 2,534
  • 1
  • 28
  • 25
Lior A
  • 61
  • 1
  • 9
  • I feel like there is more to the exception. Perhaps a permission denied error? Can you look further down in the log to see if there is more information? – stdunbar Nov 15 '18 at 17:17
  • Hi @stdunbarthere is no more details of the error. – Lior A Nov 15 '18 at 17:48
  • I deleted the tomcat and install another, even less versions, and the same error. – Lior A Nov 15 '18 at 17:50
  • @stdunbar i change the war file permissions like : chmod -R 777 mywebapp.war and nothing the tomcat not extract the war file. and in the log thats the error. – Lior A Nov 15 '18 at 17:51
  • Without additional information it's just a guess then. The permissions on your webapp are not important - it's the permissions on, I believe, the `META-INF` directory. Are you short on disk space? Again, I'm afraid I'm guessing with the information available. – stdunbar Nov 15 '18 at 18:09
  • Which additional information can i give? – Lior A Nov 15 '18 at 18:13
  • What about the META-INF ? @stdunbar – Lior A Nov 15 '18 at 18:13
  • When you create the `.war` file, what are the permissions for the `META-INF` directory? Are you creating the `.war` file on a Windows machine and deploying to a Linux machine? If the permissions on the `META-INF` directory do not allow writing then you will not be able to extract a file into it. – stdunbar Nov 15 '18 at 18:31
  • Yes, i give all permission to that folder from windows and warthe app and paste in webapp folderin linux. – Lior A Nov 15 '18 at 18:54
  • When the folder is extracted, what are the permissions on it in Linux? – stdunbar Nov 15 '18 at 19:01
  • -rw-r--r--. 1 root root 15461413 Nov 15 15:43 infinidat.war – Lior A Nov 15 '18 at 19:09
  • That is root permission on it... – Lior A Nov 15 '18 at 19:10
  • No, if you were to do a `jar -xf infinidat.war` on Linux into a temporary directory and do a `ls -ld META-INF`, what are the permissions of the `META-INF` directory? – stdunbar Nov 15 '18 at 20:31

3 Answers3

17

The problem is the file "META-INF/war-tracker" in the deployment-war:

From the Tomcat-docs: The Host Container:

unpackWARs
[...]
Note: If Tomcat expands the WAR file then it will add a file (/META-INF/war-tracking) [sic] to the unpacked directory structure which it uses to detect changes in the WAR file while Tomcat is not running. Any such change will trigger the deletion of the expanded directory and the deployment of the updated WAR file when Tomcat next starts.
[...]

(BTW: The documentation gets the file name wrong. It's not /META-INF/war-tracking but really /META-INF/war-tracker.)

It seems that you manually packed the war-file and included META-INF/war-tracker. During deployment, Tomcat (from version 8 onwards AFAIK) tries to create said file to detect the changes. However, if such a file exists, Tomcat is not able to create the file and will throw the exception you mentioned above.

Solution:

Remove the file "META-INF/war-tracker" from your war-file before deployment and you're all set.

StackzOfZtuff
  • 2,534
  • 1
  • 28
  • 25
greg
  • 212
  • 2
  • 8
5

We had exactly the same behaviour under Windows. In our case, the explanation was simple, whereas hard do find: there already was a file META-INF/war-tracker within the *.war we were deploying. Presumably, the war had been forged by hand based on an already unpacked directory tree instead of being created by the IDE.

Pascal
  • 51
  • 2
0

This is sort of half-an-answer or an-addon to the existing answers.

Your stacktrace contains filename ExpandWar.java and line number 180: (ExpandWar.java:180)

The line that throws the error is this:

throw new IOException(sm.getString("expandWar.createFileFailed", warTracker));

The error message that you're seeing is called expandWar.createFileFailed:

/drives/c/github.com/tomcat[main]
$ ag "expandWar.createFileFailed"
java/org/apache/catalina/startup/ExpandWar.java
178:                throw new IOException(sm.getString("expandWar.createFileFailed", warTracker));

java/org/apache/catalina/startup/LocalStrings.properties
97:expandWar.createFileFailed=Unable to create the file [{0}]

java/org/apache/catalina/startup/LocalStrings_ja.properties
97:expandWar.createFileFailed=ファイル [{0}] を作成できません

java/org/apache/catalina/startup/LocalStrings_ko.properties
97:expandWar.createFileFailed=파일 [{0}]을(를) 생성할 수 없습니다.

java/org/apache/catalina/startup/LocalStrings_fr.properties
97:expandWar.createFileFailed=Impossible de créer le fichier [{0}]

java/org/apache/catalina/startup/LocalStrings_zh_CN.properties
96:expandWar.createFileFailed=无法创建文件[{0}]

It was introduced in a commit from 2017-12-01.

General thoughts on this feature

TLDR: I don't like it. Manually unpacking WARs and then deleting the WAR saves headaches.

I THINK Tomcat SHOULD try to overwrite that file if it exists. Or maybe it's a conscious decision to rather not fail silently and instead fail loudly by not expanding the WAR at all and giving that error message. So then at least people can fix their broken WAR files.

However I think that the message should be a little clearer. "createFileFailed" could have many reasons. But I think this specific reason "Unexpected tracker file found in WAR file!?!" should have an error message of its own. -- Not sure if that makes the WAR file illegal or inconsistent as per the WAR file standard. (If there even is one.)

But as a general comment: the whole "unpackWARs"-feature has always seemed really suspicious and weird to me.

I make a point to NEVER use it. Because I don't really understand it and I don't trust it. And there are a bunch of tie-breaker if-then-else clauses inside the Tomcat documentation that I don't understand.

Namely: the documentation for "unpackWARs" defers to the "Automatic Application Deployment" section.

I don't understand this. (Although I've REALLY tried.) And so I especially don't expect people who don't regularly deal with Tomcat to understand this. -- For example my colleagues or external contractors or whoever.

I don't understand people to figure out what will happen if there is BOTH a WAR file AND an "exploded directory"/"expanded directory" underneath "webapps/".

Here's how I deal with this situation:

I make a point of ensuring this happen. I will do a sanity check that expansion worked, then shut down Tomcat, DELETE the WAR file, start Tomcat, check if things still work. Then DOCUMENT that change.

One particular point that I found problematic is that this file seems to be treated as optional but sometimes also as mandatory.

So when have both packed-WAR and unpacked-dir and /META-INF/war-tracker does NOT exist in the unpacked-dir, then there is NO check. This condition is silently ignored and is treated as no-need-to-redeploy.

Namely this in an if clause will cause this: !warTracker.exists() => so if no tracker, then no redeployment.

The code in context is this:

// Check to see of the WAR has been expanded previously
if (docBase.exists()) {
    // A WAR was expanded. Tomcat will have set the last modified
    // time of warTracker file to the last modified time of the WAR so
    // changes to the WAR while Tomcat is stopped can be detected
    if (!warTracker.exists() || warTracker.lastModified() == warLastModified) {
        // No (detectable) changes to the WAR
        success = true;
        return docBase.getAbsolutePath();
    }

    // WAR must have been modified. Remove expanded directory.
    log.info(sm.getString("expandWar.deleteOld", docBase));
    if (!delete(docBase)) {
        throw new IOException(sm.getString("expandWar.deleteFailed", docBase));
    }
}
$ ag expandWar.deleteOld
java/org/apache/catalina/startup/ExpandWar.java
109:            log.info(sm.getString("expandWar.deleteOld", docBase));

java/org/apache/catalina/startup/LocalStrings.properties
99:expandWar.deleteOld=An expanded directory [{0}] was found with a last modified time that did not match the associated WAR. It will be deleted.

java/org/apache/catalina/startup/LocalStrings_ja.properties
99:expandWar.deleteOld=関連付けられた WAR ファイルと最終更新日時の異なる展開先ディレクトリ [{0}] が見つかりました。削除します。

java/org/apache/catalina/startup/LocalStrings_fr.properties
99:expandWar.deleteOld=Un répertoire décompressé [{0}] a été trouvé avec une date de dernière modification qui ne correspond pas au WAR associé, il sera effacé

java/org/apache/catalina/startup/LocalStrings_ko.properties
99:expandWar.deleteOld=압축이 풀려진 디렉토리 [{0}]의 최종 변경 시간이, 연관된 WAR의 최종 변경 시간과 부합하지 않습니다. 해당 디렉토리는 삭제될 것입니다.

java/org/apache/catalina/startup/LocalStrings_zh_CN.properties
98:expandWar.deleteOld=发现一个展开的目录[{0}],它的最后修改时间与关联的WAR不一致.它将被删除.
✓

A valid architecture choice MIGHT have been to just refuse to start: if the tracker is important, and it does not exist in the expanded-dir, then this might well mean that the old autodeployment aborted halfway through.

The tracker file USED to be created BEFORE actually unpacking. Then a bug report was filed that basically said: "Create it AFTER unpacking, so that we can use it as an i-am-done-message":

So creation was moved to AFTER unpacking. However if we also still have this !warTracker.exists() thing flying around, then we're not really using its presence as an i-am-done-message after all, now are we? And neither are we using its ABSENCE as an i-am-NOT-done marker.

A way out of this would be to ENFORCE presence: Tomcat refuses to start unless marker present in expanded-dir. This would break SO MANY webapps. So that's not gonna work.

Another would be to refuse to start in these edgecases: you have both an unexpanded-WAR and an expanded-DIR and NO marker file. That's also abreaking change. But maybe that is something for a major release or something. It would at least remove the ambiguity. (And you could phase this change in as a WARNING for a year before you make it an ERROR in the next major release.)

StackzOfZtuff
  • 2,534
  • 1
  • 28
  • 25