Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@
- `servers` is now trimmed like the other list keys: `servers=dev, prod` works instead of failing startup with a `NullPointerException`.
- PostGIS source: the keys `collections.<id>.id.alias`, `geometry.alias` and `properties.<p>.alias` are removed. They were a not-working and unfinished idea (`properties.<p>.alias` made startup fail with a `NullPointerException`); they are now ignored.

### Library updates

- `swagger-core` is kept only for its Jackson mixins; all of its transitive dependencies are excluded in `hakunapi-simple-servlet-jakarta`. Jackson 2 (`jackson-databind`, `jackson-core`, `jackson-dataformat-yaml`, `jackson-datatype-jsr310`), `snakeyaml`, `swagger-annotations`, `jakarta.xml.bind-api` 2.x and `jakarta.activation-api` 1.x are no longer in the reference webapp WAR (8 jars, ~3 MB). Applications that relied on Jackson 2 arriving transitively must declare it themselves.

## 2.0.0

For a full list of changes see: https://github.com/nlsfi/hakunapi/milestone/17
Expand Down
2 changes: 1 addition & 1 deletion docs/overview/modules.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ The table below lists all direct third-party dependencies declared in the Hakuna
| Jakarta EE APIs | servlet 6.0.0, ws.rs 3.1.0, validation 3.0.2 | Servlet API, JAX-RS API | **To consider:** Currently too much logic is implemented against JAX-RS APIs. Additional layer would allow for migration to another Web API layer ("Control" and "Service" layers are now somewhat intermingled) |
| Jersey | 3.1.11 | JAX-RS implementation: servlet container integration + HK2 dependency injection | |
| Jackson | 3.1.6 (annotations 2.21) | JSON streaming, object mapping and JAX-RS integration for Jersey. Jackson 3.1.x reuses the 2.21 annotation artifact. | |
| Swagger Core | 2.2.42 | OpenAPI 3 model classes and serialization for API description generation | |
| Swagger Core | 2.2.42 | OpenAPI 3 model classes (`swagger-models`, core) and the Jackson mixins that serialize them (`swagger-core`, servlet) | `swagger-core` is declared with all transitive dependencies excluded: only its mixins are used, and they need nothing beyond `jackson-annotations` and `swagger-models`. This keeps Jackson 2 out of the WAR. |

#### Spatial geometry and CRS

Expand Down
7 changes: 7 additions & 0 deletions webapp-jakarta/hakunapi-simple-servlet-jakarta/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,13 @@
<dependency>
<groupId>io.swagger.core.v3</groupId>
<artifactId>swagger-core</artifactId>
<!-- Only the Jackson mixins are used; they need just jackson-annotations and swagger-models -->
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package fi.nls.hakunapi.simple.webapp.jakarta.features;

import static org.junit.Assert.assertEquals;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;

import jakarta.servlet.ServletContextEvent;
import jakarta.ws.rs.client.WebTarget;
import jakarta.ws.rs.core.Application;
import jakarta.ws.rs.core.Response;

import org.glassfish.jersey.test.JerseyTest;
import org.glassfish.jersey.test.TestProperties;
import org.junit.Test;

import fi.nls.hakunapi.simple.webapp.jakarta.HakunaContextListener;
import fi.nls.hakunapi.simple.webapp.jakarta.HakunaTestServletContext;
import fi.nls.hakunapi.simple.webapp.jakarta.SimpleFeaturesApplication;

/**
* Byte-exact output of the generated documents for the hakuna_i18n config: the
* OpenAPI document, and the schema and queryables of building_part_area in its
* base language and in fi.
*
* These go through the OpenAPI mixins and the SchemaDefinition path of
* OpenAPIMessageBodyWriter, so a change to the serialization stack shows up here
* as a diff rather than as a silently different document.
*/
public class GoldenDocumentTest extends JerseyTest {

private static final String OPENAPI = "application/vnd.oai.openapi+json;version=3.0";
private static final String SCHEMA = "application/schema+json";

@Override
protected Application configure() {
enable(TestProperties.LOG_TRAFFIC);

ClassLoader classLoader = getClass().getClassLoader();
File file = new File(classLoader.getResource("hakuna_i18n/hakuna.properties").getFile());

System.setProperty("hakuna.config.path", file.getParentFile().getAbsolutePath() + "/");

final HakunaTestServletContext sc = new HakunaTestServletContext();
final ServletContextEvent sce = new ServletContextEvent(sc);
new HakunaContextListener().contextInitialized(sce);

return new SimpleFeaturesApplication(sc);
}

@Test
public void testOpenApiDocument() throws Exception {
assertEquals(golden("api.json"), fetch("/api", OPENAPI, null));
}

@Test
public void testCollectionSchema() throws Exception {
assertEquals(golden("schema.json"), fetch("/collections/building_part_area/schema", SCHEMA, null));
assertEquals(golden("schema-fi.json"), fetch("/collections/building_part_area/schema", SCHEMA, "fi"));
}

@Test
public void testCollectionQueryables() throws Exception {
assertEquals(golden("queryables.json"), fetch("/collections/building_part_area/queryables", SCHEMA, null));
assertEquals(golden("queryables-fi.json"), fetch("/collections/building_part_area/queryables", SCHEMA, "fi"));
}

private String fetch(String path, String accept, String lang) {
WebTarget target = target(path);
if (lang != null) {
target = target.queryParam("lang", lang);
}
Response r = target.request(accept).get();
String body = r.readEntity(String.class);
assertEquals(200, r.getStatus());
return body;
}

private static String golden(String name) throws IOException {
try (InputStream in = GoldenDocumentTest.class.getResourceAsStream("/golden/" + name)) {
return new String(in.readAllBytes(), StandardCharsets.UTF_8);
}
}

}
Loading
Loading