I have an application which offers a frontend but should also allow API calls (modifying the application). Therefore I have an Index class which redirects to the frontend when the context is not similar to an API call url and otherwise doesn't redirect. However, the api call doesn't reach the Jersey API handler but simply displays the default layout.
In my Index
class I have:
Object onActivate(EventContext context) {
if (context.getCount() < 2)
return WorkspaceOverview.class;
String first = context.get(String.class, 0);
String second = context.get(String.class, 1);
return "api".equalsIgnoreCase(first) &&
Arrays.stream(allowedApiCalls).anyMatch(s -> s.equalsIgnoreCase(second))
? null
: WorkspaceOverview.class;
}
In the API class I have (with different namings but generally the same):
@Path("/api")
@Api(description = "description")
@Generated(value = "io.swagger.codegen.languages.JavaJerseyServerCodegen", date = "2018-10-29T15:10:52.958Z")
public class Api {
private ApiService getDelegate() {
return (ApiService) Bootstrap.getRegistry().getService(ApiService.class);
}
@PUT
@Path("/request")
@ApiOperation(value = "handles", notes = "notes", response = Void.class, authorizations = {
@Authorization(value = "basicAuth") }, tags = {})
@ApiResponses(value = {
@ApiResponse(code = 200, message = "The request update was successful", response = Void.class),
@ApiResponse(code = 400, message = "An unknown error occurred", response = Void.class),
@ApiResponse(code = 401, message = "Authentication information is missing or invalid", response = Void.class),
@ApiResponse(code = 404, message = "The request doesn't exist", response = Void.class) })
public Response request(
@ApiParam(value = "The of the request", required = true) @QueryParam("id") Long id,
@ApiParam(value = "value", required = true, allowableValues = "A, B, C") @QueryParam("value") String value,
@Context SecurityContext securityContext, @Context HttpHeaders headers, @Context HttpServletRequest request) throws NotFoundException {
String authorizationHeader = headers.getHeaderString("Authorization");
String requestHost = headers.getHeaderString("Host");
String remoteHost = request.getRemoteHost();
return getDelegate().handleRequest(id, value, securityContext, authorizationHeader, requestHost, remoteHost);
}
}
And in my pom
(drastically shortened):
<project
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0">
<artifactId>Project</artifactId>
<packaging>war</packaging>
<name>Project</name>
<dependency>
<groupId>org.apache.tapestry</groupId>
<artifactId>tapestry-core</artifactId>
</dependency>
<dependency>
<groupId>org.apache.tapestry</groupId>
<artifactId>tapestry-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.tapestry</groupId>
<artifactId>tapestry-javadoc</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.json</artifactId>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-jersey2-jaxrs</artifactId>
<scope>compile</scope>
<version>${swagger-core-version}</version>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
<version>${swagger-core-version}</version>
</dependency>
<dependency>
<groupId>com.squareup.okhttp</groupId>
<artifactId>okhttp</artifactId>
<version>${okhttp-version}</version>
</dependency>
<dependency>
<groupId>com.squareup.okhttp</groupId>
<artifactId>logging-interceptor</artifactId>
<version>${okhttp-version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet-core</artifactId>
<version>${jersey2-version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-multipart</artifactId>
<version>${jersey2-version}</version>
</dependency>
<dependency>
<groupId>de.mkammerer</groupId>
<artifactId>argon2-jvm</artifactId>
</dependency>
<dependency>
<groupId>org.apache.tapestry</groupId>
<artifactId>tapestry-upload</artifactId>
<version>${tapestry-release-version}</version>
</dependency>
<dependency>
<groupId>org.apache.tapestry</groupId>
<artifactId>tapestry-csrf-protection</artifactId>
<version>${tapestry-csrf.version}</version>
</dependency>
<dependency>
<groupId>org.apache.tapestry</groupId>
<artifactId>tapestry-kaptcha</artifactId>
<version>${tapestry-release-version}</version>
</dependency>
</dependencies>
<build>
<finalName>Project</finalName>
<properties>
<jetty-maven-version>9.2.21.v20170120</jetty-maven-version>
<tapestry-release-version>5.4.3</tapestry-release-version>
<servlet-api-release-version>2.5</servlet-api-release-version>
<testng-release-version>5.14.10</testng-release-version>
<tapestry-security-version>0.6.6</tapestry-security-version>
<swagger-core-version>1.5.15</swagger-core-version>
<okhttp-version>2.7.5</okhttp-version>
<gson-version>2.8.1</gson-version>
<jersey2-version>2.22.2</jersey2-version>
<maven.compiler.target>1.7</maven.compiler.target>
<maven.compiler.source>1.7</maven.compiler.source>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<tapestry-csrf.version>1.2.0.RELEASE</tapestry-csrf.version>
</properties>
</project>
And the web.xml
:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<context-param>
<!-- The only significant configuration for Tapestry 5, this informs Tapestry of where to look for pages, components and mixins. -->
<param-name>tapestry.app-package</param-name>
<param-value>the.package.to.the.application</param-value>
</context-param>
<context-param>
<param-name>tapestry.secure-enabled</param-name>
<param-value>false</param-value>
</context-param>
<filter>
<filter-name>ServletFilter</filter-name>
<filter-class>the.package.of.the.filter.Filter</filter-class>
</filter>
<filter-mapping>
<filter-name>ServletFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>app</filter-name>
<filter-class>org.apache.tapestry5.TapestryFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>app</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>
the.package.of.the.listener.Listener
</listener-class>
</listener>
<session-config>
<tracking-mode>COOKIE</tracking-mode>
<session-timeout>-1</session-timeout>
</session-config>
<!--API-->
<servlet>
<servlet-name>jersey</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>
io.swagger.jaxrs.listing,
io.swagger.sample.resource,
the.package.to.the.api
</param-value>
</init-param>
<init-param>
<param-name>jersey.config.server.provider.classnames</param-name>
<param-value>org.glassfish.jersey.media.multipart.MultiPartFeature</param-value>
</init-param>
<init-param>
<param-name>jersey.config.server.wadl.disableWadl</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<servlet-name>Jersey2Config</servlet-name>
<servlet-class>io.swagger.jersey.config.JerseyJaxrsConfig</servlet-class>
<init-param>
<param-name>api.version</param-name>
<param-value>1.0.0</param-value>
</init-param>
<init-param>
<param-name>swagger.api.title</param-name>
<param-value>Swagger Server</param-value>
</init-param>
<init-param>
<param-name>swagger.api.basepath</param-name>
<param-value>https://localhost</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet>
<servlet-name>Bootstrap</servlet-name>
<servlet-class>the.package.to.the.bootstrap.Bootstrap</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Bootstrap</servlet-name>
<url-pattern>the.package.to.the.api.*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>jersey</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<filter>
<filter-name>ApiOriginFilter</filter-name>
<filter-class>the.package.of.the.filter.Filter
</filter-class>
</filter>
<filter-mapping>
<filter-name>ApiOriginFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
An example request would be:
curl -X PUT "localhost:8080/api/request?id=0&vaue=A" -H "accept: application/json" -H "authorization: Basic dXNlcjoxMjM0d" -k -v
But the result is always 200
with the html code of the DefaultLayout
page.
If there's some minor mistake in the source code which would cause a comipilation error let me know, I had to modify the code not to reveal any secrets.
I think that's all relevant files, if you need more information, let me know in the comments. I'm sorry for not being able to provide a minimal, working example, but I simply don't know which files / parts of code are relevant.