Просмотр исходного кода

Add Minijax framework (#3075)

[Minijax](https://minijax.org) - Lightweight subset of Java EE
Cody Ebberson 7 лет назад
Родитель
Сommit
4a603d8b67

+ 1 - 0
.travis.yml

@@ -92,6 +92,7 @@ env:
     - "TESTDIR=Java/jlhttp"
     - "TESTDIR=Java/jooby"
     - "TESTDIR=Java/light-java"
+    - "TESTDIR=Java/minijax"
     - "TESTDIR=Java/netty"
     - "TESTDIR=Java/ninja-standalone"
     - "TESTDIR=Java/officefloor"

+ 21 - 0
frameworks/Java/minijax/README.md

@@ -0,0 +1,21 @@
+# Minijax Benchmarking Test
+
+[Minijax](https://minijax.org) - Lightweight subset of JAX-RS and JSR 330.
+
+* Jetty for HTTP server
+* Mustache for HTML templates
+* MySQL for database
+* Eclipselink for ORM
+
+All REST endpoints are in [MinijaxBenchmark.java](src/main/java/com/techempower/minijax/MinijaxBenchmark.java)
+
+## Test URLs
+
+All implementations use the same URLs.
+
+ * Plaintext - `http://localhost:8080/plaintext`
+ * JSON - `http://localhost:8080/json`
+ * DB - `http://localhost:8080/db`
+ * Queries - `http://localhost:8080/db?queries=`
+ * Updates - `http://localhost:8080/updates?queries=`
+ * Fortune - `http://localhost:8080/fortunes`

+ 27 - 0
frameworks/Java/minijax/benchmark_config.json

@@ -0,0 +1,27 @@
+{
+  "framework": "minijax",
+  "tests": [{
+    "default": {
+      "setup_file": "setup",
+      "json_url": "/json",
+      "plaintext_url": "/plaintext",
+      "db_url": "/db",
+      "query_url": "/queries?queries=",
+      "fortune_url": "/fortunes",
+      "update_url": "/updates?queries=",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Fullstack",
+      "database": "MySQL",
+      "framework": "Minijax",
+      "language": "Java",
+      "flavor": "None",
+      "orm": "Full",
+      "platform": "JAX-RS",
+      "webserver": "Jetty",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "Minijax"
+    }
+  }]
+}

+ 4 - 0
frameworks/Java/minijax/minijax.properties

@@ -0,0 +1,4 @@
+javax.persistence.jdbc.url=jdbc:mysql://localhost:3306/hello_world?jdbcCompliantTruncation=false&zeroDateTimeBehavior=convertToNull&traceProtocol=false&useUnbufferedInput=false&useReadAheadInput=false&maintainTimeStats=false&useServerPrepStmts=true&cacheRSMetadata=true&useSSL=false
+javax.persistence.jdbc.driver=com.mysql.cj.jdbc.Driver
+javax.persistence.jdbc.user=benchmarkdbuser
+javax.persistence.jdbc.password=benchmarkdbpass

+ 139 - 0
frameworks/Java/minijax/pom.xml

@@ -0,0 +1,139 @@
+<?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>
+    <groupId>com.techempower</groupId>
+    <artifactId>minijax-techempower</artifactId>
+    <version>0.0.1</version>
+    <packaging>jar</packaging>
+    <name>minijax-techempower</name>
+    <description>Minijax implementation of TechEmpower Framework Benchmarks</description>
+    <properties>
+        <eclipselink.version>2.7.0</eclipselink.version>
+        <jpa.version>2.1.1</jpa.version>
+        <logback.version>1.2.3</logback.version>
+        <minijax.version>0.0.30</minijax.version>
+        <mysql-connector.version>6.0.6</mysql-connector.version>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <shade.version>3.1.0</shade.version>
+    </properties>
+    <dependencies>
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+            <version>${mysql-connector.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.eclipse.persistence</groupId>
+            <artifactId>eclipselink</artifactId>
+            <version>${eclipselink.version}</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.eclipse.persistence</groupId>
+                    <artifactId>javax.persistence</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.eclipse.persistence</groupId>
+            <artifactId>javax.persistence</artifactId>
+            <version>${jpa.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.minijax</groupId>
+            <artifactId>minijax-core</artifactId>
+            <version>${minijax.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.minijax</groupId>
+            <artifactId>minijax-db</artifactId>
+            <version>${minijax.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.minijax</groupId>
+            <artifactId>minijax-json</artifactId>
+            <version>${minijax.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.minijax</groupId>
+            <artifactId>minijax-mustache</artifactId>
+            <version>${minijax.version}</version>
+        </dependency>
+    </dependencies>
+    <repositories>
+        <repository>
+            <id>ossrh</id>
+            <url>https://oss.sonatype.org/content/repositories/releases/</url>
+        </repository>
+    </repositories>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>2.3.2</version>
+                <inherited>true</inherited>
+                <configuration>
+                    <source>1.8</source>
+                    <target>1.8</target>
+                    <optimize>true</optimize>
+                    <debug>false</debug>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>com.github.ekryd.sortpom</groupId>
+                <artifactId>sortpom-maven-plugin</artifactId>
+                <version>2.8.0</version>
+                <configuration>
+                    <predefinedSortOrder>recommended_2008_06</predefinedSortOrder>
+                    <lineSeparator>\n</lineSeparator>
+                    <nrOfIndentSpace>4</nrOfIndentSpace>
+                    <encoding>${project.build.sourceEncoding}</encoding>
+                    <sortProperties>true</sortProperties>
+                    <sortDependencies>groupId,artifactId</sortDependencies>
+                    <createBackupFile>false</createBackupFile>
+                </configuration>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>sort</goal>
+                        </goals>
+                        <phase>verify</phase>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-shade-plugin</artifactId>
+                <version>${shade.version}</version>
+                <configuration>
+                    <filters>
+                        <filter>
+                            <artifact>*:*</artifact>
+                            <excludes>
+                                <exclude>META-INF/*.SF</exclude>
+                                <exclude>META-INF/*.DSA</exclude>
+                                <exclude>META-INF/*.RSA</exclude>
+                            </excludes>
+                        </filter>
+                    </filters>
+                    <createDependencyReducedPom>false</createDependencyReducedPom>
+                </configuration>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>shade</goal>
+                        </goals>
+                        <phase>package</phase>
+                        <configuration>
+                            <transformers>
+                                <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
+                                    <mainClass>com.techempower.minijax.MinijaxBenchmark</mainClass>
+                                </transformer>
+                            </transformers>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+</project>

+ 9 - 0
frameworks/Java/minijax/setup.sh

@@ -0,0 +1,9 @@
+#!/bin/bash
+
+fw_depends mysql java maven
+
+sed -i 's|localhost|'${DBHOST}'|g' minijax.properties
+
+mvn clean package
+
+java -XX:+UseNUMA -XX:+UseParallelGC -jar target/minijax-techempower-0.0.1.jar &

+ 7 - 0
frameworks/Java/minijax/source_code

@@ -0,0 +1,7 @@
+minijax/src/main/java/com/techempower/minijax/Dao.java
+minijax/src/main/java/com/techempower/minijax/Fortune.java
+minijax/src/main/java/com/techempower/minijax/MinijaxBenchmark.java
+minijax/src/main/java/com/techempower/minijax/World.java
+minijax/src/main/resources/META-INF/persistence.xml
+minijax/src/main/resources/templates/error.mustache
+minijax/src/main/resources/templates/fortunes.mustache

+ 54 - 0
frameworks/Java/minijax/src/main/java/com/techempower/minijax/Dao.java

@@ -0,0 +1,54 @@
+package com.techempower.minijax;
+
+import static java.util.stream.Collectors.*;
+
+import java.util.List;
+import java.util.concurrent.ThreadLocalRandom;
+import java.util.stream.Stream;
+
+import javax.enterprise.context.RequestScoped;
+import javax.persistence.EntityManager;
+import javax.persistence.EntityTransaction;
+import javax.persistence.PersistenceContext;
+
+@RequestScoped
+public class Dao {
+
+    @PersistenceContext
+    private EntityManager em;
+
+    public World getWorldById(final int id) {
+        return em.find(World.class, id);
+    }
+
+    public World getRandomWorld() {
+        return getWorldById(randomWorld());
+    }
+
+    public List<World> getWorlds(final int count) {
+        return Stream.generate(() -> getWorldById(randomWorld()))
+                .limit(clamp(count, 1, 500))
+                .collect(toList());
+    }
+
+    public void batchUpdate(final List<World> worlds) {
+        final EntityTransaction tx = em.getTransaction();
+        tx.begin();
+        for (final World world : worlds) {
+            em.merge(world);
+        }
+        tx.commit();
+    }
+
+    public List<Fortune> getAllFortunes() {
+        return em.createNamedQuery("Fortune.getAll", Fortune.class).getResultList();
+    }
+
+    public static int randomWorld() {
+        return 1 + ThreadLocalRandom.current().nextInt(10000);
+    }
+
+    private static int clamp(final int x, final int min, final int max) {
+        return Math.min(max, Math.max(min, x));
+    }
+}

+ 49 - 0
frameworks/Java/minijax/src/main/java/com/techempower/minijax/Fortune.java

@@ -0,0 +1,49 @@
+package com.techempower.minijax;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.NamedQuery;
+import javax.persistence.Table;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlRootElement;
+
+@Entity
+@Table(name = "fortune")
+@NamedQuery(name = "Fortune.getAll", query = "SELECT f FROM Fortune f")
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.FIELD)
+public class Fortune implements Comparable<Fortune> {
+
+    @Id
+    private int id;
+
+    @Column(name = "message", nullable = false)
+    private String message;
+
+    public Fortune() {
+    }
+
+    public Fortune(final String message) {
+        this.message = message;
+    }
+
+    public Fortune(final int id, final String message) {
+        this.id = id;
+        this.message = message;
+    }
+
+    public int getId() {
+        return id;
+    }
+
+    public String getMessage() {
+        return message;
+    }
+
+    @Override
+    public int compareTo(final Fortune o) {
+        return message.compareTo(o.message);
+    }
+}

+ 101 - 0
frameworks/Java/minijax/src/main/java/com/techempower/minijax/MinijaxBenchmark.java

@@ -0,0 +1,101 @@
+package com.techempower.minijax;
+
+import static java.util.Collections.*;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import javax.inject.Inject;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+
+import org.minijax.Minijax;
+import org.minijax.db.PersistenceFeature;
+import org.minijax.json.JsonFeature;
+import org.minijax.mustache.MustacheFeature;
+import org.minijax.view.View;
+
+public class MinijaxBenchmark {
+
+    @Inject
+    private Dao dao;
+
+    @GET
+    @Path("/plaintext")
+    @Produces(MediaType.TEXT_PLAIN)
+    public static String plaintext() {
+        return "Hello, World!";
+    }
+
+    @GET
+    @Path("/json")
+    @Produces(MediaType.APPLICATION_JSON)
+    public static Map<String, String> json() {
+        return singletonMap("message", "Hello, World!");
+    }
+
+    @GET
+    @Path("/db")
+    @Produces(MediaType.APPLICATION_JSON)
+    public World db() {
+        return dao.getRandomWorld();
+    }
+
+    @GET
+    @Path("/queries")
+    @Produces(MediaType.APPLICATION_JSON)
+    public List<World> queries(@QueryParam("queries") final String count) {
+        return dao.getWorlds(parseCount(count));
+    }
+
+    @GET
+    @Path("/fortunes")
+    @Produces("text/html;charset=UTF-8")
+    public View fortunes() {
+        final List<Fortune> fortunes = dao.getAllFortunes();
+        fortunes.add(new Fortune("Additional fortune added at request time."));
+        Collections.sort(fortunes);
+
+        final View view = new View("fortunes");
+        view.getModel().put("fortunes", fortunes);
+        return view;
+    }
+
+    @GET
+    @Path("/updates")
+    @Produces(MediaType.APPLICATION_JSON)
+    public List<World> updates(@QueryParam("queries") final String count) {
+        final List<World> worlds = dao.getWorlds(parseCount(count));
+        for (final World world : worlds) {
+            world.setRandomNumber(Dao.randomWorld());
+        }
+        dao.batchUpdate(worlds);
+        return worlds;
+    }
+
+    private static int parseCount(final String count) {
+        if (count == null || count.isEmpty()) {
+            return 1;
+        }
+        try {
+            return Integer.parseInt(count);
+        } catch (final NumberFormatException ex) {
+            return 1;
+        }
+    }
+
+    public static void main(final String[] args) throws IOException {
+        new Minijax()
+                .properties("minijax.properties")
+                .register(PersistenceFeature.class)
+                .register(JsonFeature.class)
+                .register(MustacheFeature.class)
+                .register(MinijaxBenchmark.class)
+                .run();
+    }
+}

+ 42 - 0
frameworks/Java/minijax/src/main/java/com/techempower/minijax/World.java

@@ -0,0 +1,42 @@
+package com.techempower.minijax;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Table;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlRootElement;
+
+@Entity
+@Table(name = "world")
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.FIELD)
+public class World {
+
+    @Id
+    private int id;
+
+    @Column(name = "randomNumber", nullable = false)
+    private int randomNumber;
+
+    public World() {
+    }
+
+    public World(final int id, final int randomNumber) {
+        this.id = id;
+        this.randomNumber = randomNumber;
+    }
+
+    public int getId() {
+        return id;
+    }
+
+    public int getRandomNumber() {
+        return randomNumber;
+    }
+
+    public void setRandomNumber(final int randomNumber) {
+        this.randomNumber = randomNumber;
+    }
+}

+ 11 - 0
frameworks/Java/minijax/src/main/resources/META-INF/persistence.xml

@@ -0,0 +1,11 @@
+<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 http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd" version="2.0">
+    <persistence-unit name="minijax" transaction-type="RESOURCE_LOCAL">
+        <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
+        <class>com.techempower.minijax.Fortune</class>
+        <class>com.techempower.minijax.World</class>
+        <properties>
+            <property name="eclipselink.jdbc.batch-writing" value="JDBC" />
+            <property name="eclipselink.jdbc.cache-statements" value="true" />
+        </properties>
+    </persistence-unit>
+</persistence>

+ 10 - 0
frameworks/Java/minijax/src/main/resources/templates/error.mustache

@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Error</title>
+</head>
+<body>
+<h1>Error</h1>
+<p>{{props.message}}</p>
+</body>
+</html>

+ 14 - 0
frameworks/Java/minijax/src/main/resources/templates/fortunes.mustache

@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Fortunes</title>
+</head>
+<body>
+<table>
+<tr><th>id</th><th>message</th></tr>
+{{#fortunes}}
+<tr><td>{{id}}</td><td>{{message}}</td></tr>
+{{/fortunes}}
+</table>
+</body>
+</html>