Merge pull request #8373 from SmartyAnsh/BAEL-3464_Ninja

Bael 3464 ninja
This commit is contained in:
Eric Martin 2019-12-21 17:54:28 -06:00 committed by GitHub
commit f7f100e040
27 changed files with 753 additions and 2 deletions

183
ninja/pom.xml Normal file
View File

@ -0,0 +1,183 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>ninja</artifactId>
<packaging>jar</packaging>
<groupId>com.baeldung</groupId>
<version>1.0.0</version>
<url>http://www.ninjaframework.org</url>
<properties>
<ninja.version>6.5.0</ninja.version>
<jetty.version>9.4.18.v20190429</jetty.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.2</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>1.3.1</version>
<executions>
<execution>
<id>enforce-banned-dependencies</id>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<bannedDependencies>
<excludes>
<exclude>commons-logging</exclude>
</excludes>
</bannedDependencies>
</rules>
<fail>true</fail>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>${jetty.version}</version>
<configuration>
<webApp>
<contextPath>/</contextPath>
</webApp>
<stopKey>stop</stopKey>
<stopPort>8889</stopPort>
<scanIntervalSeconds>1</scanIntervalSeconds>
<reload>automatic</reload>
<scanTargetPatterns>
<scanTargetPattern>
<directory>target/classes</directory>
<includes>
<include>**/*</include>
</includes>
<excludes>
<exclude>**/*.ftl.html</exclude>
<exclude>assets/**</exclude>
</excludes>
</scanTargetPattern>
</scanTargetPatterns>
<systemProperties>
<systemProperty>
<name>ninja.mode</name>
<value>dev</value>
</systemProperty>
</systemProperties>
</configuration>
</plugin>
<!-- Allows you to run Ninja via the SuperDevMode. -->
<!-- run "mvn ninja:run" on the command line for the best -->
<!-- development experience. -->
<plugin>
<groupId>org.ninjaframework</groupId>
<artifactId>ninja-maven-plugin</artifactId>
<version>${ninja.version}</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.2</version>
<configuration>
<createDependencyReducedPom>true</createDependencyReducedPom>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>ninja.standalone.NinjaJetty</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*</include>
</includes>
<excludes>
<exclude>**/*.java</exclude>
</excludes>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*</include>
</includes>
</resource>
</resources>
</build>
<dependencies>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>bootstrap</artifactId>
<version>3.3.4</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jquery</artifactId>
<version>2.1.3</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.186</version>
</dependency>
<dependency>
<groupId>org.ninjaframework</groupId>
<artifactId>ninja-standalone</artifactId>
<version>${ninja.version}</version>
</dependency>
<dependency>
<groupId>org.ninjaframework</groupId>
<artifactId>ninja-test-utilities</artifactId>
<version>${ninja.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
version="2.0">
<!-- Database settings for development -->
<persistence-unit name="dev_unit"
transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<properties>
<property name="hibernate.connection.driver_class" value="org.h2.Driver" />
<property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect" />
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.format_sql" value="true" />
<property name="hibernate.hbm2ddl.auto" value="update" />
<property name="hibernate.connection.autocommit" value="true" />
<!-- Connection Pooling settings -->
<property name="hibernate.connection.provider_class" value="org.hibernate.service.jdbc.connections.internal.C3P0ConnectionProvider" />
<property name="hibernate.c3p0.max_size" value="100" />
<property name="hibernate.c3p0.min_size" value="0" />
<property name="hibernate.c3p0.acquire_increment" value="1" />
<property name="hibernate.c3p0.idle_test_period" value="300" />
<property name="hibernate.c3p0.max_statements" value="0" />
<property name="hibernate.c3p0.timeout" value="100" />
</properties>
</persistence-unit>
</persistence>

View File

@ -0,0 +1,3 @@
/* Add additional stylesheets below
-------------------------------------------------- */

View File

@ -0,0 +1,13 @@
package conf;
import java.util.List;
import ninja.Filter;
public class Filters implements ninja.application.ApplicationFilters {
@Override
public void addFilters(List<Class<? extends Filter>> filters) {
// Add your application - wide filters here
// filters.add(MyFilter.class);
}
}

View File

@ -0,0 +1,18 @@
package conf;
import com.google.inject.AbstractModule;
import com.google.inject.Singleton;
import services.UserService;
import services.UserServiceImpl;
@Singleton
public class Module extends AbstractModule {
protected void configure() {
bind(UserService.class).to(UserServiceImpl.class);
}
}

View File

@ -0,0 +1,32 @@
package conf;
import ninja.AssetsController;
import ninja.Router;
import ninja.application.ApplicationRoutes;
import controllers.ApplicationController;
public class Routes implements ApplicationRoutes {
@Override
public void init(Router router) {
router.GET().route("/index").with(ApplicationController::index);
router.GET().route("/home").with(ApplicationController::home);
router.GET().route("/hello").with(ApplicationController::helloWorld);
router.GET().route("/userJson").with(ApplicationController::userJson);
router.GET().route("/createUser").with(ApplicationController::createUser);
router.GET().route("/flash").with(ApplicationController::showFlashMsg);
router.GET().route("/users").with(ApplicationController::fetchUsers);
router.POST().route("/users").with(ApplicationController::insertUser);
//Assets
router.GET().route("/assets/webjars/{fileName: .*}").with(AssetsController::serveWebJars);
router.GET().route("/assets/{fileName: .*}").with(AssetsController::serveStatic);
//Index
router.GET().route("/.*").with(ApplicationController::index);
}
}

View File

@ -0,0 +1,21 @@
application.name=baeldung ninja dev application
%test.application.name=baeldung ninja test application
%prod.application.name=baeldung ninja application
application.cookie.prefix=NINJA
application.languages=fr,en
application.session.expire_time_in_seconds=3600
application.session.send_only_if_changed=true
application.session.transferred_over_https_only=false
ninja.port=8000
ninja.ssl.port=8001
application.secret = fxSjSL9Q017BSL7gBnkyo2Prln7uXaXIT35gotXRIED8c46OSa8s4QdoIQdTsEtj
# h2 jpa configuration
ninja.jpa.persistence_unit_name=dev_unit
db.connection.url=jdbc:h2:./devDb
db.connection.username=sa
db.connection.password=

View File

@ -0,0 +1,2 @@
header.home=Home!
helloMsg=Hello, welcome to Ninja Framework!

View File

@ -0,0 +1,2 @@
header.home=Accueil!
helloMsg=Bonjour, bienvenue dans Ninja Framework!

View File

@ -0,0 +1,102 @@
package controllers;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import javax.inject.Inject;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import com.google.inject.persist.Transactional;
import models.User;
import ninja.Context;
import ninja.Result;
import ninja.Results;
import ninja.i18n.Lang;
import ninja.i18n.Messages;
import ninja.jpa.UnitOfWork;
import ninja.session.FlashScope;
import ninja.validation.JSR303Validation;
import ninja.validation.Validation;
import services.UserService;
@Singleton
public class ApplicationController {
@Inject
Lang lang;
@Inject
Messages msg;
private static Log logger = LogFactory.getLog(ApplicationController.class);
@Inject
Provider<EntityManager> entityManagerProvider;
@Inject
UserService userService;
public Result index() {
return Results.html();
}
public Result userJson() {
HashMap<String, String> userMap = userService.getUserMap();
logger.info(userMap);
return Results.json().render(userMap);
}
public Result helloWorld(Context context) {
Optional<String> language = Optional.of("fr");
String helloMsg = msg.get("helloMsg", language).get();
return Results.text().render(helloMsg);
}
public Result showFlashMsg(FlashScope flashScope) {
flashScope.success("Success message");
flashScope.error("Error message");
return Results.redirect("/home");
}
public Result home() {
return Results.html();
}
public Result createUser() {
return Results.html();
}
@UnitOfWork
public Result fetchUsers() {
EntityManager entityManager = entityManagerProvider.get();
Query q = entityManager.createQuery("SELECT x FROM User x");
List<User> users = (List<User>) q.getResultList();
return Results.json().render(users);
}
@Transactional
public Result insertUser(FlashScope flashScope, @JSR303Validation User user, Validation validation) {
logger.info("Inserting User : " +user);
if (validation.getViolations().size() > 0) {
flashScope.error("Validation Error: User can't be created");
} else {
EntityManager entityManager = entityManagerProvider.get();
entityManager.persist(user);
entityManager.flush();
flashScope.success("User '" + user + "' is created successfully");
}
return Results.redirect("/home");
}
}

View File

@ -0,0 +1,15 @@
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../config/ehcache.xsd" updateCheck="false">
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="false"
maxElementsOnDisk="10000000"
diskPersistent="false"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU"
/>
</ehcache>

View File

@ -0,0 +1,33 @@
<configuration>
<!-- Uncomment to enable file-based logging with
daily (or size exceeding) gzip archival.
Also uncomment the "ROLLING" reference in <root>.
<appender name="ROLLING" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>mylog.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<FileNamePattern>mylog.%d{yyyy-MM-dd}.%i.log.gz</FileNamePattern>
<MaxHistory>30</MaxHistory>
<timeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>10MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender> -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<!-- encoders are assigned the type
ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="info">
<appender-ref ref="STDOUT" />
<!-- <appender-ref ref="ROLLING" /> -->
</root>
</configuration>

View File

@ -0,0 +1,25 @@
package models;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.validation.constraints.NotNull;
@Entity
public class User {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
Long id;
@NotNull
public String firstName;
public String email;
public String toString() {
return firstName + " : " + email;
}
}

View File

@ -0,0 +1,9 @@
package services;
import java.util.HashMap;
public interface UserService {
HashMap<String, String> getUserMap();
}

View File

@ -0,0 +1,15 @@
package services;
import java.util.HashMap;
public class UserServiceImpl implements UserService {
@Override
public HashMap<String, String> getUserMap() {
HashMap<String, String> userMap = new HashMap<>();
userMap.put("name", "Norman Lewis");
userMap.put("email", "norman@email.com");
return userMap;
}
}

View File

@ -0,0 +1,12 @@
<#import "../layout/defaultLayout.ftl.html" as layout>
<@layout.myLayout "Create User">
<form method="post" action="users">
First Name : <input type="text" name="firstName"/>
<br/>
Email : <input type="text" name="email"/>
<br/>
<input type="submit" value="Create"/>
</@layout.myLayout>

View File

@ -0,0 +1,9 @@
<#import "../layout/defaultLayout.ftl.html" as layout>
<@layout.myLayout "Home page">
<h1>${i18n("helloMsg")}</h1>
<a href="/userJson">User Json</a>
</@layout.myLayout>

View File

@ -0,0 +1,9 @@
<html>
<head>
<title>Ninja: Index</title>
</head>
<body>
<h1>${i18n("helloMsg")}</h1>
<a href="/userJson">User Json</a>
</body>
</html>

View File

@ -0,0 +1,58 @@
<#macro myLayout title="Layout example">
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>${title}</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="">
<meta name="author" content="">
<!-- Le styles -->
<link href="/assets/webjars/bootstrap/3.3.4/css/bootstrap.min.css" rel="stylesheet">
<!-- Optional theme -->
<link rel="stylesheet" href="/assets/webjars/bootstrap/3.3.4/css/bootstrap-theme.min.css">
<!-- Latest compiled and minified JavaScript -->
<style type="text/css">
body {
padding-top: 60px;
padding-bottom: 40px;
}
.error-template {padding: 40px 15px;text-align: center;}
</style>
<!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->
<!--[if lt IE 9]>
<script src="https://html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
</head>
<body>
<div class="container">
<#include "header.ftl.html"/>
<#if (flash.error)??>
<div class="alert alert-danger">
${flash.error}
</div>
</#if>
<#if (flash.success)??>
<div class="alert alert-success">
${flash.success}
</div>
</#if>
<#nested/>
<#include "footer.ftl.html"/>
</div> <!-- /container -->
<script type="text/javascript" src="/assets/webjars/jquery/2.1.3/jquery.js"></script>
<script type="text/javascript" src="/assets/webjars/bootstrap/3.3.4/js/bootstrap.min.js"></script>
</body>
</html>
</#macro>

View File

@ -0,0 +1,5 @@
<hr>
<footer>
Built with <a href="http://www.ninjaframework.org">Ninja framework</a>.
</footer>

View File

@ -0,0 +1,20 @@
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li class="active"><a href="/">${i18n("header.home")}</a></li>
<li class=""><a href="/hello">Hello</a></li>
<li class=""><a href="/users">List User</a></li>
<li class=""><a href="/createUser">Create User</a></li>
</ul>
</div>
<!--/.navbar-collapse -->
</div>
</div>

View File

@ -0,0 +1,18 @@
<#import "../layout/defaultLayout.ftl.html" as layout>
<@layout.myLayout "Error. Forbidden.">
<div class="container">
<div class="row">
<div class="col-md-12">
<div class="error-template">
<h1>
Oops!</h1>
<h2>
403 Forbidden</h2>
<div class="error-details">
Sorry, an error has occured. Requested page is forbidden!
</div>
</div>
</div>
</div>
</div>
</@layout.myLayout>

View File

@ -0,0 +1,18 @@
<#import "../layout/defaultLayout.ftl.html" as layout>
<@layout.myLayout "Error. Not found.">
<div class="container">
<div class="row">
<div class="col-md-12">
<div class="error-template">
<h1>
Oops!</h1>
<h2>
404 Not Found</h2>
<div class="error-details">
Sorry, an error has occured. Requested page not found!
</div>
</div>
</div>
</div>
</div>
</@layout.myLayout>

View File

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (C) 2013 the original author or authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<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">
<display-name>ninja</display-name>
<listener>
<listener-class>ninja.servlet.NinjaServletListener</listener-class>
</listener>
<filter>
<filter-name>guiceFilter</filter-name>
<filter-class>com.google.inject.servlet.GuiceFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>guiceFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>

View File

@ -0,0 +1,27 @@
package controllers;
import static org.hamcrest.CoreMatchers.containsString;
import static org.junit.Assert.assertThat;
import org.doctester.testbrowser.Request;
import org.doctester.testbrowser.Response;
import org.junit.Test;
import ninja.NinjaDocTester;
public class ApiControllerDocTesterTest extends NinjaDocTester {
String URL_INDEX = "/";
String URL_HELLO = "/hello";
@Test
public void testGetIndex() {
Response response = makeRequest(Request.GET().url(testServerUrl().path(URL_INDEX)));
assertThat(response.payload, containsString("Hello, welcome to Ninja Framework!"));
}
@Test
public void testGetHello() {
Response response = makeRequest(Request.GET().url(testServerUrl().path(URL_HELLO)));
assertThat(response.payload, containsString("Bonjour, bienvenue dans Ninja Framework!"));
}
}

View File

@ -0,0 +1,32 @@
package controllers;
import static org.junit.Assert.assertEquals;
import javax.inject.Inject;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import ninja.NinjaRunner;
import ninja.Result;
import services.UserService;
@RunWith(NinjaRunner.class)
public class ApiControllerMockUnitTest {
@Inject private UserService userService;
ApplicationController applicationController;
@Before
public void setupTest() {
applicationController = new ApplicationController();
applicationController.userService = userService;
}
@Test
public void testThatGetUserJson() {
Result result = applicationController.userJson();
System.out.println(result.getRenderable());
assertEquals(userService.getUserMap().toString(), result.getRenderable().toString());
}
}

View File

@ -590,7 +590,7 @@
<!-- <module>muleesb</module> --> <!-- Fixing in BAEL-10878 -->
<module>mustache</module>
<module>mybatis</module>
<module>ninja</module>
<module>netflix</module>
<module>optaplanner</module>
@ -1225,7 +1225,7 @@
<!-- <module>muleesb</module> --> <!-- Fixing in BAEL-10878 -->
<module>mustache</module>
<module>mybatis</module>
<module>ninja</module>
<module>netflix</module>
<module>optaplanner</module>