I want to load and process json schema files from within two different deployments, the first being a WAR with JAX-RS endpoint and the second an EAR with Singleton-EJB + a resources JAR containing the schema files (I've read that packaging resources files for use in EJBs is only possible when bundling them in a separate JAR inside the EAR).
Development environment is eclipse 2019-03 with JBoss Wildfly 16.
WAR deployment with JAX-RS endpoint
The WAR part is fine, I have an @ApplicationScoped Bean and can access the schema files located in src/main/webapp/schemas/ via ServletContext, see the following code snippet:
@ForWarDeployment
@ApplicationScoped
public class JsonSchemaValidatorWar extends JsonSchemaValidatorBase {
...
@PostConstruct
public void init() {
Consumer<Path> readSchema = schemaFile -> {
String schemaName = schemaFile.getName(schemaFile.getNameCount() - 1).toString();
JsonSchema js = jvs.readSchema(schemaFile);
map.put(schemaName, js); // this is a concurrent hash map in base class
log.info("Schema " + schemaName + " added: " + js.toJson());
};
URI schemaFolder;
try {
schemaFolder = servletContext.getResource("/schemas").toURI();
try (Stream<Path> paths = Files.walk(Paths.get(schemaFolder))) {
paths.filter(Files::isRegularFile).forEach(readSchema);
}
} catch (URISyntaxException | IOException e) {
throw new RuntimeException("Error loading schema files!", e);
}
}
Output on first request:
... (default task-1) Schema person.schema.json added: {"$id": ...
EAR deployment with EJB and resources JAR
The EJB part is tricky, I haven't found a solution for reading all schema files yet.
What I currently have is a multi-module maven project with the following structure:
- parent
- | ear
- | ejb3
- | resources
pom.xml for parent project
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>mdv</groupId>
<artifactId>json-parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>json-ejb3</module>
<module>json-ear</module>
<module>json-resources</module>
</modules>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
</project>
pom.xml for ear project
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>mdv</groupId>
<artifactId>json-parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>json-ear</artifactId>
<packaging>ear</packaging>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>mdv</groupId>
<artifactId>json-ejb3</artifactId>
<version>${project.version}</version>
<type>ejb</type>
</dependency>
<dependency>
<groupId>mdv</groupId>
<artifactId>json-resources</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-ear-plugin</artifactId>
<version>3.0.1</version>
<configuration>
<version>7</version>
<defaultLibBundleDir>lib</defaultLibBundleDir>
<earSourceDirectory>${basedir}/src/main/resources</earSourceDirectory>
<outputFileNameMapping>@{artifactId}@@{dashClassifier?}@.@{extension}@</outputFileNameMapping>
</configuration>
</plugin>
</plugins>
</build>
</project>
pom.xml for resources project
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>mdv</groupId>
<artifactId>json-parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>json-resources</artifactId>
</project>
pom.xml for ejb3 project
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>mdv</groupId>
<artifactId>json-parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>json-ejb3</artifactId>
<packaging>ejb</packaging>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<artifactId>maven-ejb-plugin</artifactId>
<version>3.0.1</version>
<configuration>
<ejbVersion>3.2</ejbVersion>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<!-- contains a json schema processing library and the class JsonSchemaValidatorEjb -->
<groupId>mdv</groupId>
<artifactId>json</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
The problem with loading schema files in EJB
I want to load the schema files in an @ApplicationScoped bean for use in a Singleton EJB, the corresponding class is JsonSchemaValidatorService:
package mdv;
import java.util.logging.Logger;
import javax.annotation.PostConstruct;
import javax.ejb.Singleton;
import javax.ejb.Startup;
import javax.inject.Inject;
import json.ForEjbDeployment;
import json.IJsonSchemaValidator;
@Singleton
@Startup
public class JsonSchemaValidatorService {
Logger log = Logger.getLogger("JsonSchemaValidatorService");
@Inject
@ForEjbDeployment
IJsonSchemaValidator jsonSchemaValidator;
// this is where json schema files should be loaded
public JsonSchemaValidatorService() {
//
}
@PostConstruct
public void init() {
log.info("Started JsonSchemaValidatorService.");
log.info("Loaded schemas in jsonSchemaValidator: " + jsonSchemaValidator.getLoadedSchemas());
}
}
The class for loading json schema files in EJB environment is this bean:
package json;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URISyntaxException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.util.function.Consumer;
import java.util.logging.Logger;
import javax.annotation.PostConstruct;
import javax.enterprise.context.ApplicationScoped;
import javax.resource.spi.IllegalStateException;
import org.leadpony.justify.api.JsonSchema;
@ForEjbDeployment
@ApplicationScoped
public class JsonSchemaValidatorEjb extends JsonSchemaValidatorBase {
Logger log = Logger.getLogger("JsonSchemaValidator");
public JsonSchemaValidatorEjb() {
//
}
@PostConstruct
public void init() {
try {
// This is where I can't manage to get a list of the json schema files and process them
final ClassLoader loader = Thread.currentThread().getContextClassLoader();
try(
final InputStream is = loader.getResourceAsStream("schemas");
final InputStreamReader isr = new InputStreamReader(is, StandardCharsets.UTF_8);
final BufferedReader br = new BufferedReader(isr)) {
log.info("schema files in directory: ");
br.lines().forEach(x -> log.info(x));
}
} catch (Exception e) {
throw new RuntimeException("Error trying to parse schema files!", e);
}
}
}
No Exception is thrown but also no files will be found in the directory provided, e.g. "schemas". The shortened output after EJB started is:
[JsonSchemaValidatorService] Started JsonSchemaValidatorService.
[JsonSchemaValidator] schema files in directory:
[JsonSchemaValidatorService] Loaded schemas in jsonSchemaValidator: {}
The file structure of the deployed ear is this:
- lib
| - icu4j.jar
| - javax.json-api.jar
| - javax.json.jar
| - json-resources.jar // jar with resources, in this case the schemas
| | - schemas
| | | - person.schema.json
| - json.jar // jar containing @ApplicationScoped beans for war und ejb
| - justify.jar // json schema processing library used
- META-INF
| - maven
| | ...
| - schemas
| | - person.schema.json
| - application.xml
| - MANIFEST.MF
- schemas
| -person.schema.json
- json-ejb3.jar
As you can see I have managed to bundle the schemas folder and the single json schema file in multiple locations, but none of this works.
Is this even possible to achieve?
Am I wrong with the path specified at getResourceAsStream("schemas")?
The goal is to load all existing json schema files at startup to parse them to JsonSchema objects once to validate them later on (it will be a message-driven bean, by the way).