SlideShare ist ein Scribd-Unternehmen logo
1 von 79
How to Generate Customized Java 8 Code
From Your Database
Per Minborg
CTO, Speedment, Inc
Emil Forslund
Developer, Speedment, Inc.
Every Decision a Developer Makes is a
Trade-off
The best code is
no code at all
Using Code Generation
• Makes the code efficient
and short
• Modifications are done
once and applied
everywhere
• Minimizes errors
• “DRY” (Don’t Repeat
Yourself) vs. ”WET” (We
Enjoy Typing)
• “Code your code”
But how can we control the generated code?
About Us
Per Minborg
• Founder of several IT companies
• Lives in Palo Alto
• 20 years of Java experience
• 15+ US patents
• Speaker at Java events
• Blog: Minborg’s Java Pot
Emil Forslund
• Java Developer
• Lives in Palo Alto
• 8 years of Java
experience
• Speaker at Java events
• Blog: Age of Java
Spire
• Speedment Open Source mascot
• Lives on GitHub
• 2 years of mascot experience
Agenda
• Problem Description
• Code Generation in Database Applications
• How Does it Work?
• Code Example
• Controlling the Code Generation
• Generate Custom Classes
• Add new Method to Existing Classes
• Code Example
• Additional Features
• Beyond Open Source
• Questions & Answers
Agenda
• Problem Description
• Code Generation in Database Applications
• How Does it Work?
• Code Example
• Controlling the Code Generation
• Generate Custom Classes
• Add new Method to Existing Classes
• Code Example
• Additional Features
• Beyond Open Source
• Questions & Answers
Do You Recognize This Code?
Class.forName("org.postgresql.Driver");
try (final Connection conn = DriverManager.getConnection(
"jdbc:postgresql://hostname:port/dbname",
"username",
"password")) {
// Database Logic Here...
}
Why Creating DB-Apps is So Time
Consuming
• Even trivial database operations require a
lot of boilerplate code
• Mixing SQL and Java is error-prone
• ORMs require you to write annotated
POJOs for every table
• Creating even a simple DB app can take
hours
Open-Source Project Speedment
• Stream ORM Java toolkit and
runtime
• Generate domain-model from the
database
• No need for complicated
configurations or setup
• All operations are type-safe
• Data is accessed using Java 8
Streams
• Business friendly Apache 2-
license
Speedment on GitHub
Speedment Workflow
customers.stream()
.filter(…)
.filter(…)
.map(…)
.collect(toList());
Step 1: Generate
Code
Step 2: Write Logic Step 3: Run
Application
Step 4: Iterate
Tool
Artifacts
• com.speedment:
• runtime
• generator
• tool
• speedment-maven-plugin
Agenda
• Problem Description
• Code Generation in Database Applications
• How Does it Work?
• Code Example
• Controlling the Code Generation
• Generate Custom Classes
• Add new Method to Existing Classes
• Code Example
• Additional Features
• Beyond Open Source
• Questions & Answers
So How Do the Generated Code Work?
• Code is organized based on database structure
• Hash-sums make sure user changes are not overwritten
If the DB structure changes, the code is
updated with the press of a button
Entities, Managers and Applications
• An Entity represents a row in a table
• Is a POJO
• Customer
• CustomerImpl
• A Manager represents a table
• Responsible for the CRUD operations
• CustomerManager
• CustomerManagerImpl
• An Application represents the entire project
• Responsible for configuration and settings
• SalesApplication
• SalesApplicationBuilder
Querying the Database using Streams
• Queries are expressed using
the standard Java 8 Stream
API
• Streams are analyzed to
produce high-performance
queries
Expressing Queries as Streams
customers.stream()
.filter(Customer.REGION.equal(Region.NORTH_AMERICA))
.filter(Customer.REGISTERED.greaterOrEqual(startOfYear))
.count();
Standard Stream
API
Generated Enum
Constants
Only 1 value is loaded from
DB
Full Type-Safety
SELECT COUNT('id') FROM 'customer'
WHERE 'customer'.'region' = ‘North America’
AND 'customer'.'registered' >= ‘2016-01-01’;
Querying the Database using Streams
SELECT * FROM 'customer'
REGION.equal(NORTH_AMERICA)
REGISTERED.greaterOrEqual(2016-01-01)
count()
Sourc
e
Filter
Filter
Term.
Pipeline
Querying the Database using Streams
SELECT * FROM 'customer'
WHERE 'customer'.'region' = ‘North America’
REGION.equal(NORTH_AMERICA)
REGISTERED.greaterOrEqual(2016-01-01)
count()
Sourc
e
Filter
Filter
Term.
Pipeline
Querying the Database using Streams
SELECT * FROM 'customer'
WHERE 'customer'.'region' = ‘North America’
AND 'customer'.'registered' >= ‘2016-01-01’;
REGISTERED.greaterOrEqual(2016-01-01)
count()
Sourc
e
Filter
Term.
Pipeline
Querying the Database using Streams
SELECT COUNT('id') FROM 'customer'
WHERE 'customer'.'region' = ‘North America’
AND 'customer'.'registered' >= ‘2016-01-01’;
count()
Sourc
e
Term.
Pipeline
Querying the Database using Streams
SELECT COUNT('id') FROM 'customer'
WHERE 'customer'.'region' = ‘North America’
AND 'customer'.'registered' >= ‘2016-01-01’;
Sourc
e
Pipeline
Expressing Queries as Streams
// Gets the second page of customers in North America
// sorted by name in the form of a JSON array
customers.stream()
.filter(REGION.equal(Region.NORTH_AMERICA))
.sorted(NAME.comparator())
.skip(10)
.limit(10) // JVM from here…
.collect(toJson(encode.allOf(customers)))
[
{”id”:11, ”name”: …},
{…},
…
]
Expressing Queries as Streams
// Supports parallelism on custom executors
// with full control of thread work item layout
customers.stream()
.parallel()
.filter(REGION.equal(Region.NORTH_AMERICA))
.forEach(expensiveOperatation());
Application Example
• Total Count of Customers
• Located in North America
• Registered This Year
Step 1: Getting Speedment using Maven
<plugin>
<groupId>com.speedment</groupId>
<artifactId>speedment-maven-plugin</artifactId>
<version>3.0.3</version>
</plugin>
Generate source files based on database
Step 2: Initializing Speedment
SalesApplication app = new SalesApplicationBuilder()
.withPassword("qwerty")
.build();
CustomerManager customers = app.getOrThrow(CustomerManager.class);
These classes are generated
automatically
Instance is configured using Builder-
pattern
A manager class is generated for every database table
Step 3: Querying
Region fromWhere = Region.NORTH_AMERICA;
Instant fromWhen = Instant.parse("2016-01-01");
long count = customers.stream()
.filter(Customer.REGION.equal(fromWhere))
.filter(Customer.REGISTERED.greaterOrEqual(fromWhen))
.count();
Step 4: Output
System.out.println(
"A total of %d customers from %s " +
"have registered this year.",
count, fromWhere.name()
);
Full Application
public static void main(String… args) {
SalesApplication app = new SalesApplicationBuilder()
.withPassword("qwerty")
.build();
CustomerManager customers = app.getOrThrow(CustomerManager.class);
Region fromWhere = Region.NORTH_AMERICA;
Instant fromWhen = Instant.parse("2016-01-01");
long count = customers.stream()
.filter(Customer.REGION.equal(fromWhere))
.filter(Customer.REGISTERED.greaterOrEqual(fromWhen))
.count();
System.out.println(
"A total of %d customers from %s " +
"have registered this year.",
count, fromWhere.name()
);
}
Output
Pers-MacBook-Pro:~ pemi$ java –jar salesapplication.jar
A total of 354 customers from NORTH_AMERICA have registered this year.
Agenda
• Problem Description
• Code Generation in Database Applications
• How Does it Work?
• Code Example
• Controlling the Code Generation
• Generate Custom Classes
• Add new Method to Existing Classes
• Code Example
• Additional Features
• Beyond Open Source
• Questions & Answers
Controlling the Code Generation
• So far we have queried a
database with streams
• We have used code generation
to create entities and managers
• Can it be used for more?
What is Available out of the Box?
• MVC oriented code generation
• Modular design
• Database domain model
• JSON configuration (DSL)
• Java language namer
• Translator and TranslatorDecorator
• Maven goals
• Type mappers
MVC Oriented Code Generation
• Model
• File, Class, Interface, Enum, Field, Method, Constructor,
Type, Generic, Annotation, …
• View
• Renders a model to Java (or another language)
• Set code style using custom views
• Control
• AutoImport, AutoEquals, AutoJavadoc, SetGetAdd, FinalParameters
• Write custom controllers to automate recurring tasks
MVC Oriented Code Generation
• Separation of concerns
• Code generation is type safe
• Catch errors compile time
• Discover methods directly in the IDE
• Reuse code segments and controllers
Modular Design
Database Domain Model
• Project
• Dbms
• Schema
• Table
• Column
• PrimaryKey
• ForeignKey
• Index
List<Table> tables = project.dbmses()
.flatMap(Dbms::schemas)
.flatMap(Schema::tables)
.collect(toList());
JSON Configuration (DSL)
{
"config" : {
"name" : "sales",
"dbmses" : [{
"name" : "db0",
"typeName" : "MySQL",
"ipAddress" : "127.0.0.1",
"username" : "root",
"schemas" : [{
"name" : "sales",
"tables" : [
{ "name" : "city" },
{ "name" : "salesperson" }
]
}]
}]
}
}
Java Language Namer
• Camel caser: converts from “some_db_name” to
“someDbName”
• Java naming conventions: user, User and USER
• Detects keywords like “final”,”static” and escapes them
• Detects collisions
• Pluralizer: bag → bags, entity → entities, fish → fish
Translator and TranslatorDecorator
• Translator
• Renders a DB entity like a Table to a new Class or an Interface
• TranslatorDecorator
• Modifies an existing Class or Interface
Maven Goals
• speedment:tool
• Launches the graphical tool
• Allows customization of configuration model
• Code generation
• speedment:generate
• Code generation without launching the tool
• speedment:reload
• Reloads database metadata without launching the tool
• speedment:clear
• Removes all the generated classes (except manual changes) without launching the
tool
Type Mappers
• Controls how columns are implemented
• Runtime conversion between Database and Java types
java.sql.Timestamp long
Generation vs. Templates
• Separation of concerns
• Easily change code style
• Minimize maintenance
• Maximize reusability
Generate a New Custom Class
1. Create a new Translator
2. Model how the new class
should look
3. Define a Plugin Class
4. Include it in project pom.xml
Example: Generate a Point class
Step 1: Create a New Translator Class
public class PointTranslator extends
AbstractJavaClassTranslator<Project, Class> {
public final static TranslatorKey<Project, Class> POINT_KEY =
new TranslatorKey.of(“generated_point", Class.class);
public PointTranslator(Project document) { super(document, Class::of); }
@Override
protected Class makeCodeGenModel(File file) {
return newBuilder(file, getClassOrInterfaceName())
.forEveryProject((clazz, project) -> {
// Generate Content Here
}).build();
}
@Override
protected String getClassOrInterfaceName() { return ”Point"; }
@Override
protected String getJavadocRepresentText() { return "A 2-dimensional coordinate."; }
}
Every translator is identified by a
TranslatorKey
Name of generated class
Javadoc
Called every time the translator is invoked
forEvery(Project|Dbms|Schema|Table|Column|
…)
Step 2: The makeCodeGenModel -
methodclazz.public_()
.add(Field.of(“x”, int.class)
.private_().final_()
)
.add(Field.of(“y”, int.class)
.private_().final_()
)
.add(Constructor.of().public_()
.add(Field.of(“x”, int.class))
.add(Field.of(“y”, int.class))
.add(“this.x = x;”,
“this.y = y;”
)
)
.add(Method.of(“getX”, int.class).public_()
.add(“return x;”)
)
.add(Method.of(“getY”, int.class).public_()
.add(“return y;”)
)
.call(new AutoEquals<>())
.call(new AutoToString<>());
Step 3: Define a Plugin Class
public class PointPlugin {
@ExecuteBefore(RESOLVED)
void install(CodeGenerationComponent codeGen) {
codeGen.put(
Project.class,
PointTranslator.POINT_KEY,
PointTranslator::new
);
}
}
The key defined earlier
Will execute when Speedment is
being initialized
How the translator is constructed
Step 4: Include it in Project pom.xml
<plugin>
<groupId>com.speedment</groupId>
<artifactId>speedment-maven-plugin</artifactId>
<version>3.0.3</version>
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>point-plugin</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
</dependencies>
<configuration>
<components>
<component>com.example.pointplugin.PointPlugin</component>
</components>
</configuration>
</plugin>
This tells Speedment to load the plugin
Make sure our plugin project is on the classpath
Execute
/**
* A 2-dimensional coordinate.
* <p>
* This file is safe to edit. It will not be overwritten by
the code generator.
*
* @author company
*/
public class Point {
private final int x;
private final int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
The following file is generated: public int hashCode() {
int hashCode = 31;
hashCode += 41 * x;
hashCode += 41 * y;
return hashCode;
}
public Boolean equals(Object other) {
if (this == other) return true;
else if (other == null) return false;
else if (!(other instanceof Point)) {
return false;
}
final Point point = (Point) other;
return x == point.x && y == point.y;
}
public String toString() {
return new StringBuilder(“Point{”)
.append(“x: “).append(x).append(“, “)
.append(“y: “).append(y).append(“}”);
}
}
A More Concrete Example
1. Create a new Translator
2. Model how the new class
should look
3. Define a Plugin Class
4. Include it in project pom.xml
Example: Generate an Enum of
tables in the database
Step 1: Create a New Translator Class
public class TableEnumTranslator extends
AbstractJavaClassTranslator<Project, Enum> {
public final static TranslatorKey<Project, Enum> TABLES_ENUM_KEY =
new TranslatorKey.of(“tables_enum", Enum.class);
public TableEnumTranslator(Project document) { super(document, Enum::of); }
@Override
protected Enum makeCodeGenModel(File file) {
return newBuilder(file, getClassOrInterfaceName())
.forEveryProject((clazz, project) -> {
// Generate Content Here
}).build();
}
@Override
protected String getClassOrInterfaceName() { return ”Tables"; }
@Override
protected String getJavadocRepresentText() { return "An enumeration of tables in the database."; }
}
Every translator is identified by a
TranslatorKey
Name of generated class
Javadoc
Called every time the translator is invoked
forEvery(Project|Dbms|Schema|Table|Column|
…)
Step 2: The makeCodeGenModel -
method
DocumentDbUtil.traverseOver(project, Table.class)
.map(Table::getJavaName)
.map(getSupport().namer()::javaStaticFieldName)
.sorted()
.map(EnumConstant::of)
.forEachOrdered(clazz::add);
Step 3: Define a Plugin Class
public class TableEnumPlugin {
@ExecuteBefore(RESOLVED)
protected void install(CodeGenerationComponent codeGen) {
codeGen.put(
Project.class,
TableEnumTranslator.TABLES_ENUM_KEY,
TableEnumTranslator::new
);
}
}
Step 4: Include it in Project pom.xml
<plugin>
<groupId>com.speedment</groupId>
<artifactId>speedment-maven-plugin</artifactId>
<version>3.0.3</version>
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>table-enum-plugin</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
</dependencies>
<configuration>
<components>
<component>com.example.tableenumplugin.TableEnumPlugin</component>
</components>
</configuration>
</plugin>
This tells Speedment to load the plugin
Make sure our plugin project is on the
classpath
Execute
/**
* An enumeration of tables in the database.
* <p>
* This file is safe to edit. It will not be overwritten by the code generator.
*
* @author company
*/
enum Tables {
CITY, SALESPERSON;
}
The following file is generated:
Generate all the Things
• Gson Adapters
• Spring Configuration Files
• REST Controllers
• and much more…
Ext Speeder
Agenda
• Problem Description
• Code Generation in Database Applications
• How Does it Work?
• Code Example
• Controlling the Code Generation
• Generate Custom Classes
• Add new Method to Existing Classes
• Code Example
• Additional Features
• Beyond Open Source
• Questions & Answers
Add New Method to Existing Classes
• So far we have
• Queried a database with generated
classes
• Generated a custom class
• How do we modify the existing
generation of classes?
Add New Method to Existing Classes
• Fit Into Existing Class Hierarchy
• Change Naming Conventions
• Optimize Internal Implementations
• Add Custom Methods
Add New Method to Existing Classes
Example: Add a getColumnCount
method to generated managers
1. Create a new
TranslatorDecorator class
2. Write code generation logic
3. Add it to Speedment
Agenda
• Problem Description
• Code Generation in Database Applications
• How Does it Work?
• Code Example
• Controlling the Code Generation
• Generate Custom Classes
• Add new Method to Existing Classes
• Code Example
• Additional Features
• Beyond Open Source
• Questions & Answers
Step 1: Creating a New Decorator Class
public class ColumnCountDecorator implements TranslatorDecorator<Table, Interface> {
@Override
public void apply(JavaClassTranslator<Table, Interface> translator) {
translator.onMake(builder -> {
builder.forEveryTable((intrf, table) -> {
// Code generation logic goes here
});
});
}
}
Step 2: Write Code Generation Logic
int columnCount = table.columns().count();
intrf.add(Method.of("getColumnCount", int.class)
.default_()
.set(Javadoc.of("Returns the number of columns in this table.")
.add(RETURN.setValue("the column count"))
)
.add("return " + columnCount + ";")
);
Step 3: Add it to Speedment
public final class TableEnumPlugin {
@ExecuteBefore(RESOLVED)
protected void install(CodeGenerationComponent codeGen) {
codeGen.put(
Project.class,
TableEnumTranslator.TABLES_ENUM_KEY,
TableEnumTranslator::new
);
codeGen.add(
Table.class,
StandardTranslatorKey.GENERATED_MANAGER,
new ColumnCountDecorator()
);
}
}
Modify an existing translator key
Our new decorator
The same plugin class as we
created earlier
Execute
When the project is
regenerated, a new method is
added to each manager
Agenda
• Problem Description
• Code Generation in Database Applications
• How Does it Work?
• Code Example
• Controlling the Code Generation
• Generate Custom Classes
• Add new Method to Existing Classes
• Code Example
• Additional Features
• Beyond Open Source
• Questions & Answers
Additional Features
• Add GUI Tool components for
custom configuration
• Extend the JSON DSL
dynamically with plugins
• Automate your build
environment with Maven
• Add custom data type
mappers
Additional Features
• Plugin a custom namer
• Generate classes that are related to other domain models
• Generate classes for other languages
• Style the GUI Tool
Database Connectors
Open Source
• MySQL
• PostgreSQL
• MariaDB
Enterprise
• Oracle
• Microsoft SQL server
• DB2
• AS400
Agenda
• Problem Description
• Code Generation in Database Applications
• How Does it Work?
• Code Example
• Controlling the Code Generation
• Generate Custom Classes
• Add new Method to Existing Classes
• Code Example
• Additional Features
• Beyond Open Source
• Questions & Answers
Beyond Open-Source
• Speedment Enterprise
• Run your database queries orders of magnitude faster!
• 10x, 100x, 1 000x, 10 000x, …
• Use the same Stream API
How is This Possible?
• No changes to user-written code
• Alternative stream source
• Data is stored in-memory
• Generates optimized serializers
for offheap storage
In-JVM-Memory, JMH Benchmarks(*)
Benchmark Mode Cnt Score Error Units
SpeedmentBenchmark.findStartsWith avgt 200 ≈ 10⁻⁵ s/op
SpeedmentBenchmark.findStartsWithSql avgt 200 ≈ 10⁻⁴ s/op
SpeedmentBenchmark.join avgt 200 0.476 ± 0.005 s/op
SpeedmentBenchmark.joinSql avgt 200 5.174 ± 0.010 s/op
SpeedmentBenchmark.sort avgt 200 ≈ 10⁻⁶ s/op
SpeedmentBenchmark.sortSql avgt 200 ≈ 10⁻⁴ s/op
SpeedmentBenchmark.scrollSorted avgt 200 ≈ 10⁻⁵ s/op
SpeedmentBenchmark.scrollSortedSql avgt 200 24.661 ± 0.670 s/op
SpeedmentBenchmark.count avgt 180 ≈ 10⁻⁸ s/op
SpeedmentBenchmark.countSql avgt 200 5.143 ± 0.012 s/op
(*) Preliminary results, Mac Book Pro, 2.2 GHz i7, 16GB, MySQL 5.7.16 standard
with indexes on all relevant columns.
10x
>10x
100x
2,000,000x
500,000,000x
Speedment Enterprise Example
Courtesy of Extremely Heavy Industries
Free Enterprise Trial
Today we have released version 1.1.1
Get a free trial! Leave your contact information.
Q&A
www.speedment.org
github.com/speedment/speedment
@speedment
www.speedment.com
Linkedin:
Per Minborg
Emil Forslund

Weitere ähnliche Inhalte

Was ist angesagt?

The Future of Plugin Dev
The Future of Plugin DevThe Future of Plugin Dev
The Future of Plugin DevBrandon Kelly
 
2/15/2012 - Wrapping Your Head Around the SharePoint Beast
2/15/2012 - Wrapping Your Head Around the SharePoint Beast2/15/2012 - Wrapping Your Head Around the SharePoint Beast
2/15/2012 - Wrapping Your Head Around the SharePoint BeastMark Rackley
 
Intro to .NET for Government Developers
Intro to .NET for Government DevelopersIntro to .NET for Government Developers
Intro to .NET for Government DevelopersFrank La Vigne
 
SPTechCon - Share point and jquery essentials
SPTechCon - Share point and jquery essentialsSPTechCon - Share point and jquery essentials
SPTechCon - Share point and jquery essentialsMark Rackley
 
Java EE revisits design patterns
Java EE revisits design patterns Java EE revisits design patterns
Java EE revisits design patterns Alex Theedom
 
Apache Cayenne: a Java ORM Alternative
Apache Cayenne: a Java ORM AlternativeApache Cayenne: a Java ORM Alternative
Apache Cayenne: a Java ORM AlternativeAndrus Adamchik
 
The Magic Revealed: Four Real-World Examples of Using the Client Object Model...
The Magic Revealed: Four Real-World Examples of Using the Client Object Model...The Magic Revealed: Four Real-World Examples of Using the Client Object Model...
The Magic Revealed: Four Real-World Examples of Using the Client Object Model...SPTechCon
 
Play Framework and Activator
Play Framework and ActivatorPlay Framework and Activator
Play Framework and ActivatorKevin Webber
 
HTML5 and CSS3 refresher
HTML5 and CSS3 refresherHTML5 and CSS3 refresher
HTML5 and CSS3 refresherIvano Malavolta
 
Using Play Framework 2 in production
Using Play Framework 2 in productionUsing Play Framework 2 in production
Using Play Framework 2 in productionChristian Papauschek
 
Getting Started with the OpenNTF Domino API
Getting Started with the OpenNTF Domino APIGetting Started with the OpenNTF Domino API
Getting Started with the OpenNTF Domino APITeamstudio
 
D2W Stateful Controllers
D2W Stateful ControllersD2W Stateful Controllers
D2W Stateful ControllersWO Community
 
Building search app with ElasticSearch
Building search app with ElasticSearchBuilding search app with ElasticSearch
Building search app with ElasticSearchLukas Vlcek
 
HTML5: the new frontier of the web
HTML5: the new frontier of the webHTML5: the new frontier of the web
HTML5: the new frontier of the webIvano Malavolta
 
SharePoint Saturday St. Louis - SharePoint & jQuery
SharePoint Saturday St. Louis - SharePoint & jQuerySharePoint Saturday St. Louis - SharePoint & jQuery
SharePoint Saturday St. Louis - SharePoint & jQueryMark Rackley
 
Test driven development v1.0
Test driven development v1.0Test driven development v1.0
Test driven development v1.0Ganesh Kondal
 

Was ist angesagt? (20)

The Future of Plugin Dev
The Future of Plugin DevThe Future of Plugin Dev
The Future of Plugin Dev
 
Appengine Nljug
Appengine NljugAppengine Nljug
Appengine Nljug
 
2/15/2012 - Wrapping Your Head Around the SharePoint Beast
2/15/2012 - Wrapping Your Head Around the SharePoint Beast2/15/2012 - Wrapping Your Head Around the SharePoint Beast
2/15/2012 - Wrapping Your Head Around the SharePoint Beast
 
Intro to .NET for Government Developers
Intro to .NET for Government DevelopersIntro to .NET for Government Developers
Intro to .NET for Government Developers
 
SPTechCon - Share point and jquery essentials
SPTechCon - Share point and jquery essentialsSPTechCon - Share point and jquery essentials
SPTechCon - Share point and jquery essentials
 
Java EE revisits design patterns
Java EE revisits design patterns Java EE revisits design patterns
Java EE revisits design patterns
 
RESTful Services
RESTful ServicesRESTful Services
RESTful Services
 
Apache Cayenne: a Java ORM Alternative
Apache Cayenne: a Java ORM AlternativeApache Cayenne: a Java ORM Alternative
Apache Cayenne: a Java ORM Alternative
 
The Magic Revealed: Four Real-World Examples of Using the Client Object Model...
The Magic Revealed: Four Real-World Examples of Using the Client Object Model...The Magic Revealed: Four Real-World Examples of Using the Client Object Model...
The Magic Revealed: Four Real-World Examples of Using the Client Object Model...
 
Play Framework and Activator
Play Framework and ActivatorPlay Framework and Activator
Play Framework and Activator
 
HTML5 and CSS3 refresher
HTML5 and CSS3 refresherHTML5 and CSS3 refresher
HTML5 and CSS3 refresher
 
Node and Azure
Node and AzureNode and Azure
Node and Azure
 
Using Play Framework 2 in production
Using Play Framework 2 in productionUsing Play Framework 2 in production
Using Play Framework 2 in production
 
Getting Started with the OpenNTF Domino API
Getting Started with the OpenNTF Domino APIGetting Started with the OpenNTF Domino API
Getting Started with the OpenNTF Domino API
 
[2015/2016] JavaScript
[2015/2016] JavaScript[2015/2016] JavaScript
[2015/2016] JavaScript
 
D2W Stateful Controllers
D2W Stateful ControllersD2W Stateful Controllers
D2W Stateful Controllers
 
Building search app with ElasticSearch
Building search app with ElasticSearchBuilding search app with ElasticSearch
Building search app with ElasticSearch
 
HTML5: the new frontier of the web
HTML5: the new frontier of the webHTML5: the new frontier of the web
HTML5: the new frontier of the web
 
SharePoint Saturday St. Louis - SharePoint & jQuery
SharePoint Saturday St. Louis - SharePoint & jQuerySharePoint Saturday St. Louis - SharePoint & jQuery
SharePoint Saturday St. Louis - SharePoint & jQuery
 
Test driven development v1.0
Test driven development v1.0Test driven development v1.0
Test driven development v1.0
 

Ähnlich wie Silicon Valley JUG - How to generate customized java 8 code from your database

JavaOne2016 - How to Generate Customized Java 8 Code from Your Database [TUT4...
JavaOne2016 - How to Generate Customized Java 8 Code from Your Database [TUT4...JavaOne2016 - How to Generate Customized Java 8 Code from Your Database [TUT4...
JavaOne2016 - How to Generate Customized Java 8 Code from Your Database [TUT4...Speedment, Inc.
 
SenchaCon 2016 - How to Auto Generate a Back-end in Minutes
SenchaCon 2016 - How to Auto Generate a Back-end in MinutesSenchaCon 2016 - How to Auto Generate a Back-end in Minutes
SenchaCon 2016 - How to Auto Generate a Back-end in MinutesMalin Weiss
 
SenchaCon 2016 - How to Auto Generate a Back-end in Minutes
SenchaCon 2016 - How to Auto Generate a Back-end in MinutesSenchaCon 2016 - How to Auto Generate a Back-end in Minutes
SenchaCon 2016 - How to Auto Generate a Back-end in MinutesSpeedment, Inc.
 
SenchaCon 2016: How to Auto Generate a Back-end in Minutes - Per Minborg, Emi...
SenchaCon 2016: How to Auto Generate a Back-end in Minutes - Per Minborg, Emi...SenchaCon 2016: How to Auto Generate a Back-end in Minutes - Per Minborg, Emi...
SenchaCon 2016: How to Auto Generate a Back-end in Minutes - Per Minborg, Emi...Sencha
 
Intro to node and mongodb 1
Intro to node and mongodb   1Intro to node and mongodb   1
Intro to node and mongodb 1Mohammad Qureshi
 
Quick start with AngularJS
Quick start with AngularJSQuick start with AngularJS
Quick start with AngularJSIuliia Baranova
 
Web Development using Ruby on Rails
Web Development using Ruby on RailsWeb Development using Ruby on Rails
Web Development using Ruby on RailsAvi Kedar
 
OrigoDB - take the red pill
OrigoDB - take the red pillOrigoDB - take the red pill
OrigoDB - take the red pillRobert Friberg
 
How to Contribute to Apache Usergrid
How to Contribute to Apache UsergridHow to Contribute to Apache Usergrid
How to Contribute to Apache UsergridDavid M. Johnson
 
Tech io spa_angularjs_20130814_v0.9.5
Tech io spa_angularjs_20130814_v0.9.5Tech io spa_angularjs_20130814_v0.9.5
Tech io spa_angularjs_20130814_v0.9.5Ganesh Kondal
 
Database continuous integration, unit test and functional test
Database continuous integration, unit test and functional testDatabase continuous integration, unit test and functional test
Database continuous integration, unit test and functional testHarry Zheng
 
Managing Millions of Tests Using Databricks
Managing Millions of Tests Using DatabricksManaging Millions of Tests Using Databricks
Managing Millions of Tests Using DatabricksDatabricks
 
Build a game with javascript (april 2017)
Build a game with javascript (april 2017)Build a game with javascript (april 2017)
Build a game with javascript (april 2017)Thinkful
 
WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...Fabio Franzini
 
Python - A Comprehensive Programming Language
Python - A Comprehensive Programming LanguagePython - A Comprehensive Programming Language
Python - A Comprehensive Programming LanguageTsungWei Hu
 
AngularJS 1.x - your first application (problems and solutions)
AngularJS 1.x - your first application (problems and solutions)AngularJS 1.x - your first application (problems and solutions)
AngularJS 1.x - your first application (problems and solutions)Igor Talevski
 
Masterin Large Scale Java Script Applications
Masterin Large Scale Java Script ApplicationsMasterin Large Scale Java Script Applications
Masterin Large Scale Java Script ApplicationsFabian Jakobs
 

Ähnlich wie Silicon Valley JUG - How to generate customized java 8 code from your database (20)

JavaOne2016 - How to Generate Customized Java 8 Code from Your Database [TUT4...
JavaOne2016 - How to Generate Customized Java 8 Code from Your Database [TUT4...JavaOne2016 - How to Generate Customized Java 8 Code from Your Database [TUT4...
JavaOne2016 - How to Generate Customized Java 8 Code from Your Database [TUT4...
 
SenchaCon 2016 - How to Auto Generate a Back-end in Minutes
SenchaCon 2016 - How to Auto Generate a Back-end in MinutesSenchaCon 2016 - How to Auto Generate a Back-end in Minutes
SenchaCon 2016 - How to Auto Generate a Back-end in Minutes
 
SenchaCon 2016 - How to Auto Generate a Back-end in Minutes
SenchaCon 2016 - How to Auto Generate a Back-end in MinutesSenchaCon 2016 - How to Auto Generate a Back-end in Minutes
SenchaCon 2016 - How to Auto Generate a Back-end in Minutes
 
SenchaCon 2016: How to Auto Generate a Back-end in Minutes - Per Minborg, Emi...
SenchaCon 2016: How to Auto Generate a Back-end in Minutes - Per Minborg, Emi...SenchaCon 2016: How to Auto Generate a Back-end in Minutes - Per Minborg, Emi...
SenchaCon 2016: How to Auto Generate a Back-end in Minutes - Per Minborg, Emi...
 
Intro to node and mongodb 1
Intro to node and mongodb   1Intro to node and mongodb   1
Intro to node and mongodb 1
 
Quick start with AngularJS
Quick start with AngularJSQuick start with AngularJS
Quick start with AngularJS
 
Web Development using Ruby on Rails
Web Development using Ruby on RailsWeb Development using Ruby on Rails
Web Development using Ruby on Rails
 
OrigoDB - take the red pill
OrigoDB - take the red pillOrigoDB - take the red pill
OrigoDB - take the red pill
 
How to Contribute to Apache Usergrid
How to Contribute to Apache UsergridHow to Contribute to Apache Usergrid
How to Contribute to Apache Usergrid
 
Tech io spa_angularjs_20130814_v0.9.5
Tech io spa_angularjs_20130814_v0.9.5Tech io spa_angularjs_20130814_v0.9.5
Tech io spa_angularjs_20130814_v0.9.5
 
Database continuous integration, unit test and functional test
Database continuous integration, unit test and functional testDatabase continuous integration, unit test and functional test
Database continuous integration, unit test and functional test
 
DOTNET8.pptx
DOTNET8.pptxDOTNET8.pptx
DOTNET8.pptx
 
Managing Millions of Tests Using Databricks
Managing Millions of Tests Using DatabricksManaging Millions of Tests Using Databricks
Managing Millions of Tests Using Databricks
 
Build a game with javascript (april 2017)
Build a game with javascript (april 2017)Build a game with javascript (april 2017)
Build a game with javascript (april 2017)
 
WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...WebNet Conference 2012 - Designing complex applications using html5 and knock...
WebNet Conference 2012 - Designing complex applications using html5 and knock...
 
Python - A Comprehensive Programming Language
Python - A Comprehensive Programming LanguagePython - A Comprehensive Programming Language
Python - A Comprehensive Programming Language
 
05 entity framework
05 entity framework05 entity framework
05 entity framework
 
AngularJS 1.x - your first application (problems and solutions)
AngularJS 1.x - your first application (problems and solutions)AngularJS 1.x - your first application (problems and solutions)
AngularJS 1.x - your first application (problems and solutions)
 
Masterin Large Scale Java Script Applications
Masterin Large Scale Java Script ApplicationsMasterin Large Scale Java Script Applications
Masterin Large Scale Java Script Applications
 
Grails 101
Grails 101Grails 101
Grails 101
 

Mehr von Speedment, Inc.

How to generate customized java 8 code from your database
How to generate customized java 8 code from your databaseHow to generate customized java 8 code from your database
How to generate customized java 8 code from your databaseSpeedment, Inc.
 
SenchaCon Roadshow Irvine 2017
SenchaCon Roadshow Irvine 2017SenchaCon Roadshow Irvine 2017
SenchaCon Roadshow Irvine 2017Speedment, Inc.
 
NYJavaSIG - Big Data Microservices w/ Speedment
NYJavaSIG - Big Data Microservices w/ SpeedmentNYJavaSIG - Big Data Microservices w/ Speedment
NYJavaSIG - Big Data Microservices w/ SpeedmentSpeedment, Inc.
 
JavaOne2016 - Microservices: Terabytes in Microseconds [CON4516]
JavaOne2016 - Microservices: Terabytes in Microseconds [CON4516]JavaOne2016 - Microservices: Terabytes in Microseconds [CON4516]
JavaOne2016 - Microservices: Terabytes in Microseconds [CON4516]Speedment, Inc.
 
DZone Java 8 Block Buster: Query Databases Using Streams
DZone Java 8 Block Buster: Query Databases Using StreamsDZone Java 8 Block Buster: Query Databases Using Streams
DZone Java 8 Block Buster: Query Databases Using StreamsSpeedment, Inc.
 
Speed-up Your Big Data Applications with Sencha and Speedment
Speed-up Your Big Data Applications with Sencha and SpeedmentSpeed-up Your Big Data Applications with Sencha and Speedment
Speed-up Your Big Data Applications with Sencha and SpeedmentSpeedment, Inc.
 
Speedment & Sencha at Oracle Open World 2015
Speedment & Sencha at Oracle Open World 2015Speedment & Sencha at Oracle Open World 2015
Speedment & Sencha at Oracle Open World 2015Speedment, Inc.
 
Java one2015 - Work With Hundreds of Hot Terabytes in JVMs
Java one2015 - Work With Hundreds of Hot Terabytes in JVMsJava one2015 - Work With Hundreds of Hot Terabytes in JVMs
Java one2015 - Work With Hundreds of Hot Terabytes in JVMsSpeedment, Inc.
 
eXtreme Tuesday Club at Pivotal Labs ft. Speemdnet / San Francisco - SEP 2015
eXtreme Tuesday Club at Pivotal Labs ft. Speemdnet / San Francisco - SEP 2015eXtreme Tuesday Club at Pivotal Labs ft. Speemdnet / San Francisco - SEP 2015
eXtreme Tuesday Club at Pivotal Labs ft. Speemdnet / San Francisco - SEP 2015Speedment, Inc.
 
Speedment - Reactive programming for Java8
Speedment - Reactive programming for Java8Speedment - Reactive programming for Java8
Speedment - Reactive programming for Java8Speedment, Inc.
 
SAP Open Source meetup/Speedment - Palo Alto 2015
SAP Open Source meetup/Speedment - Palo Alto 2015SAP Open Source meetup/Speedment - Palo Alto 2015
SAP Open Source meetup/Speedment - Palo Alto 2015Speedment, Inc.
 

Mehr von Speedment, Inc. (12)

How to generate customized java 8 code from your database
How to generate customized java 8 code from your databaseHow to generate customized java 8 code from your database
How to generate customized java 8 code from your database
 
SenchaCon Roadshow Irvine 2017
SenchaCon Roadshow Irvine 2017SenchaCon Roadshow Irvine 2017
SenchaCon Roadshow Irvine 2017
 
NYJavaSIG - Big Data Microservices w/ Speedment
NYJavaSIG - Big Data Microservices w/ SpeedmentNYJavaSIG - Big Data Microservices w/ Speedment
NYJavaSIG - Big Data Microservices w/ Speedment
 
JavaOne2016 - Microservices: Terabytes in Microseconds [CON4516]
JavaOne2016 - Microservices: Terabytes in Microseconds [CON4516]JavaOne2016 - Microservices: Terabytes in Microseconds [CON4516]
JavaOne2016 - Microservices: Terabytes in Microseconds [CON4516]
 
DZone Java 8 Block Buster: Query Databases Using Streams
DZone Java 8 Block Buster: Query Databases Using StreamsDZone Java 8 Block Buster: Query Databases Using Streams
DZone Java 8 Block Buster: Query Databases Using Streams
 
Speed-up Your Big Data Applications with Sencha and Speedment
Speed-up Your Big Data Applications with Sencha and SpeedmentSpeed-up Your Big Data Applications with Sencha and Speedment
Speed-up Your Big Data Applications with Sencha and Speedment
 
Speedment & Sencha at Oracle Open World 2015
Speedment & Sencha at Oracle Open World 2015Speedment & Sencha at Oracle Open World 2015
Speedment & Sencha at Oracle Open World 2015
 
Java one2015 - Work With Hundreds of Hot Terabytes in JVMs
Java one2015 - Work With Hundreds of Hot Terabytes in JVMsJava one2015 - Work With Hundreds of Hot Terabytes in JVMs
Java one2015 - Work With Hundreds of Hot Terabytes in JVMs
 
eXtreme Tuesday Club at Pivotal Labs ft. Speemdnet / San Francisco - SEP 2015
eXtreme Tuesday Club at Pivotal Labs ft. Speemdnet / San Francisco - SEP 2015eXtreme Tuesday Club at Pivotal Labs ft. Speemdnet / San Francisco - SEP 2015
eXtreme Tuesday Club at Pivotal Labs ft. Speemdnet / San Francisco - SEP 2015
 
Speedment - Reactive programming for Java8
Speedment - Reactive programming for Java8Speedment - Reactive programming for Java8
Speedment - Reactive programming for Java8
 
Java days gbg online
Java days gbg onlineJava days gbg online
Java days gbg online
 
SAP Open Source meetup/Speedment - Palo Alto 2015
SAP Open Source meetup/Speedment - Palo Alto 2015SAP Open Source meetup/Speedment - Palo Alto 2015
SAP Open Source meetup/Speedment - Palo Alto 2015
 

Kürzlich hochgeladen

Delhi Call Girls Punjabi Bagh 9711199171 ☎✔👌✔ Whatsapp Hard And Sexy Vip Call
Delhi Call Girls Punjabi Bagh 9711199171 ☎✔👌✔ Whatsapp Hard And Sexy Vip CallDelhi Call Girls Punjabi Bagh 9711199171 ☎✔👌✔ Whatsapp Hard And Sexy Vip Call
Delhi Call Girls Punjabi Bagh 9711199171 ☎✔👌✔ Whatsapp Hard And Sexy Vip Callshivangimorya083
 
Call Girls in Sarai Kale Khan Delhi 💯 Call Us 🔝9205541914 🔝( Delhi) Escorts S...
Call Girls in Sarai Kale Khan Delhi 💯 Call Us 🔝9205541914 🔝( Delhi) Escorts S...Call Girls in Sarai Kale Khan Delhi 💯 Call Us 🔝9205541914 🔝( Delhi) Escorts S...
Call Girls in Sarai Kale Khan Delhi 💯 Call Us 🔝9205541914 🔝( Delhi) Escorts S...Delhi Call girls
 
Introduction-to-Machine-Learning (1).pptx
Introduction-to-Machine-Learning (1).pptxIntroduction-to-Machine-Learning (1).pptx
Introduction-to-Machine-Learning (1).pptxfirstjob4
 
Log Analysis using OSSEC sasoasasasas.pptx
Log Analysis using OSSEC sasoasasasas.pptxLog Analysis using OSSEC sasoasasasas.pptx
Log Analysis using OSSEC sasoasasasas.pptxJohnnyPlasten
 
Mature dropshipping via API with DroFx.pptx
Mature dropshipping via API with DroFx.pptxMature dropshipping via API with DroFx.pptx
Mature dropshipping via API with DroFx.pptxolyaivanovalion
 
Schema on read is obsolete. Welcome metaprogramming..pdf
Schema on read is obsolete. Welcome metaprogramming..pdfSchema on read is obsolete. Welcome metaprogramming..pdf
Schema on read is obsolete. Welcome metaprogramming..pdfLars Albertsson
 
Digital Advertising Lecture for Advanced Digital & Social Media Strategy at U...
Digital Advertising Lecture for Advanced Digital & Social Media Strategy at U...Digital Advertising Lecture for Advanced Digital & Social Media Strategy at U...
Digital Advertising Lecture for Advanced Digital & Social Media Strategy at U...Valters Lauzums
 
Call Girls Indiranagar Just Call 👗 7737669865 👗 Top Class Call Girl Service B...
Call Girls Indiranagar Just Call 👗 7737669865 👗 Top Class Call Girl Service B...Call Girls Indiranagar Just Call 👗 7737669865 👗 Top Class Call Girl Service B...
Call Girls Indiranagar Just Call 👗 7737669865 👗 Top Class Call Girl Service B...amitlee9823
 
Data-Analysis for Chicago Crime Data 2023
Data-Analysis for Chicago Crime Data  2023Data-Analysis for Chicago Crime Data  2023
Data-Analysis for Chicago Crime Data 2023ymrp368
 
Edukaciniai dropshipping via API with DroFx
Edukaciniai dropshipping via API with DroFxEdukaciniai dropshipping via API with DroFx
Edukaciniai dropshipping via API with DroFxolyaivanovalion
 
VIP Model Call Girls Hinjewadi ( Pune ) Call ON 8005736733 Starting From 5K t...
VIP Model Call Girls Hinjewadi ( Pune ) Call ON 8005736733 Starting From 5K t...VIP Model Call Girls Hinjewadi ( Pune ) Call ON 8005736733 Starting From 5K t...
VIP Model Call Girls Hinjewadi ( Pune ) Call ON 8005736733 Starting From 5K t...SUHANI PANDEY
 
BigBuy dropshipping via API with DroFx.pptx
BigBuy dropshipping via API with DroFx.pptxBigBuy dropshipping via API with DroFx.pptx
BigBuy dropshipping via API with DroFx.pptxolyaivanovalion
 
Best VIP Call Girls Noida Sector 39 Call Me: 8448380779
Best VIP Call Girls Noida Sector 39 Call Me: 8448380779Best VIP Call Girls Noida Sector 39 Call Me: 8448380779
Best VIP Call Girls Noida Sector 39 Call Me: 8448380779Delhi Call girls
 
Discover Why Less is More in B2B Research
Discover Why Less is More in B2B ResearchDiscover Why Less is More in B2B Research
Discover Why Less is More in B2B Researchmichael115558
 
Midocean dropshipping via API with DroFx
Midocean dropshipping via API with DroFxMidocean dropshipping via API with DroFx
Midocean dropshipping via API with DroFxolyaivanovalion
 
Ravak dropshipping via API with DroFx.pptx
Ravak dropshipping via API with DroFx.pptxRavak dropshipping via API with DroFx.pptx
Ravak dropshipping via API with DroFx.pptxolyaivanovalion
 
April 2024 - Crypto Market Report's Analysis
April 2024 - Crypto Market Report's AnalysisApril 2024 - Crypto Market Report's Analysis
April 2024 - Crypto Market Report's Analysismanisha194592
 
Accredited-Transport-Cooperatives-Jan-2021-Web.pdf
Accredited-Transport-Cooperatives-Jan-2021-Web.pdfAccredited-Transport-Cooperatives-Jan-2021-Web.pdf
Accredited-Transport-Cooperatives-Jan-2021-Web.pdfadriantubila
 

Kürzlich hochgeladen (20)

Delhi Call Girls Punjabi Bagh 9711199171 ☎✔👌✔ Whatsapp Hard And Sexy Vip Call
Delhi Call Girls Punjabi Bagh 9711199171 ☎✔👌✔ Whatsapp Hard And Sexy Vip CallDelhi Call Girls Punjabi Bagh 9711199171 ☎✔👌✔ Whatsapp Hard And Sexy Vip Call
Delhi Call Girls Punjabi Bagh 9711199171 ☎✔👌✔ Whatsapp Hard And Sexy Vip Call
 
Call Girls in Sarai Kale Khan Delhi 💯 Call Us 🔝9205541914 🔝( Delhi) Escorts S...
Call Girls in Sarai Kale Khan Delhi 💯 Call Us 🔝9205541914 🔝( Delhi) Escorts S...Call Girls in Sarai Kale Khan Delhi 💯 Call Us 🔝9205541914 🔝( Delhi) Escorts S...
Call Girls in Sarai Kale Khan Delhi 💯 Call Us 🔝9205541914 🔝( Delhi) Escorts S...
 
Introduction-to-Machine-Learning (1).pptx
Introduction-to-Machine-Learning (1).pptxIntroduction-to-Machine-Learning (1).pptx
Introduction-to-Machine-Learning (1).pptx
 
Log Analysis using OSSEC sasoasasasas.pptx
Log Analysis using OSSEC sasoasasasas.pptxLog Analysis using OSSEC sasoasasasas.pptx
Log Analysis using OSSEC sasoasasasas.pptx
 
Mature dropshipping via API with DroFx.pptx
Mature dropshipping via API with DroFx.pptxMature dropshipping via API with DroFx.pptx
Mature dropshipping via API with DroFx.pptx
 
Schema on read is obsolete. Welcome metaprogramming..pdf
Schema on read is obsolete. Welcome metaprogramming..pdfSchema on read is obsolete. Welcome metaprogramming..pdf
Schema on read is obsolete. Welcome metaprogramming..pdf
 
Digital Advertising Lecture for Advanced Digital & Social Media Strategy at U...
Digital Advertising Lecture for Advanced Digital & Social Media Strategy at U...Digital Advertising Lecture for Advanced Digital & Social Media Strategy at U...
Digital Advertising Lecture for Advanced Digital & Social Media Strategy at U...
 
Call Girls Indiranagar Just Call 👗 7737669865 👗 Top Class Call Girl Service B...
Call Girls Indiranagar Just Call 👗 7737669865 👗 Top Class Call Girl Service B...Call Girls Indiranagar Just Call 👗 7737669865 👗 Top Class Call Girl Service B...
Call Girls Indiranagar Just Call 👗 7737669865 👗 Top Class Call Girl Service B...
 
Data-Analysis for Chicago Crime Data 2023
Data-Analysis for Chicago Crime Data  2023Data-Analysis for Chicago Crime Data  2023
Data-Analysis for Chicago Crime Data 2023
 
Sampling (random) method and Non random.ppt
Sampling (random) method and Non random.pptSampling (random) method and Non random.ppt
Sampling (random) method and Non random.ppt
 
Edukaciniai dropshipping via API with DroFx
Edukaciniai dropshipping via API with DroFxEdukaciniai dropshipping via API with DroFx
Edukaciniai dropshipping via API with DroFx
 
VIP Model Call Girls Hinjewadi ( Pune ) Call ON 8005736733 Starting From 5K t...
VIP Model Call Girls Hinjewadi ( Pune ) Call ON 8005736733 Starting From 5K t...VIP Model Call Girls Hinjewadi ( Pune ) Call ON 8005736733 Starting From 5K t...
VIP Model Call Girls Hinjewadi ( Pune ) Call ON 8005736733 Starting From 5K t...
 
BigBuy dropshipping via API with DroFx.pptx
BigBuy dropshipping via API with DroFx.pptxBigBuy dropshipping via API with DroFx.pptx
BigBuy dropshipping via API with DroFx.pptx
 
Abortion pills in Doha Qatar (+966572737505 ! Get Cytotec
Abortion pills in Doha Qatar (+966572737505 ! Get CytotecAbortion pills in Doha Qatar (+966572737505 ! Get Cytotec
Abortion pills in Doha Qatar (+966572737505 ! Get Cytotec
 
Best VIP Call Girls Noida Sector 39 Call Me: 8448380779
Best VIP Call Girls Noida Sector 39 Call Me: 8448380779Best VIP Call Girls Noida Sector 39 Call Me: 8448380779
Best VIP Call Girls Noida Sector 39 Call Me: 8448380779
 
Discover Why Less is More in B2B Research
Discover Why Less is More in B2B ResearchDiscover Why Less is More in B2B Research
Discover Why Less is More in B2B Research
 
Midocean dropshipping via API with DroFx
Midocean dropshipping via API with DroFxMidocean dropshipping via API with DroFx
Midocean dropshipping via API with DroFx
 
Ravak dropshipping via API with DroFx.pptx
Ravak dropshipping via API with DroFx.pptxRavak dropshipping via API with DroFx.pptx
Ravak dropshipping via API with DroFx.pptx
 
April 2024 - Crypto Market Report's Analysis
April 2024 - Crypto Market Report's AnalysisApril 2024 - Crypto Market Report's Analysis
April 2024 - Crypto Market Report's Analysis
 
Accredited-Transport-Cooperatives-Jan-2021-Web.pdf
Accredited-Transport-Cooperatives-Jan-2021-Web.pdfAccredited-Transport-Cooperatives-Jan-2021-Web.pdf
Accredited-Transport-Cooperatives-Jan-2021-Web.pdf
 

Silicon Valley JUG - How to generate customized java 8 code from your database

  • 1. How to Generate Customized Java 8 Code From Your Database Per Minborg CTO, Speedment, Inc Emil Forslund Developer, Speedment, Inc.
  • 2. Every Decision a Developer Makes is a Trade-off The best code is no code at all
  • 3. Using Code Generation • Makes the code efficient and short • Modifications are done once and applied everywhere • Minimizes errors • “DRY” (Don’t Repeat Yourself) vs. ”WET” (We Enjoy Typing) • “Code your code” But how can we control the generated code?
  • 4. About Us Per Minborg • Founder of several IT companies • Lives in Palo Alto • 20 years of Java experience • 15+ US patents • Speaker at Java events • Blog: Minborg’s Java Pot Emil Forslund • Java Developer • Lives in Palo Alto • 8 years of Java experience • Speaker at Java events • Blog: Age of Java Spire • Speedment Open Source mascot • Lives on GitHub • 2 years of mascot experience
  • 5. Agenda • Problem Description • Code Generation in Database Applications • How Does it Work? • Code Example • Controlling the Code Generation • Generate Custom Classes • Add new Method to Existing Classes • Code Example • Additional Features • Beyond Open Source • Questions & Answers
  • 6. Agenda • Problem Description • Code Generation in Database Applications • How Does it Work? • Code Example • Controlling the Code Generation • Generate Custom Classes • Add new Method to Existing Classes • Code Example • Additional Features • Beyond Open Source • Questions & Answers
  • 7. Do You Recognize This Code? Class.forName("org.postgresql.Driver"); try (final Connection conn = DriverManager.getConnection( "jdbc:postgresql://hostname:port/dbname", "username", "password")) { // Database Logic Here... }
  • 8. Why Creating DB-Apps is So Time Consuming • Even trivial database operations require a lot of boilerplate code • Mixing SQL and Java is error-prone • ORMs require you to write annotated POJOs for every table • Creating even a simple DB app can take hours
  • 9. Open-Source Project Speedment • Stream ORM Java toolkit and runtime • Generate domain-model from the database • No need for complicated configurations or setup • All operations are type-safe • Data is accessed using Java 8 Streams • Business friendly Apache 2- license
  • 11. Speedment Workflow customers.stream() .filter(…) .filter(…) .map(…) .collect(toList()); Step 1: Generate Code Step 2: Write Logic Step 3: Run Application Step 4: Iterate
  • 12. Tool
  • 13. Artifacts • com.speedment: • runtime • generator • tool • speedment-maven-plugin
  • 14. Agenda • Problem Description • Code Generation in Database Applications • How Does it Work? • Code Example • Controlling the Code Generation • Generate Custom Classes • Add new Method to Existing Classes • Code Example • Additional Features • Beyond Open Source • Questions & Answers
  • 15. So How Do the Generated Code Work? • Code is organized based on database structure • Hash-sums make sure user changes are not overwritten If the DB structure changes, the code is updated with the press of a button
  • 16. Entities, Managers and Applications • An Entity represents a row in a table • Is a POJO • Customer • CustomerImpl • A Manager represents a table • Responsible for the CRUD operations • CustomerManager • CustomerManagerImpl • An Application represents the entire project • Responsible for configuration and settings • SalesApplication • SalesApplicationBuilder
  • 17. Querying the Database using Streams • Queries are expressed using the standard Java 8 Stream API • Streams are analyzed to produce high-performance queries
  • 18. Expressing Queries as Streams customers.stream() .filter(Customer.REGION.equal(Region.NORTH_AMERICA)) .filter(Customer.REGISTERED.greaterOrEqual(startOfYear)) .count(); Standard Stream API Generated Enum Constants Only 1 value is loaded from DB Full Type-Safety SELECT COUNT('id') FROM 'customer' WHERE 'customer'.'region' = ‘North America’ AND 'customer'.'registered' >= ‘2016-01-01’;
  • 19. Querying the Database using Streams SELECT * FROM 'customer' REGION.equal(NORTH_AMERICA) REGISTERED.greaterOrEqual(2016-01-01) count() Sourc e Filter Filter Term. Pipeline
  • 20. Querying the Database using Streams SELECT * FROM 'customer' WHERE 'customer'.'region' = ‘North America’ REGION.equal(NORTH_AMERICA) REGISTERED.greaterOrEqual(2016-01-01) count() Sourc e Filter Filter Term. Pipeline
  • 21. Querying the Database using Streams SELECT * FROM 'customer' WHERE 'customer'.'region' = ‘North America’ AND 'customer'.'registered' >= ‘2016-01-01’; REGISTERED.greaterOrEqual(2016-01-01) count() Sourc e Filter Term. Pipeline
  • 22. Querying the Database using Streams SELECT COUNT('id') FROM 'customer' WHERE 'customer'.'region' = ‘North America’ AND 'customer'.'registered' >= ‘2016-01-01’; count() Sourc e Term. Pipeline
  • 23. Querying the Database using Streams SELECT COUNT('id') FROM 'customer' WHERE 'customer'.'region' = ‘North America’ AND 'customer'.'registered' >= ‘2016-01-01’; Sourc e Pipeline
  • 24. Expressing Queries as Streams // Gets the second page of customers in North America // sorted by name in the form of a JSON array customers.stream() .filter(REGION.equal(Region.NORTH_AMERICA)) .sorted(NAME.comparator()) .skip(10) .limit(10) // JVM from here… .collect(toJson(encode.allOf(customers))) [ {”id”:11, ”name”: …}, {…}, … ]
  • 25. Expressing Queries as Streams // Supports parallelism on custom executors // with full control of thread work item layout customers.stream() .parallel() .filter(REGION.equal(Region.NORTH_AMERICA)) .forEach(expensiveOperatation());
  • 26. Application Example • Total Count of Customers • Located in North America • Registered This Year
  • 27. Step 1: Getting Speedment using Maven <plugin> <groupId>com.speedment</groupId> <artifactId>speedment-maven-plugin</artifactId> <version>3.0.3</version> </plugin> Generate source files based on database
  • 28. Step 2: Initializing Speedment SalesApplication app = new SalesApplicationBuilder() .withPassword("qwerty") .build(); CustomerManager customers = app.getOrThrow(CustomerManager.class); These classes are generated automatically Instance is configured using Builder- pattern A manager class is generated for every database table
  • 29. Step 3: Querying Region fromWhere = Region.NORTH_AMERICA; Instant fromWhen = Instant.parse("2016-01-01"); long count = customers.stream() .filter(Customer.REGION.equal(fromWhere)) .filter(Customer.REGISTERED.greaterOrEqual(fromWhen)) .count();
  • 30. Step 4: Output System.out.println( "A total of %d customers from %s " + "have registered this year.", count, fromWhere.name() );
  • 31. Full Application public static void main(String… args) { SalesApplication app = new SalesApplicationBuilder() .withPassword("qwerty") .build(); CustomerManager customers = app.getOrThrow(CustomerManager.class); Region fromWhere = Region.NORTH_AMERICA; Instant fromWhen = Instant.parse("2016-01-01"); long count = customers.stream() .filter(Customer.REGION.equal(fromWhere)) .filter(Customer.REGISTERED.greaterOrEqual(fromWhen)) .count(); System.out.println( "A total of %d customers from %s " + "have registered this year.", count, fromWhere.name() ); }
  • 32. Output Pers-MacBook-Pro:~ pemi$ java –jar salesapplication.jar A total of 354 customers from NORTH_AMERICA have registered this year.
  • 33. Agenda • Problem Description • Code Generation in Database Applications • How Does it Work? • Code Example • Controlling the Code Generation • Generate Custom Classes • Add new Method to Existing Classes • Code Example • Additional Features • Beyond Open Source • Questions & Answers
  • 34. Controlling the Code Generation • So far we have queried a database with streams • We have used code generation to create entities and managers • Can it be used for more?
  • 35. What is Available out of the Box? • MVC oriented code generation • Modular design • Database domain model • JSON configuration (DSL) • Java language namer • Translator and TranslatorDecorator • Maven goals • Type mappers
  • 36. MVC Oriented Code Generation • Model • File, Class, Interface, Enum, Field, Method, Constructor, Type, Generic, Annotation, … • View • Renders a model to Java (or another language) • Set code style using custom views • Control • AutoImport, AutoEquals, AutoJavadoc, SetGetAdd, FinalParameters • Write custom controllers to automate recurring tasks
  • 37. MVC Oriented Code Generation • Separation of concerns • Code generation is type safe • Catch errors compile time • Discover methods directly in the IDE • Reuse code segments and controllers
  • 39. Database Domain Model • Project • Dbms • Schema • Table • Column • PrimaryKey • ForeignKey • Index List<Table> tables = project.dbmses() .flatMap(Dbms::schemas) .flatMap(Schema::tables) .collect(toList());
  • 40. JSON Configuration (DSL) { "config" : { "name" : "sales", "dbmses" : [{ "name" : "db0", "typeName" : "MySQL", "ipAddress" : "127.0.0.1", "username" : "root", "schemas" : [{ "name" : "sales", "tables" : [ { "name" : "city" }, { "name" : "salesperson" } ] }] }] } }
  • 41. Java Language Namer • Camel caser: converts from “some_db_name” to “someDbName” • Java naming conventions: user, User and USER • Detects keywords like “final”,”static” and escapes them • Detects collisions • Pluralizer: bag → bags, entity → entities, fish → fish
  • 42. Translator and TranslatorDecorator • Translator • Renders a DB entity like a Table to a new Class or an Interface • TranslatorDecorator • Modifies an existing Class or Interface
  • 43. Maven Goals • speedment:tool • Launches the graphical tool • Allows customization of configuration model • Code generation • speedment:generate • Code generation without launching the tool • speedment:reload • Reloads database metadata without launching the tool • speedment:clear • Removes all the generated classes (except manual changes) without launching the tool
  • 44. Type Mappers • Controls how columns are implemented • Runtime conversion between Database and Java types java.sql.Timestamp long
  • 45. Generation vs. Templates • Separation of concerns • Easily change code style • Minimize maintenance • Maximize reusability
  • 46. Generate a New Custom Class 1. Create a new Translator 2. Model how the new class should look 3. Define a Plugin Class 4. Include it in project pom.xml Example: Generate a Point class
  • 47. Step 1: Create a New Translator Class public class PointTranslator extends AbstractJavaClassTranslator<Project, Class> { public final static TranslatorKey<Project, Class> POINT_KEY = new TranslatorKey.of(“generated_point", Class.class); public PointTranslator(Project document) { super(document, Class::of); } @Override protected Class makeCodeGenModel(File file) { return newBuilder(file, getClassOrInterfaceName()) .forEveryProject((clazz, project) -> { // Generate Content Here }).build(); } @Override protected String getClassOrInterfaceName() { return ”Point"; } @Override protected String getJavadocRepresentText() { return "A 2-dimensional coordinate."; } } Every translator is identified by a TranslatorKey Name of generated class Javadoc Called every time the translator is invoked forEvery(Project|Dbms|Schema|Table|Column| …)
  • 48. Step 2: The makeCodeGenModel - methodclazz.public_() .add(Field.of(“x”, int.class) .private_().final_() ) .add(Field.of(“y”, int.class) .private_().final_() ) .add(Constructor.of().public_() .add(Field.of(“x”, int.class)) .add(Field.of(“y”, int.class)) .add(“this.x = x;”, “this.y = y;” ) ) .add(Method.of(“getX”, int.class).public_() .add(“return x;”) ) .add(Method.of(“getY”, int.class).public_() .add(“return y;”) ) .call(new AutoEquals<>()) .call(new AutoToString<>());
  • 49. Step 3: Define a Plugin Class public class PointPlugin { @ExecuteBefore(RESOLVED) void install(CodeGenerationComponent codeGen) { codeGen.put( Project.class, PointTranslator.POINT_KEY, PointTranslator::new ); } } The key defined earlier Will execute when Speedment is being initialized How the translator is constructed
  • 50. Step 4: Include it in Project pom.xml <plugin> <groupId>com.speedment</groupId> <artifactId>speedment-maven-plugin</artifactId> <version>3.0.3</version> <dependencies> <dependency> <groupId>com.example</groupId> <artifactId>point-plugin</artifactId> <version>1.0.0-SNAPSHOT</version> </dependency> </dependencies> <configuration> <components> <component>com.example.pointplugin.PointPlugin</component> </components> </configuration> </plugin> This tells Speedment to load the plugin Make sure our plugin project is on the classpath
  • 51. Execute /** * A 2-dimensional coordinate. * <p> * This file is safe to edit. It will not be overwritten by the code generator. * * @author company */ public class Point { private final int x; private final int y; public Point(int x, int y) { this.x = x; this.y = y; } public int getX() { return x; } public int getY() { return y; } The following file is generated: public int hashCode() { int hashCode = 31; hashCode += 41 * x; hashCode += 41 * y; return hashCode; } public Boolean equals(Object other) { if (this == other) return true; else if (other == null) return false; else if (!(other instanceof Point)) { return false; } final Point point = (Point) other; return x == point.x && y == point.y; } public String toString() { return new StringBuilder(“Point{”) .append(“x: “).append(x).append(“, “) .append(“y: “).append(y).append(“}”); } }
  • 52. A More Concrete Example 1. Create a new Translator 2. Model how the new class should look 3. Define a Plugin Class 4. Include it in project pom.xml Example: Generate an Enum of tables in the database
  • 53. Step 1: Create a New Translator Class public class TableEnumTranslator extends AbstractJavaClassTranslator<Project, Enum> { public final static TranslatorKey<Project, Enum> TABLES_ENUM_KEY = new TranslatorKey.of(“tables_enum", Enum.class); public TableEnumTranslator(Project document) { super(document, Enum::of); } @Override protected Enum makeCodeGenModel(File file) { return newBuilder(file, getClassOrInterfaceName()) .forEveryProject((clazz, project) -> { // Generate Content Here }).build(); } @Override protected String getClassOrInterfaceName() { return ”Tables"; } @Override protected String getJavadocRepresentText() { return "An enumeration of tables in the database."; } } Every translator is identified by a TranslatorKey Name of generated class Javadoc Called every time the translator is invoked forEvery(Project|Dbms|Schema|Table|Column| …)
  • 54. Step 2: The makeCodeGenModel - method DocumentDbUtil.traverseOver(project, Table.class) .map(Table::getJavaName) .map(getSupport().namer()::javaStaticFieldName) .sorted() .map(EnumConstant::of) .forEachOrdered(clazz::add);
  • 55. Step 3: Define a Plugin Class public class TableEnumPlugin { @ExecuteBefore(RESOLVED) protected void install(CodeGenerationComponent codeGen) { codeGen.put( Project.class, TableEnumTranslator.TABLES_ENUM_KEY, TableEnumTranslator::new ); } }
  • 56. Step 4: Include it in Project pom.xml <plugin> <groupId>com.speedment</groupId> <artifactId>speedment-maven-plugin</artifactId> <version>3.0.3</version> <dependencies> <dependency> <groupId>com.example</groupId> <artifactId>table-enum-plugin</artifactId> <version>1.0.0-SNAPSHOT</version> </dependency> </dependencies> <configuration> <components> <component>com.example.tableenumplugin.TableEnumPlugin</component> </components> </configuration> </plugin> This tells Speedment to load the plugin Make sure our plugin project is on the classpath
  • 57. Execute /** * An enumeration of tables in the database. * <p> * This file is safe to edit. It will not be overwritten by the code generator. * * @author company */ enum Tables { CITY, SALESPERSON; } The following file is generated:
  • 58. Generate all the Things • Gson Adapters • Spring Configuration Files • REST Controllers • and much more…
  • 60. Agenda • Problem Description • Code Generation in Database Applications • How Does it Work? • Code Example • Controlling the Code Generation • Generate Custom Classes • Add new Method to Existing Classes • Code Example • Additional Features • Beyond Open Source • Questions & Answers
  • 61. Add New Method to Existing Classes • So far we have • Queried a database with generated classes • Generated a custom class • How do we modify the existing generation of classes?
  • 62. Add New Method to Existing Classes • Fit Into Existing Class Hierarchy • Change Naming Conventions • Optimize Internal Implementations • Add Custom Methods
  • 63. Add New Method to Existing Classes Example: Add a getColumnCount method to generated managers 1. Create a new TranslatorDecorator class 2. Write code generation logic 3. Add it to Speedment
  • 64. Agenda • Problem Description • Code Generation in Database Applications • How Does it Work? • Code Example • Controlling the Code Generation • Generate Custom Classes • Add new Method to Existing Classes • Code Example • Additional Features • Beyond Open Source • Questions & Answers
  • 65. Step 1: Creating a New Decorator Class public class ColumnCountDecorator implements TranslatorDecorator<Table, Interface> { @Override public void apply(JavaClassTranslator<Table, Interface> translator) { translator.onMake(builder -> { builder.forEveryTable((intrf, table) -> { // Code generation logic goes here }); }); } }
  • 66. Step 2: Write Code Generation Logic int columnCount = table.columns().count(); intrf.add(Method.of("getColumnCount", int.class) .default_() .set(Javadoc.of("Returns the number of columns in this table.") .add(RETURN.setValue("the column count")) ) .add("return " + columnCount + ";") );
  • 67. Step 3: Add it to Speedment public final class TableEnumPlugin { @ExecuteBefore(RESOLVED) protected void install(CodeGenerationComponent codeGen) { codeGen.put( Project.class, TableEnumTranslator.TABLES_ENUM_KEY, TableEnumTranslator::new ); codeGen.add( Table.class, StandardTranslatorKey.GENERATED_MANAGER, new ColumnCountDecorator() ); } } Modify an existing translator key Our new decorator The same plugin class as we created earlier
  • 68. Execute When the project is regenerated, a new method is added to each manager
  • 69. Agenda • Problem Description • Code Generation in Database Applications • How Does it Work? • Code Example • Controlling the Code Generation • Generate Custom Classes • Add new Method to Existing Classes • Code Example • Additional Features • Beyond Open Source • Questions & Answers
  • 70. Additional Features • Add GUI Tool components for custom configuration • Extend the JSON DSL dynamically with plugins • Automate your build environment with Maven • Add custom data type mappers
  • 71. Additional Features • Plugin a custom namer • Generate classes that are related to other domain models • Generate classes for other languages • Style the GUI Tool
  • 72. Database Connectors Open Source • MySQL • PostgreSQL • MariaDB Enterprise • Oracle • Microsoft SQL server • DB2 • AS400
  • 73. Agenda • Problem Description • Code Generation in Database Applications • How Does it Work? • Code Example • Controlling the Code Generation • Generate Custom Classes • Add new Method to Existing Classes • Code Example • Additional Features • Beyond Open Source • Questions & Answers
  • 74. Beyond Open-Source • Speedment Enterprise • Run your database queries orders of magnitude faster! • 10x, 100x, 1 000x, 10 000x, … • Use the same Stream API
  • 75. How is This Possible? • No changes to user-written code • Alternative stream source • Data is stored in-memory • Generates optimized serializers for offheap storage
  • 76. In-JVM-Memory, JMH Benchmarks(*) Benchmark Mode Cnt Score Error Units SpeedmentBenchmark.findStartsWith avgt 200 ≈ 10⁻⁵ s/op SpeedmentBenchmark.findStartsWithSql avgt 200 ≈ 10⁻⁴ s/op SpeedmentBenchmark.join avgt 200 0.476 ± 0.005 s/op SpeedmentBenchmark.joinSql avgt 200 5.174 ± 0.010 s/op SpeedmentBenchmark.sort avgt 200 ≈ 10⁻⁶ s/op SpeedmentBenchmark.sortSql avgt 200 ≈ 10⁻⁴ s/op SpeedmentBenchmark.scrollSorted avgt 200 ≈ 10⁻⁵ s/op SpeedmentBenchmark.scrollSortedSql avgt 200 24.661 ± 0.670 s/op SpeedmentBenchmark.count avgt 180 ≈ 10⁻⁸ s/op SpeedmentBenchmark.countSql avgt 200 5.143 ± 0.012 s/op (*) Preliminary results, Mac Book Pro, 2.2 GHz i7, 16GB, MySQL 5.7.16 standard with indexes on all relevant columns. 10x >10x 100x 2,000,000x 500,000,000x
  • 77. Speedment Enterprise Example Courtesy of Extremely Heavy Industries
  • 78. Free Enterprise Trial Today we have released version 1.1.1 Get a free trial! Leave your contact information.

Hinweis der Redaktion

  1. What we are going to talk about today
  2. What we are going to talk about today
  3. Ice-breaker
  4. Negatives
  5. Positives
  6. Positives
  7. Agile Workflow
  8. Positives
  9. Positives
  10. What we are going to talk about today
  11. Code Structure Let the database be the center of the iterative process
  12. What is generated? How many of you guys are using JPA or an ORM?
  13. Pause before the fourth arrow ”Do you know what the coolest aspect of this paragraph is?”
  14. Positives
  15. Positives
  16. Output on next slide
  17. Output on next slide
  18. Output on next slide
  19. Next: Emil Live Demo #1
  20. What we are going to talk about today
  21. Stop here
  22. Mention problem before showing the solutions
  23. Class is not java.lang.Class
  24. @ExecuteBefore says this class must be configured before use Dependency injection is used to get access to the code generation component
  25. Enum != java.lang.Enum
  26. @ExecuteBefore says this class must be configured before use Dependency injection is used to get access to the code generation component
  27. Now that you have seen all this, how do you think code generation can solve your challenges? Do you have ideas what you can generate?
  28. Live Demo, then Q&A
  29. What we are going to talk about today
  30. Entities, Managers, Application
  31. Why add methods? You know your own domain model best!
  32. What we are going to talk about today
  33. For every table! Like 100 tables!
  34. What we are going to talk about today
  35. Live Demo, then Q&A
  36. Live Demo, then Q&A
  37. What we are going to talk about today
  38. What we are going to talk about today
  39. Live Demo, then Q&A
  40. What we are going to talk about today