Merge pull request #5562 from psychsane/master
[BAEL-1995] Add new module for restx-demo
This commit is contained in:
commit
4fe2f0866f
1
pom.xml
1
pom.xml
|
@ -1714,6 +1714,7 @@
|
||||||
<module>persistence-modules/spring-data-elasticsearch</module>
|
<module>persistence-modules/spring-data-elasticsearch</module>
|
||||||
<module>core-java-concurrency</module>
|
<module>core-java-concurrency</module>
|
||||||
<module>core-java-concurrency-collections</module>
|
<module>core-java-concurrency-collections</module>
|
||||||
|
<module>restx</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
</profile>
|
</profile>
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"//": "lines with // keys are just comments (we don't have real comments in json)",
|
||||||
|
"//": "this file stores password passed through md5+bcrypt hash",
|
||||||
|
"//": "you can use `restx hash md5+bcrypt {password}` shell command to get hashed passwords to put here",
|
||||||
|
|
||||||
|
"//": "to help startup with restx, there are comments with clear text passwords,",
|
||||||
|
"//": "which should obviously not be stored here.",
|
||||||
|
"user1": "$2a$10$iZluFUJShbjb1ue68bLrDuGCeJL9EMLHelVIf8u0SUbCseDOvKnoe",
|
||||||
|
"//": "user 1 password is 'user1-pwd'",
|
||||||
|
"user2": "$2a$10$oym3SYMFXf/9gGfDKKHO4eM1vWNqAZMsRZCL.BORCaP4yp5cdiCXu",
|
||||||
|
"//": "user 2 password is 'user2-pwd'"
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
[
|
||||||
|
{"name":"user1", "roles": ["hello"]},
|
||||||
|
{"name":"user2", "roles": []}
|
||||||
|
]
|
|
@ -0,0 +1,38 @@
|
||||||
|
{
|
||||||
|
"module": "restx-demo:restx-demo:0.1-SNAPSHOT",
|
||||||
|
"packaging": "war",
|
||||||
|
|
||||||
|
"properties": {
|
||||||
|
"java.version": "1.8",
|
||||||
|
"restx.version": "0.35-rc4"
|
||||||
|
},
|
||||||
|
"fragments": {
|
||||||
|
"maven": [
|
||||||
|
"classpath:///restx/build/fragments/maven/javadoc-apidoclet.xml" ]
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"compile": [
|
||||||
|
"io.restx:restx-core:${restx.version}",
|
||||||
|
"io.restx:restx-security-basic:${restx.version}",
|
||||||
|
"io.restx:restx-core-annotation-processor:${restx.version}",
|
||||||
|
"io.restx:restx-factory:${restx.version}",
|
||||||
|
"io.restx:restx-factory-admin:${restx.version}",
|
||||||
|
"io.restx:restx-validation:${restx.version}",
|
||||||
|
"io.restx:restx-monitor-codahale:${restx.version}",
|
||||||
|
"io.restx:restx-monitor-admin:${restx.version}",
|
||||||
|
"io.restx:restx-log-admin:${restx.version}",
|
||||||
|
"io.restx:restx-i18n-admin:${restx.version}",
|
||||||
|
"io.restx:restx-stats-admin:${restx.version}",
|
||||||
|
"io.restx:restx-servlet:${restx.version}",
|
||||||
|
"io.restx:restx-server-jetty8:${restx.version}!optional",
|
||||||
|
"io.restx:restx-apidocs:${restx.version}",
|
||||||
|
"io.restx:restx-specs-admin:${restx.version}",
|
||||||
|
"io.restx:restx-admin:${restx.version}",
|
||||||
|
"ch.qos.logback:logback-classic:1.0.13"
|
||||||
|
],
|
||||||
|
"test": [
|
||||||
|
"io.restx:restx-specs-tests:${restx.version}",
|
||||||
|
"junit:junit:4.11"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,155 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<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>
|
||||||
|
|
||||||
|
<artifactId>restx</artifactId>
|
||||||
|
<version>0.1-SNAPSHOT</version>
|
||||||
|
<packaging>war</packaging>
|
||||||
|
<name>restx-demo</name>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.target>1.8</maven.compiler.target>
|
||||||
|
<maven.compiler.source>1.8</maven.compiler.source>
|
||||||
|
<restx.version>0.35-rc4</restx.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>com.baeldung</groupId>
|
||||||
|
<artifactId>parent-modules</artifactId>
|
||||||
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.restx</groupId>
|
||||||
|
<artifactId>restx-core</artifactId>
|
||||||
|
<version>${restx.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.restx</groupId>
|
||||||
|
<artifactId>restx-security-basic</artifactId>
|
||||||
|
<version>${restx.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.restx</groupId>
|
||||||
|
<artifactId>restx-core-annotation-processor</artifactId>
|
||||||
|
<version>${restx.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.restx</groupId>
|
||||||
|
<artifactId>restx-factory</artifactId>
|
||||||
|
<version>${restx.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.restx</groupId>
|
||||||
|
<artifactId>restx-factory-admin</artifactId>
|
||||||
|
<version>${restx.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.restx</groupId>
|
||||||
|
<artifactId>restx-validation</artifactId>
|
||||||
|
<version>${restx.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.restx</groupId>
|
||||||
|
<artifactId>restx-monitor-codahale</artifactId>
|
||||||
|
<version>${restx.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.restx</groupId>
|
||||||
|
<artifactId>restx-monitor-admin</artifactId>
|
||||||
|
<version>${restx.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.restx</groupId>
|
||||||
|
<artifactId>restx-log-admin</artifactId>
|
||||||
|
<version>${restx.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.restx</groupId>
|
||||||
|
<artifactId>restx-i18n-admin</artifactId>
|
||||||
|
<version>${restx.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.restx</groupId>
|
||||||
|
<artifactId>restx-stats-admin</artifactId>
|
||||||
|
<version>${restx.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.restx</groupId>
|
||||||
|
<artifactId>restx-servlet</artifactId>
|
||||||
|
<version>${restx.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.restx</groupId>
|
||||||
|
<artifactId>restx-server-jetty8</artifactId>
|
||||||
|
<version>${restx.version}</version>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.restx</groupId>
|
||||||
|
<artifactId>restx-apidocs</artifactId>
|
||||||
|
<version>${restx.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.restx</groupId>
|
||||||
|
<artifactId>restx-specs-admin</artifactId>
|
||||||
|
<version>${restx.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.restx</groupId>
|
||||||
|
<artifactId>restx-admin</artifactId>
|
||||||
|
<version>${restx.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>ch.qos.logback</groupId>
|
||||||
|
<artifactId>logback-classic</artifactId>
|
||||||
|
<version>1.0.13</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.restx</groupId>
|
||||||
|
<artifactId>restx-specs-tests</artifactId>
|
||||||
|
<version>${restx.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>junit</groupId>
|
||||||
|
<artifactId>junit</artifactId>
|
||||||
|
<version>4.11</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-javadoc-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>attach-docs</id>
|
||||||
|
<!--
|
||||||
|
we generate javadoc before packaging the jar to let a chance to apidocs doclet
|
||||||
|
to generate comments dictionary to be packaged inside the jar as a resource
|
||||||
|
-->
|
||||||
|
<phase>prepare-package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>jar</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
<configuration>
|
||||||
|
<source>${maven.compiler.source}</source>
|
||||||
|
<doclet>restx.apidocs.doclet.ApidocsDoclet</doclet>
|
||||||
|
<docletArtifact>
|
||||||
|
<groupId>io.restx</groupId>
|
||||||
|
<artifactId>restx-apidocs-doclet</artifactId>
|
||||||
|
<version>${restx.version}</version>
|
||||||
|
</docletArtifact>
|
||||||
|
<additionalparam>-restx-target-dir ${project.basedir}/target/classes</additionalparam>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</project>
|
|
@ -0,0 +1,74 @@
|
||||||
|
package restx.demo;
|
||||||
|
|
||||||
|
import restx.config.ConfigLoader;
|
||||||
|
import restx.config.ConfigSupplier;
|
||||||
|
import restx.factory.Provides;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.google.common.base.Charsets;
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import restx.security.*;
|
||||||
|
import restx.factory.Module;
|
||||||
|
import restx.factory.Provides;
|
||||||
|
import javax.inject.Named;
|
||||||
|
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
|
||||||
|
@Module
|
||||||
|
public class AppModule {
|
||||||
|
@Provides
|
||||||
|
public SignatureKey signatureKey() {
|
||||||
|
return new SignatureKey("restx-demo -447494532235718370 restx-demo 801c9eaf-4116-48f2-906b-e979fba72757".getBytes(Charsets.UTF_8));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Named("restx.admin.password")
|
||||||
|
public String restxAdminPassword() {
|
||||||
|
return "4780";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
public ConfigSupplier appConfigSupplier(ConfigLoader configLoader) {
|
||||||
|
// Load settings.properties in restx.demo package as a set of config entries
|
||||||
|
return configLoader.fromResource("restx/demo/settings");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
public CredentialsStrategy credentialsStrategy() {
|
||||||
|
return new BCryptCredentialsStrategy();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
public BasicPrincipalAuthenticator basicPrincipalAuthenticator(
|
||||||
|
SecuritySettings securitySettings, CredentialsStrategy credentialsStrategy,
|
||||||
|
@Named("restx.admin.passwordHash") String defaultAdminPasswordHash, ObjectMapper mapper) {
|
||||||
|
return new StdBasicPrincipalAuthenticator(new StdUserService<>(
|
||||||
|
// use file based users repository.
|
||||||
|
// Developer's note: prefer another storage mechanism for your users if you need real user management
|
||||||
|
// and better perf
|
||||||
|
new FileBasedUserRepository<>(
|
||||||
|
StdUser.class, // this is the class for the User objects, that you can get in your app code
|
||||||
|
// with RestxSession.current().getPrincipal().get()
|
||||||
|
// it can be a custom user class, it just need to be json deserializable
|
||||||
|
mapper,
|
||||||
|
|
||||||
|
// this is the default restx admin, useful to access the restx admin console.
|
||||||
|
// if one user with restx-admin role is defined in the repository, this default user won't be
|
||||||
|
// available anymore
|
||||||
|
new StdUser("admin", ImmutableSet.<String>of("*")),
|
||||||
|
|
||||||
|
// the path where users are stored
|
||||||
|
Paths.get("data/users.json"),
|
||||||
|
|
||||||
|
// the path where credentials are stored. isolating both is a good practice in terms of security
|
||||||
|
// it is strongly recommended to follow this approach even if you use your own repository
|
||||||
|
Paths.get("data/credentials.json"),
|
||||||
|
|
||||||
|
// tells that we want to reload the files dynamically if they are touched.
|
||||||
|
// this has a performance impact, if you know your users / credentials never change without a
|
||||||
|
// restart you can disable this to get better perfs
|
||||||
|
true),
|
||||||
|
credentialsStrategy, defaultAdminPasswordHash),
|
||||||
|
securitySettings);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
package restx.demo;
|
||||||
|
|
||||||
|
import com.google.common.base.Optional;
|
||||||
|
import restx.server.WebServer;
|
||||||
|
import restx.server.Jetty8WebServer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class can be used to run the app.
|
||||||
|
*
|
||||||
|
* Alternatively, you can deploy the app as a war in a regular container like tomcat or jetty.
|
||||||
|
*
|
||||||
|
* Reading the port from system env PORT makes it compatible with heroku.
|
||||||
|
*/
|
||||||
|
public class AppServer {
|
||||||
|
public static final String WEB_INF_LOCATION = "src/main/webapp/WEB-INF/web.xml";
|
||||||
|
public static final String WEB_APP_LOCATION = "src/main/webapp";
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
int port = Integer.valueOf(Optional.fromNullable(System.getenv("PORT")).or("8080"));
|
||||||
|
WebServer server = new Jetty8WebServer(WEB_INF_LOCATION, WEB_APP_LOCATION, port, "0.0.0.0");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* load mode from system property if defined, or default to dev
|
||||||
|
* be careful with that setting, if you use this class to launch your server in production, make sure to launch
|
||||||
|
* it with -Drestx.mode=prod or change the default here
|
||||||
|
*/
|
||||||
|
System.setProperty("restx.mode", System.getProperty("restx.mode", "dev"));
|
||||||
|
System.setProperty("restx.app.package", "restx.demo");
|
||||||
|
|
||||||
|
server.startAndAwait();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
package restx.demo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A list of roles for the application.
|
||||||
|
*
|
||||||
|
* We don't use an enum here because it must be used inside an annotation.
|
||||||
|
*/
|
||||||
|
public final class Roles {
|
||||||
|
public static final String HELLO_ROLE = "hello";
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
package restx.demo.domain;
|
||||||
|
|
||||||
|
public class Message {
|
||||||
|
private String message;
|
||||||
|
|
||||||
|
public String getMessage() {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Message setMessage(final String message) {
|
||||||
|
this.message = message;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Message{" +
|
||||||
|
"message='" + message + '\'' +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
package restx.demo.rest;
|
||||||
|
|
||||||
|
import restx.demo.domain.Message;
|
||||||
|
import restx.demo.Roles;
|
||||||
|
import org.joda.time.DateTime;
|
||||||
|
import restx.annotations.GET;
|
||||||
|
import restx.annotations.POST;
|
||||||
|
import restx.annotations.RestxResource;
|
||||||
|
import restx.factory.Component;
|
||||||
|
import restx.security.PermitAll;
|
||||||
|
import restx.security.RolesAllowed;
|
||||||
|
import restx.security.RestxSession;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
|
@Component @RestxResource
|
||||||
|
public class HelloResource {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Say hello to currently logged in user.
|
||||||
|
*
|
||||||
|
* Authorized only for principals with Roles.HELLO_ROLE role.
|
||||||
|
*
|
||||||
|
* @return a Message to say hello
|
||||||
|
*/
|
||||||
|
@GET("/message")
|
||||||
|
@RolesAllowed(Roles.HELLO_ROLE)
|
||||||
|
public Message sayHello() {
|
||||||
|
return new Message().setMessage(String.format(
|
||||||
|
"hello %s, it's %s",
|
||||||
|
RestxSession.current().getPrincipal().get().getName(),
|
||||||
|
DateTime.now().toString("HH:mm:ss")));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Say hello to anybody.
|
||||||
|
*
|
||||||
|
* Does not require authentication.
|
||||||
|
*
|
||||||
|
* @return a Message to say hello
|
||||||
|
*/
|
||||||
|
@GET("/hello")
|
||||||
|
@PermitAll
|
||||||
|
public Message helloPublic(String who) {
|
||||||
|
return new Message().setMessage(String.format(
|
||||||
|
"hello %s, it's %s",
|
||||||
|
who, DateTime.now().toString("HH:mm:ss")));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class MyPOJO {
|
||||||
|
@NotNull
|
||||||
|
String value;
|
||||||
|
public String getValue(){ return value; }
|
||||||
|
public void setValue(String value){ this.value = value; }
|
||||||
|
}
|
||||||
|
@POST("/mypojo")
|
||||||
|
@PermitAll
|
||||||
|
public MyPOJO helloPojo(MyPOJO pojo){
|
||||||
|
pojo.setValue("hello "+pojo.getValue());
|
||||||
|
return pojo;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,94 @@
|
||||||
|
<configuration>
|
||||||
|
<contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator">
|
||||||
|
<resetJUL>true</resetJUL>
|
||||||
|
</contextListener>
|
||||||
|
<property name="LOGS_FOLDER" value="${logs.base:-logs}" />
|
||||||
|
|
||||||
|
<appender name="errorFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||||
|
<File>${LOGS_FOLDER}/errors.log</File>
|
||||||
|
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
|
||||||
|
<level>ERROR</level>
|
||||||
|
</filter>
|
||||||
|
<encoder>
|
||||||
|
<pattern>%d [%-16thread] [%-10X{principal}] %-5level %logger{36} - %msg%n</pattern>
|
||||||
|
</encoder>
|
||||||
|
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||||
|
<fileNamePattern>${LOGS_FOLDER}/errors.%d.log</fileNamePattern>
|
||||||
|
<maxHistory>30</maxHistory>
|
||||||
|
</rollingPolicy>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<if condition='p("restx.mode").equals("prod")'>
|
||||||
|
<then>
|
||||||
|
<!-- production mode -->
|
||||||
|
<appender name="appLog" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||||
|
<File>${LOGS_FOLDER}/app.log</File>
|
||||||
|
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
|
||||||
|
<level>INFO</level>
|
||||||
|
</filter>
|
||||||
|
<encoder>
|
||||||
|
<pattern>%d [%-16thread] [%-10X{principal}] %-5level %logger{36} - %msg%n</pattern>
|
||||||
|
</encoder>
|
||||||
|
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||||
|
<fileNamePattern>${LOGS_FOLDER}/app.%d.log</fileNamePattern>
|
||||||
|
<maxHistory>10</maxHistory>
|
||||||
|
</rollingPolicy>
|
||||||
|
</appender>
|
||||||
|
<appender name="debugFile" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||||
|
<File>${LOGS_FOLDER}/debug.log</File>
|
||||||
|
<encoder>
|
||||||
|
<pattern>%d [%-16thread] [%-10X{principal}] %-5level %logger{36} - %msg%n</pattern>
|
||||||
|
</encoder>
|
||||||
|
<rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
|
||||||
|
<fileNamePattern>${LOGS_FOLDER}/debug.%i.log.zip</fileNamePattern>
|
||||||
|
<minIndex>1</minIndex>
|
||||||
|
<maxIndex>3</maxIndex>
|
||||||
|
</rollingPolicy>
|
||||||
|
|
||||||
|
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
|
||||||
|
<maxFileSize>50MB</maxFileSize>
|
||||||
|
</triggeringPolicy>
|
||||||
|
</appender>
|
||||||
|
<root level="INFO">
|
||||||
|
<appender-ref ref="debugFile" />
|
||||||
|
<appender-ref ref="appLog" />
|
||||||
|
</root>
|
||||||
|
</then>
|
||||||
|
<else>
|
||||||
|
<!-- not production mode -->
|
||||||
|
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||||
|
<encoder>
|
||||||
|
<pattern>%d [%-16thread] [%-10X{principal}] %-5level %logger{36} - %msg%n</pattern>
|
||||||
|
</encoder>
|
||||||
|
</appender>
|
||||||
|
<appender name="appLog" class="ch.qos.logback.core.FileAppender">
|
||||||
|
<File>${LOGS_FOLDER}/app.log</File>
|
||||||
|
<encoder>
|
||||||
|
<pattern>%d [%-16thread] [%-10X{principal}] %-5level %logger{36} - %msg%n</pattern>
|
||||||
|
</encoder>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<root level="INFO">
|
||||||
|
<appender-ref ref="STDOUT" />
|
||||||
|
<appender-ref ref="appLog" />
|
||||||
|
</root>
|
||||||
|
</else>
|
||||||
|
</if>
|
||||||
|
|
||||||
|
<!-- clean up container logs -->
|
||||||
|
<logger name="org.eclipse.jetty.server.AbstractConnector" level="WARN" />
|
||||||
|
<logger name="org.eclipse.jetty.server.handler.ContextHandler" level="WARN" />
|
||||||
|
<logger name="org.eclipse.jetty.webapp.StandardDescriptorProcessor" level="WARN" />
|
||||||
|
|
||||||
|
<logger name="org.hibernate.validator.internal.engine.ConfigurationImpl" level="WARN" />
|
||||||
|
<logger name="org.reflections.Reflections" level="WARN" />
|
||||||
|
|
||||||
|
<logger name="restx.factory.Factory" level="WARN" />
|
||||||
|
|
||||||
|
<!-- app logs - set DEBUG level, in prod it will go to a dedicated file -->
|
||||||
|
<logger name="restx.demo" level="DEBUG" />
|
||||||
|
|
||||||
|
<root level="INFO">
|
||||||
|
<appender-ref ref="errorFile" />
|
||||||
|
</root>
|
||||||
|
</configuration>
|
|
@ -0,0 +1 @@
|
||||||
|
app.name=restx-demo
|
|
@ -0,0 +1,15 @@
|
||||||
|
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
|
||||||
|
version="3.0" metadata-complete="true">
|
||||||
|
|
||||||
|
<servlet>
|
||||||
|
<servlet-name>restx</servlet-name>
|
||||||
|
<servlet-class>restx.servlet.RestxMainRouterServlet</servlet-class>
|
||||||
|
<load-on-startup>1</load-on-startup>
|
||||||
|
</servlet>
|
||||||
|
<servlet-mapping>
|
||||||
|
<servlet-name>restx</servlet-name>
|
||||||
|
<url-pattern>/api/*</url-pattern>
|
||||||
|
</servlet-mapping>
|
||||||
|
</web-app>
|
|
@ -0,0 +1,23 @@
|
||||||
|
package restx.demo.rest;
|
||||||
|
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
import restx.tests.FindSpecsIn;
|
||||||
|
import restx.tests.RestxSpecTestsRunner;
|
||||||
|
|
||||||
|
@RunWith(RestxSpecTestsRunner.class)
|
||||||
|
@FindSpecsIn("specs/hello")
|
||||||
|
public class HelloResourceSpecUnitTest {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Useless, thanks to both @RunWith(RestxSpecTestsRunner.class) & @FindSpecsIn()
|
||||||
|
*
|
||||||
|
* @Rule
|
||||||
|
* public RestxSpecRule rule = new RestxSpecRule();
|
||||||
|
*
|
||||||
|
* @Test
|
||||||
|
* public void test_spec() throws Exception {
|
||||||
|
* rule.runTest(specTestPath);
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
title: should admin say hello
|
||||||
|
given:
|
||||||
|
- time: 2013-08-28T01:18:00.822+02:00
|
||||||
|
- uuids: [ "e2b4430f-9541-4602-9a3a-413d17c56a6b" ]
|
||||||
|
wts:
|
||||||
|
- when: |
|
||||||
|
GET message
|
||||||
|
$RestxSession: {"_expires":"2013-09-27T01:18:00.822+02:00","principal":"admin","sessionKey":"e2b4430f-9541-4602-9a3a-413d17c56a6b"}
|
||||||
|
then: |
|
||||||
|
{"message":"hello admin, it's 01:18:00"}
|
|
@ -0,0 +1,8 @@
|
||||||
|
title: should admin say hello
|
||||||
|
given:
|
||||||
|
- time: 2013-08-28T01:18:00.822+02:00
|
||||||
|
wts:
|
||||||
|
- when: |
|
||||||
|
GET hello?who=xavier
|
||||||
|
then: |
|
||||||
|
{"message":"hello xavier, it's 01:18:00"}
|
|
@ -0,0 +1,17 @@
|
||||||
|
title: should missing post value triggers a validation error
|
||||||
|
given:
|
||||||
|
- time: 2013-08-28T01:18:00.822+02:00
|
||||||
|
- uuids: [ "e2b4430f-9541-4602-9a3a-413d17c56a6b" ]
|
||||||
|
wts:
|
||||||
|
- when: |
|
||||||
|
POST mypojo
|
||||||
|
$RestxSession: {"_expires":"2013-09-27T01:18:00.822+02:00","principal":"user1","sessionKey":"e2b4430f-9541-4602-9a3a-413d17c56a6b"}
|
||||||
|
{}
|
||||||
|
then: |
|
||||||
|
400
|
||||||
|
- when: |
|
||||||
|
POST mypojo
|
||||||
|
$RestxSession: {"_expires":"2013-09-27T01:18:00.822+02:00","principal":"user1","sessionKey":"e2b4430f-9541-4602-9a3a-413d17c56a6b"}
|
||||||
|
{"value":"world"}
|
||||||
|
then: |
|
||||||
|
{"value":"hello world"}
|
|
@ -0,0 +1,10 @@
|
||||||
|
title: should user1 say hello
|
||||||
|
given:
|
||||||
|
- time: 2013-08-28T01:18:00.822+02:00
|
||||||
|
- uuids: [ "e2b4430f-9541-4602-9a3a-413d17c56a6b" ]
|
||||||
|
wts:
|
||||||
|
- when: |
|
||||||
|
GET message
|
||||||
|
$RestxSession: {"_expires":"2013-09-27T01:18:00.822+02:00","principal":"user1","sessionKey":"e2b4430f-9541-4602-9a3a-413d17c56a6b"}
|
||||||
|
then: |
|
||||||
|
{"message":"hello user1, it's 01:18:00"}
|
|
@ -0,0 +1,10 @@
|
||||||
|
title: should user2 not say hello
|
||||||
|
given:
|
||||||
|
- time: 2013-08-28T01:19:44.770+02:00
|
||||||
|
- uuids: [ "56f71fcc-42d3-422f-9458-8ad37fc4a0b5" ]
|
||||||
|
wts:
|
||||||
|
- when: |
|
||||||
|
GET message
|
||||||
|
$RestxSession: {"_expires":"2013-09-27T01:19:44.770+02:00","principal":"user2","sessionKey":"56f71fcc-42d3-422f-9458-8ad37fc4a0b5"}
|
||||||
|
then: |
|
||||||
|
403
|
Loading…
Reference in New Issue