Skip to content

Commit c64d6a6

Browse files
committed
MVC Code generation fails to declare exception when constructor throws a checked exception
- fix #3737
1 parent 859dc3b commit c64d6a6

File tree

6 files changed

+198
-27
lines changed

6 files changed

+198
-27
lines changed

jooby/src/main/java/io/jooby/SneakyThrows.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -899,6 +899,28 @@ public static <V> Supplier<V> throwingSupplier(Supplier<V> fn) {
899899
return fn;
900900
}
901901

902+
/**
903+
* Singleton supplier from existing instance.
904+
*
905+
* @param instance Singleton.
906+
* @return Single supplier.
907+
* @param <V> Resulting value.
908+
*/
909+
public static <V> Supplier<V> singleton(V instance) {
910+
return () -> instance;
911+
}
912+
913+
/**
914+
* Singleton supplier from another supplier.
915+
*
916+
* @param fn Supplier.
917+
* @return Single supplier.
918+
* @param <V> Resulting value.
919+
*/
920+
public static <V> Supplier<V> singleton(Supplier<V> fn) {
921+
return singleton(fn.get());
922+
}
923+
902924
/**
903925
* Factory method for {@link Function} and {@link java.util.function.Function}.
904926
*

modules/jooby-apt/src/main/java/io/jooby/internal/apt/MvcRouter.java

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -226,13 +226,22 @@ private StringBuilder constructors(String generatedName, boolean kt) {
226226
buffer,
227227
List.of(),
228228
(output, params) -> {
229-
output
230-
.append("this(")
231-
.append(kt ? "" : "new ")
232-
.append(targetType)
233-
.append("())")
234-
.append(semicolon(kt))
235-
.append(System.lineSeparator());
229+
if (kt) {
230+
output
231+
.append("this(")
232+
.append(targetType)
233+
.append("())")
234+
.append(semicolon(true))
235+
.append(System.lineSeparator());
236+
} else {
237+
output
238+
.append("this(")
239+
.append("io.jooby.SneakyThrows.singleton(")
240+
.append(targetType)
241+
.append("::new))")
242+
.append(semicolon(false))
243+
.append(System.lineSeparator());
244+
}
236245
});
237246
}
238247
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/*
2+
* Jooby https://jooby.io
3+
* Apache License Version 2.0 https://jooby.io/LICENSE.txt
4+
* Copyright 2014 Edgar Espina
5+
*/
6+
package tests.i3737;
7+
8+
import io.jooby.annotation.GET;
9+
import io.jooby.annotation.Path;
10+
11+
@Path("/3737")
12+
public class C3737 {
13+
14+
public C3737() throws Exception {}
15+
16+
@GET("/hello")
17+
public String hello() {
18+
return "hello world";
19+
}
20+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
* Jooby https://jooby.io
3+
* Apache License Version 2.0 https://jooby.io/LICENSE.txt
4+
* Copyright 2014 Edgar Espina
5+
*/
6+
package tests.i3737;
7+
8+
import static org.junit.jupiter.api.Assertions.*;
9+
10+
import org.junit.jupiter.api.Test;
11+
12+
import io.jooby.apt.ProcessorRunner;
13+
14+
public class Issue3737 {
15+
@Test
16+
public void shouldNotFail() throws Exception {
17+
// must compile
18+
new ProcessorRunner(new C3737())
19+
.withRouter(
20+
(app, source) -> {
21+
var routes = app.getRoutes();
22+
assertNotNull(routes);
23+
assertFalse(routes.isEmpty());
24+
var route = app.getRoutes().get(0);
25+
assertNotNull(route);
26+
});
27+
}
28+
}

modules/jooby-graphiql/pom.xml

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -35,26 +35,26 @@
3535

3636
<build>
3737
<plugins>
38-
<plugin>
39-
<groupId>org.apache.maven.plugins</groupId>
40-
<artifactId>maven-antrun-plugin</artifactId>
41-
<version>${maven-antrun-plugin.version}</version>
42-
<executions>
43-
<execution>
44-
<goals>
45-
<goal>run</goal>
46-
</goals>
47-
<phase>generate-resources</phase>
48-
<configuration>
49-
<target>
50-
<property name="output" value="${project.build.outputDirectory}${file.separator}io${file.separator}jooby${file.separator}graphiql"/>
51-
<mkdir dir="${output}" />
52-
<get quiet="true" usetimestamp="true" src="https://raw.githubusercontent.com/graphql/graphiql/refs/heads/main/examples/graphiql-cdn/index.html" dest="${output}${file.separator}index.html"/>
53-
</target>
54-
</configuration>
55-
</execution>
56-
</executions>
57-
</plugin>
38+
<!-- <plugin>-->
39+
<!-- <groupId>org.apache.maven.plugins</groupId>-->
40+
<!-- <artifactId>maven-antrun-plugin</artifactId>-->
41+
<!-- <version>${maven-antrun-plugin.version}</version>-->
42+
<!-- <executions>-->
43+
<!-- <execution>-->
44+
<!-- <goals>-->
45+
<!-- <goal>run</goal>-->
46+
<!-- </goals>-->
47+
<!-- <phase>generate-resources</phase>-->
48+
<!-- <configuration>-->
49+
<!-- <target>-->
50+
<!-- <property name="output" value="${project.build.outputDirectory}${file.separator}io${file.separator}jooby${file.separator}graphiql"/>-->
51+
<!-- <mkdir dir="${output}" />-->
52+
<!-- <get quiet="true" usetimestamp="true" src="https://raw.githubusercontent.com/graphql/graphiql/refs/heads/main/examples/graphiql-cdn/index.html" dest="${output}${file.separator}index.html"/>-->
53+
<!-- </target>-->
54+
<!-- </configuration>-->
55+
<!-- </execution>-->
56+
<!-- </executions>-->
57+
<!-- </plugin>-->
5858
</plugins>
5959
</build>
6060
</project>
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
<!--
2+
* Copyright (c) 2025 GraphQL Contributors
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the license found in the
6+
* LICENSE file in the root directory of this source tree.
7+
-->
8+
<!doctype html>
9+
<html lang="en">
10+
<head>
11+
<meta charset="UTF-8" />
12+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
13+
<title>GraphiQL 5 with React 19 and GraphiQL Explorer</title>
14+
<style>
15+
body {
16+
margin: 0;
17+
}
18+
19+
#graphiql {
20+
height: 100dvh;
21+
}
22+
23+
.loading {
24+
height: 100%;
25+
display: flex;
26+
align-items: center;
27+
justify-content: center;
28+
font-size: 4rem;
29+
}
30+
</style>
31+
<link rel="stylesheet" href="https://esm.sh/graphiql/dist/style.css" />
32+
<link
33+
rel="stylesheet"
34+
href="https://esm.sh/@graphiql/plugin-explorer/dist/style.css"
35+
/>
36+
<!--
37+
* Note:
38+
* The ?standalone flag bundles the module along with all of its `dependencies`, excluding `peerDependencies`, into a single JavaScript file.
39+
* `@emotion/is-prop-valid` is a shim to remove the console error ` module "@emotion /is-prop-valid" not found`. Upstream issue: https://github.com/motiondivision/motion/issues/3126
40+
-->
41+
<script type="importmap">
42+
{
43+
"imports": {
44+
"react": "https://esm.sh/[email protected]",
45+
"react/": "https://esm.sh/[email protected]/",
46+
47+
"react-dom": "https://esm.sh/[email protected]",
48+
"react-dom/": "https://esm.sh/[email protected]/",
49+
50+
"graphiql": "https://esm.sh/graphiql?standalone&external=react,react-dom,@graphiql/react,graphql",
51+
"graphiql/": "https://esm.sh/graphiql/",
52+
"@graphiql/plugin-explorer": "https://esm.sh/@graphiql/plugin-explorer?standalone&external=react,@graphiql/react,graphql",
53+
"@graphiql/react": "https://esm.sh/@graphiql/react?standalone&external=react,react-dom,graphql,@graphiql/toolkit,@emotion/is-prop-valid",
54+
55+
"@graphiql/toolkit": "https://esm.sh/@graphiql/toolkit?standalone&external=graphql",
56+
"graphql": "https://esm.sh/[email protected]",
57+
"@emotion/is-prop-valid": "data:text/javascript,"
58+
}
59+
}
60+
</script>
61+
<script type="module">
62+
import React from 'react';
63+
import ReactDOM from 'react-dom/client';
64+
import { GraphiQL, HISTORY_PLUGIN } from 'graphiql';
65+
import { createGraphiQLFetcher } from '@graphiql/toolkit';
66+
import { explorerPlugin } from '@graphiql/plugin-explorer';
67+
import 'graphiql/setup-workers/esm.sh';
68+
69+
const fetcher = createGraphiQLFetcher({
70+
url: 'https://countries.trevorblades.com',
71+
});
72+
const plugins = [HISTORY_PLUGIN, explorerPlugin()];
73+
74+
function App() {
75+
return React.createElement(GraphiQL, {
76+
fetcher,
77+
plugins,
78+
defaultEditorToolsVisibility: true,
79+
});
80+
}
81+
82+
const container = document.getElementById('graphiql');
83+
const root = ReactDOM.createRoot(container);
84+
root.render(React.createElement(App));
85+
</script>
86+
</head>
87+
<body>
88+
<div id="graphiql">
89+
<div class="loading">Loading…</div>
90+
</div>
91+
</body>
92+
</html>

0 commit comments

Comments
 (0)