gnodet-bot commented on code in PR #26604:
URL: https://github.com/apache/camel/pull/26604#discussion_r4050229391


##########
dsl/camel-jbang/camel-jbang-core/pom.xml:
##########
@@ -352,73 +369,27 @@
                                     <target>
                                         <property name="examples.base" 
value="https://raw.githubusercontent.com/apache/camel-jbang-examples/main"/>
                                         <property name="examples.dest" 
value="${project.basedir}/src/main/resources/examples"/>
-                                        <!-- Catalog -->
+                                        <!-- the catalog first; the bundled 
examples and their files are read from it -->
                                         <get 
src="${examples.base}/camel-jbang-example-catalog.json"
                                              
dest="${examples.dest}/camel-jbang-example-catalog.json"
                                              usetimestamp="true"/>
-                                        <!-- Bundled examples -->
-                                        <macrodef name="sync-example">
-                                            <attribute name="name"/>
-                                            <attribute name="file"/>
-                                            <sequential>
-                                                <mkdir 
dir="${examples.dest}/@{name}"/>
-                                                <get 
src="${examples.base}/@{name}/@{file}"
-                                                     
dest="${examples.dest}/@{name}/@{file}"
-                                                     usetimestamp="true"/>
-                                            </sequential>
-                                        </macrodef>
-                                        <!-- beginner/camel-1-tribute -->
-                                        <sync-example 
name="beginner/camel-1-tribute" file="README.md"/>
-                                        <sync-example 
name="beginner/camel-1-tribute" file="application.properties"/>
-                                        <sync-example 
name="beginner/camel-1-tribute" file="jms-to-file.camel.yaml"/>
-                                        <!-- beginner/cron-log -->
-                                        <sync-example name="beginner/cron-log" 
file="README.md"/>
-                                        <sync-example name="beginner/cron-log" 
file="application.properties"/>
-                                        <sync-example name="beginner/cron-log" 
file="cron-log.camel.yaml"/>
-                                        <!-- beginner/rest-api -->
-                                        <sync-example name="beginner/rest-api" 
file="README.md"/>
-                                        <sync-example name="beginner/rest-api" 
file="application.properties"/>
-                                        <sync-example name="beginner/rest-api" 
file="rest-api.camel.yaml"/>
-                                        <!-- beginner/routes -->
-                                        <sync-example name="beginner/routes" 
file="Greeter.java"/>
-                                        <sync-example name="beginner/routes" 
file="README.md"/>
-                                        <sync-example name="beginner/routes" 
file="application.properties"/>
-                                        <sync-example name="beginner/routes" 
file="beans.yaml"/>
-                                        <sync-example name="beginner/routes" 
file="routes.camel.yaml"/>
-                                        <!-- beginner/timer-log -->
-                                        <sync-example 
name="beginner/timer-log" file="README.md"/>
-                                        <sync-example 
name="beginner/timer-log" file="application.properties"/>
-                                        <sync-example 
name="beginner/timer-log" file="timer-log.camel.yaml"/>
-                                        <!-- beginner/tui-hello-world -->
-                                        <sync-example 
name="beginner/tui-hello-world" file="README.md"/>
-                                        <sync-example 
name="beginner/tui-hello-world" file="tui-hello-world.yaml"/>
-                                        <!-- database/sql -->
-                                        <sync-example name="database/sql" 
file="README.md"/>
-                                        <sync-example name="database/sql" 
file="application.properties"/>
-                                        <sync-example name="database/sql" 
file="sql.camel.yaml"/>
-                                        <!-- eip/circuit-breaker -->
-                                        <sync-example 
name="eip/circuit-breaker" file="README.md"/>
-                                        <sync-example 
name="eip/circuit-breaker" file="route.camel.yaml"/>
-                                        <!-- language/groovy -->
-                                        <sync-example name="language/groovy" 
file="README.md"/>
-                                        <sync-example name="language/groovy" 
file="application.properties"/>
-                                        <sync-example name="language/groovy" 
file="groovy.camel.yaml"/>
-                                        <!-- observability/memory-leak -->
-                                        <sync-example 
name="observability/memory-leak" file="MemoryLeak.java"/>
-                                        <sync-example 
name="observability/memory-leak" file="README.md"/>
-                                        <!-- observability/message-size -->
-                                        <sync-example 
name="observability/message-size" file="README.md"/>
-                                        <sync-example 
name="observability/message-size" file="orders.camel.yaml"/>
-                                        <!-- observability/route-topology -->
-                                        <sync-example 
name="observability/route-topology" file="README.md"/>
-                                        <sync-example 
name="observability/route-topology" file="application.properties"/>
-                                        <sync-example 
name="observability/route-topology" file="route-topology.camel.yaml"/>
-                                        <!-- transformation/xslt -->
-                                        <sync-example 
name="transformation/xslt" file="README.md"/>
-                                        <sync-example 
name="transformation/xslt" file="consumer.camel.yaml"/>
-                                        <mkdir 
dir="${examples.dest}/transformation/xslt/input"/>
-                                        <sync-example 
name="transformation/xslt" file="input/account.xml"/>
-                                        <sync-example 
name="transformation/xslt" file="stylesheet.xsl"/>
+                                        <taskdef name="groovy" 
classname="org.codehaus.groovy.ant.Groovy" 
classpathref="maven.plugin.classpath"/>
+                                        <groovy><![CDATA[
+                                            import groovy.json.JsonSlurper
+                                            def base = 
properties['examples.base']
+                                            def dest = new 
File(properties['examples.dest'])
+                                            def catalog = new 
JsonSlurper().parse(new File(dest, 'camel-jbang-example-catalog.json'))
+                                            // start from a clean tree so 
examples that left the catalog, or moved, do not linger
+                                            dest.listFiles().findAll { 
it.directory }.each { it.deleteDir() }

Review Comment:
   ⚠️ **NullPointerException risk:** `File.listFiles()` returns `null` when 
`dest` does not exist or is not a directory — for example if the preceding 
`<get>` for the catalog JSON failed and left `dest` uncreated. Calling 
`.findAll { ... }` on `null` throws NPE and aborts the build with a confusing 
stack trace instead of a clear error.
   
   ```suggestion
                                               def files = dest.listFiles()
                                               if (files == null) {
                                                   throw new 
RuntimeException("Cannot list '${dest}' — does it exist and is it a directory?")
                                               }
                                               files.findAll { it.directory 
}.each { it.deleteDir() }
   ```



##########
dsl/camel-jbang/camel-jbang-core/pom.xml:
##########
@@ -352,73 +369,27 @@
                                     <target>
                                         <property name="examples.base" 
value="https://raw.githubusercontent.com/apache/camel-jbang-examples/main"/>
                                         <property name="examples.dest" 
value="${project.basedir}/src/main/resources/examples"/>
-                                        <!-- Catalog -->
+                                        <!-- the catalog first; the bundled 
examples and their files are read from it -->
                                         <get 
src="${examples.base}/camel-jbang-example-catalog.json"
                                              
dest="${examples.dest}/camel-jbang-example-catalog.json"
                                              usetimestamp="true"/>
-                                        <!-- Bundled examples -->
-                                        <macrodef name="sync-example">
-                                            <attribute name="name"/>
-                                            <attribute name="file"/>
-                                            <sequential>
-                                                <mkdir 
dir="${examples.dest}/@{name}"/>
-                                                <get 
src="${examples.base}/@{name}/@{file}"
-                                                     
dest="${examples.dest}/@{name}/@{file}"
-                                                     usetimestamp="true"/>
-                                            </sequential>
-                                        </macrodef>
-                                        <!-- beginner/camel-1-tribute -->
-                                        <sync-example 
name="beginner/camel-1-tribute" file="README.md"/>
-                                        <sync-example 
name="beginner/camel-1-tribute" file="application.properties"/>
-                                        <sync-example 
name="beginner/camel-1-tribute" file="jms-to-file.camel.yaml"/>
-                                        <!-- beginner/cron-log -->
-                                        <sync-example name="beginner/cron-log" 
file="README.md"/>
-                                        <sync-example name="beginner/cron-log" 
file="application.properties"/>
-                                        <sync-example name="beginner/cron-log" 
file="cron-log.camel.yaml"/>
-                                        <!-- beginner/rest-api -->
-                                        <sync-example name="beginner/rest-api" 
file="README.md"/>
-                                        <sync-example name="beginner/rest-api" 
file="application.properties"/>
-                                        <sync-example name="beginner/rest-api" 
file="rest-api.camel.yaml"/>
-                                        <!-- beginner/routes -->
-                                        <sync-example name="beginner/routes" 
file="Greeter.java"/>
-                                        <sync-example name="beginner/routes" 
file="README.md"/>
-                                        <sync-example name="beginner/routes" 
file="application.properties"/>
-                                        <sync-example name="beginner/routes" 
file="beans.yaml"/>
-                                        <sync-example name="beginner/routes" 
file="routes.camel.yaml"/>
-                                        <!-- beginner/timer-log -->
-                                        <sync-example 
name="beginner/timer-log" file="README.md"/>
-                                        <sync-example 
name="beginner/timer-log" file="application.properties"/>
-                                        <sync-example 
name="beginner/timer-log" file="timer-log.camel.yaml"/>
-                                        <!-- beginner/tui-hello-world -->
-                                        <sync-example 
name="beginner/tui-hello-world" file="README.md"/>
-                                        <sync-example 
name="beginner/tui-hello-world" file="tui-hello-world.yaml"/>
-                                        <!-- database/sql -->
-                                        <sync-example name="database/sql" 
file="README.md"/>
-                                        <sync-example name="database/sql" 
file="application.properties"/>
-                                        <sync-example name="database/sql" 
file="sql.camel.yaml"/>
-                                        <!-- eip/circuit-breaker -->
-                                        <sync-example 
name="eip/circuit-breaker" file="README.md"/>
-                                        <sync-example 
name="eip/circuit-breaker" file="route.camel.yaml"/>
-                                        <!-- language/groovy -->
-                                        <sync-example name="language/groovy" 
file="README.md"/>
-                                        <sync-example name="language/groovy" 
file="application.properties"/>
-                                        <sync-example name="language/groovy" 
file="groovy.camel.yaml"/>
-                                        <!-- observability/memory-leak -->
-                                        <sync-example 
name="observability/memory-leak" file="MemoryLeak.java"/>
-                                        <sync-example 
name="observability/memory-leak" file="README.md"/>
-                                        <!-- observability/message-size -->
-                                        <sync-example 
name="observability/message-size" file="README.md"/>
-                                        <sync-example 
name="observability/message-size" file="orders.camel.yaml"/>
-                                        <!-- observability/route-topology -->
-                                        <sync-example 
name="observability/route-topology" file="README.md"/>
-                                        <sync-example 
name="observability/route-topology" file="application.properties"/>
-                                        <sync-example 
name="observability/route-topology" file="route-topology.camel.yaml"/>
-                                        <!-- transformation/xslt -->
-                                        <sync-example 
name="transformation/xslt" file="README.md"/>
-                                        <sync-example 
name="transformation/xslt" file="consumer.camel.yaml"/>
-                                        <mkdir 
dir="${examples.dest}/transformation/xslt/input"/>
-                                        <sync-example 
name="transformation/xslt" file="input/account.xml"/>
-                                        <sync-example 
name="transformation/xslt" file="stylesheet.xsl"/>
+                                        <taskdef name="groovy" 
classname="org.codehaus.groovy.ant.Groovy" 
classpathref="maven.plugin.classpath"/>
+                                        <groovy><![CDATA[
+                                            import groovy.json.JsonSlurper
+                                            def base = 
properties['examples.base']
+                                            def dest = new 
File(properties['examples.dest'])
+                                            def catalog = new 
JsonSlurper().parse(new File(dest, 'camel-jbang-example-catalog.json'))
+                                            // start from a clean tree so 
examples that left the catalog, or moved, do not linger
+                                            dest.listFiles().findAll { 
it.directory }.each { it.deleteDir() }
+                                            catalog.findAll { it.bundled 
}.each { ex ->
+                                                ex.files.each { f ->
+                                                    def target = new 
File(dest, ex.name + '/' + f)
+                                                    target.parentFile.mkdirs()
+                                                    new 
URL("${base}/${ex.name}/${f}").withInputStream { i -> target.withOutputStream { 
o -> o << i } }

Review Comment:
   💡 **Silent failure on 404:** if any file URL returns a non-200 (example 
moved, renamed, or the catalog lists a file that does not exist yet), 
`withInputStream` throws `java.io.FileNotFoundException`. The build fails, but 
the error message only shows the URL — not which example or file was being 
fetched. Wrapping with a try/catch and rethrowing with context makes failures 
actionable:
   
   ```suggestion
                                                       try {
                                                           new 
URL("${base}/${ex.name}/${f}").withInputStream { i -> target.withOutputStream { 
o -> o << i } }
                                                       } catch (Exception e) {
                                                           throw new 
RuntimeException("Failed to fetch ${ex.name}/${f}: ${e.message}", e)
                                                       }
                                                       println "synced 
${ex.name}/${f}"
   ```



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to