Serdar Gökay created CAMEL-25427:
------------------------------------

             Summary: camel-support - on-demand route reload fails with 
FileNotFoundException after a route file is removed from the source dir
                 Key: CAMEL-25427
                 URL: https://issues.apache.org/jira/browse/CAMEL-25427
             Project: Camel
          Issue Type: Bug
          Components: camel-jbang, camel-core
    Affects Versions: 4.22.1
         Environment: Camel JBang 4.22.1, JBang 0.139.3, Java 25.0.4, macOS
            Reporter: Serdar Gökay


On-demand route reload fails when one of several route files has been removed 
from the source directory, for example after a route file was renamed. The 
reload removes all routes and then fails with a FileNotFoundException for the 
removed file. Afterwards no route runs, including the routes of files that did 
not change, and every later on-demand reload fails the same way until the JVM 
is restarted.

h3. Reproduce

Camel JBang 4.22.1 with two route files in a {{src}} directory:
{noformat}
# src/a.camel.yaml
- route:
    id: a
    from:
      uri: timer:a?period=10000
      steps:
        - log: tick a

# src/b.camel.yaml
- route:
    id: b
    from:
      uri: timer:b?period=10000
      steps:
        - log: tick b
{noformat}
{noformat}
camel run --source-dir=src --console --port=18761 --management-port=18762
# routes a and b start
rm src/b.camel.yaml
curl 'http://localhost:18762/q/dev/reload?reload=true'
curl -H 'Accept: application/json' http://localhost:18762/q/dev/route   # no 
routes left, a is gone too
curl 'http://localhost:18762/q/dev/reload?reload=true'                  # fails 
again
{noformat}

Expected: route {{b}} is removed and route {{a}} is reloaded and keeps running.

Actual: both routes are gone, and each reload logs:
{noformat}
WARN  RouteOnDemandReloadStrategy : Error reloading routes due to 
java.io.FileNotFoundException: Resource not found: file:src/b.camel.yaml. This 
exception is ignored.
org.apache.camel.RuntimeCamelException: java.io.FileNotFoundException: Resource 
not found: file:src/b.camel.yaml
    at 
org.apache.camel.support.RouteWatcherReloadStrategy.onRouteReload(RouteWatcherReloadStrategy.java:388)
    at 
org.apache.camel.support.RouteOnDemandReloadStrategy.doOnReload(RouteOnDemandReloadStrategy.java:120)
    at 
org.apache.camel.support.RouteOnDemandReloadStrategy.onReload(RouteOnDemandReloadStrategy.java:75)
    at 
org.apache.camel.impl.console.ReloadDevConsole.lambda$doCallText$0(ReloadDevConsole.java:62)
Caused by: java.io.FileNotFoundException: Resource not found: 
file:src/b.camel.yaml
    at 
org.apache.camel.dsl.yaml.YamlRoutesBuilderLoader.preParseRoute(YamlRoutesBuilderLoader.java:667)
    at 
org.apache.camel.impl.engine.DefaultRoutesLoader.findRoutesBuilders(DefaultRoutesLoader.java:165)
    at 
org.apache.camel.impl.engine.DefaultRoutesLoader.updateRoutes(DefaultRoutesLoader.java:295)
    at 
org.apache.camel.support.RouteWatcherReloadStrategy.onRouteReload(RouteWatcherReloadStrategy.java:319)
{noformat}
After the two reloads the reload dev console reports 
{{"reloaded":0,"failed":2}}.

h3. Cause

{{RouteOnDemandReloadStrategy.findReloadedResources}} lists the files that 
exist in the source directory, so a removed file is never passed to 
{{onRouteReload}}. With {{removeAllRoutes}} (the default), 
{{RouteWatcherReloadStrategy.onRouteReload}} then adds the source resource of 
every current route that is not among the passed resources, without checking 
that it still exists, and {{DefaultRoutesLoader.updateRoutes}} fails on the 
removed file. The passed resources already get a {{Files.exists}} check; the 
sources of the current routes do not. After the failure the attempted list is 
kept in {{previousSources}} and added again on the next reload, so the failure 
repeats.

The case where every route file is removed works, because {{removeEverything}} 
clears the list before loading.

Code: [RouteWatcherReloadStrategy, 
4.22.1|https://github.com/apache/camel/blob/camel-4.22.1/core/camel-support/src/main/java/org/apache/camel/support/RouteWatcherReloadStrategy.java#L258-L295].
 The same logic is on main: [RouteWatcherReloadStrategy, 
main|https://github.com/apache/camel/blob/main/core/camel-support/src/main/java/org/apache/camel/support/RouteWatcherReloadStrategy.java#L340-L380].

h3. Proposed change

When collecting the sources of the current routes and the remembered previous 
sources, skip a source whose file no longer exists, with the same 
{{Files.exists}} check the passed resources get. The routes of a removed file 
are then removed like those of a changed file, and the other routes reload.

h3. Classification

Filed as a Bug because the reload fails on an ordinary edit (removing or 
renaming a route file). We were not sure whether it should rather be an 
Improvement, since on-demand reload only scans the files that exist. Please 
reclassify it if Improvement fits better.

We came across this when a project was reloaded on demand after a Git pull that 
had renamed one of its route files.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to