SlideShare una empresa de Scribd logo
1 de 61
JavaTWO專業技術大會
Play!Framework for JavaEE Developers
Who am I Exp : JSP/Servlet , Tapestry , Spring/Hibernate/JavaEE , Wicket , Android , Grails , Play! Framework http://gplus.to/smallufo http://twitter.com/smallufo smallufo@gmail.com
Web Framework Experiences ,[object Object]
Too old , cumbersome
 Tapestry (old experience, T5 is very good)
Complicated , evolution/deprecation too fast
 Wicket
Too elaborate , fail to see the wood for the trees
May lead to over-engineered architecture for OO-purism
Spend too much time refactoring
Maybe web component reuse is just a myth
Grails (old experience, without Groovy++)
Slow
Too many inconsistent DSLs (URL-mapping , DB , logging...)
Not Java , IDE unfriendly,[object Object]
Conventional JavaEE Stack ,[object Object]
Let's define JSP/JSTL (JSR-53)
And let Apache (or others) to implement Jakata Taglibs
 Want web components ?
Let's define Java Server Faces (JSR-127)
And let communities to implement MyFaces, PrimeFaces, ICEfaces...
Want restful ?
Let's define JAX-RS (JSR-311)
And let communities to implement CXF, Jersey, RESTEasy, Wink...,[object Object]
Specs
Implementations
Configurations
Tedious , Error-prone
Unless you use a full-fledged JavaEE Server (Glassfish or WebLogic ...)
Layered
Defined by Standards/Specs
Assembled by InterfacesOVER ARCHITECTED
Play’s App Looks Like ? conf/routes app/App.java GET    /hello    App.hello public class App extends Controller {   public static void hello() {     User user = User.findById(1L);     render(user);   } }  views/App/hello.html Hello World : ${user.name} http://localhost:9000/hello
And Play is ... ,[object Object]
Totally independent of JavaEE environment
RESTful
No session
Stateless
Pure server side
Similar to Rails / Django
Rich domain model
Unlike JavaEE's anemic domain model,[object Object]
Can be packaged as a WAR and deployed to servlet containers,[object Object]
Play! URLs are RESTful & SEO-friendly UGLY GRACEFUL ,[object Object]
/listcar/page1/count10
/listcar/page1?count=10
/listcar/page/1/count/10
/car.jsp?id=1
/listcars.jsp?page=1&count=10
http://www.facebook.com/ photo.php? fbid=2121715487568& set=o.172881386106136& type=1&theater,[object Object]
Use HttpSessionListener to count sessions (online users)
ServletFilter
Servlet-related securities
 @ServletSecurity
 <auth-constraint /> , <security-role />,[object Object]
The most important feature you have to keep in mind
No session!
Session is the source of all problems of the JavaEE platform!
Session replication 

Más contenido relacionado

La actualidad más candente

La actualidad más candente (20)

Developing real-time data pipelines with Spring and Kafka
Developing real-time data pipelines with Spring and KafkaDeveloping real-time data pipelines with Spring and Kafka
Developing real-time data pipelines with Spring and Kafka
 
Building Event Driven (Micro)services with Apache Kafka
Building Event Driven (Micro)services with Apache KafkaBuilding Event Driven (Micro)services with Apache Kafka
Building Event Driven (Micro)services with Apache Kafka
 
Introduction To RabbitMQ
Introduction To RabbitMQIntroduction To RabbitMQ
Introduction To RabbitMQ
 
Extending WSO2 API Manager's Key Management Capabilities - WSO2 API Manager C...
Extending WSO2 API Manager's Key Management Capabilities - WSO2 API Manager C...Extending WSO2 API Manager's Key Management Capabilities - WSO2 API Manager C...
Extending WSO2 API Manager's Key Management Capabilities - WSO2 API Manager C...
 
ELK Stack
ELK StackELK Stack
ELK Stack
 
Testing with JUnit 5 and Spring - Spring I/O 2022
Testing with JUnit 5 and Spring - Spring I/O 2022Testing with JUnit 5 and Spring - Spring I/O 2022
Testing with JUnit 5 and Spring - Spring I/O 2022
 
Software Development Best Practices: Separating UI from Business Logic
Software Development Best Practices: Separating UI from Business LogicSoftware Development Best Practices: Separating UI from Business Logic
Software Development Best Practices: Separating UI from Business Logic
 
Introduction to Event Driven Architecture
Introduction to Event Driven ArchitectureIntroduction to Event Driven Architecture
Introduction to Event Driven Architecture
 
[Spring Camp 2018] 11번가 Spring Cloud 기반 MSA로의 전환 : 지난 1년간의 이야기
[Spring Camp 2018] 11번가 Spring Cloud 기반 MSA로의 전환 : 지난 1년간의 이야기[Spring Camp 2018] 11번가 Spring Cloud 기반 MSA로의 전환 : 지난 1년간의 이야기
[Spring Camp 2018] 11번가 Spring Cloud 기반 MSA로의 전환 : 지난 1년간의 이야기
 
Event Driven Software Architecture Pattern
Event Driven Software Architecture PatternEvent Driven Software Architecture Pattern
Event Driven Software Architecture Pattern
 
An Authentication and Authorization Architecture for a Microservices World
An Authentication and Authorization Architecture for a Microservices WorldAn Authentication and Authorization Architecture for a Microservices World
An Authentication and Authorization Architecture for a Microservices World
 
Workshop Microservices - Construindo APIs RESTful com Spring Boot
Workshop Microservices - Construindo APIs RESTful com Spring BootWorkshop Microservices - Construindo APIs RESTful com Spring Boot
Workshop Microservices - Construindo APIs RESTful com Spring Boot
 
OpenTelemetry For Architects
OpenTelemetry For ArchitectsOpenTelemetry For Architects
OpenTelemetry For Architects
 
Loki - like prometheus, but for logs
Loki - like prometheus, but for logsLoki - like prometheus, but for logs
Loki - like prometheus, but for logs
 
Tuning Apache Kafka Connectors for Flink.pptx
Tuning Apache Kafka Connectors for Flink.pptxTuning Apache Kafka Connectors for Flink.pptx
Tuning Apache Kafka Connectors for Flink.pptx
 
Introduction to Open Mano
Introduction to Open ManoIntroduction to Open Mano
Introduction to Open Mano
 
Introduction to Kafka Cruise Control
Introduction to Kafka Cruise ControlIntroduction to Kafka Cruise Control
Introduction to Kafka Cruise Control
 
Spring Boot to Quarkus: A real app migration experience | DevNation Tech Talk
Spring Boot to Quarkus: A real app migration experience | DevNation Tech TalkSpring Boot to Quarkus: A real app migration experience | DevNation Tech Talk
Spring Boot to Quarkus: A real app migration experience | DevNation Tech Talk
 
Introducing Saga Pattern in Microservices with Spring Statemachine
Introducing Saga Pattern in Microservices with Spring StatemachineIntroducing Saga Pattern in Microservices with Spring Statemachine
Introducing Saga Pattern in Microservices with Spring Statemachine
 
Testing Kafka components with Kafka for JUnit
Testing Kafka components with Kafka for JUnitTesting Kafka components with Kafka for JUnit
Testing Kafka components with Kafka for JUnit
 

Destacado

Play framework - Human Talks Grenoble - 12.02.2013
Play framework - Human Talks Grenoble - 12.02.2013Play framework - Human Talks Grenoble - 12.02.2013
Play framework - Human Talks Grenoble - 12.02.2013
Xavier NOPRE
 
Enib cours c.a.i. web - séance #5 : scala play! framework
Enib   cours c.a.i. web - séance #5 : scala play! frameworkEnib   cours c.a.i. web - séance #5 : scala play! framework
Enib cours c.a.i. web - séance #5 : scala play! framework
Horacio Gonzalez
 
Réseaux sociaux - Utilisation tout au long de d’un parcours professionnel
Réseaux sociaux - Utilisation tout au long de d’un parcours professionnelRéseaux sociaux - Utilisation tout au long de d’un parcours professionnel
Réseaux sociaux - Utilisation tout au long de d’un parcours professionnel
Abaka Conseil
 
Stream Processing using Apache Flink in Zalando's World of Microservices - Re...
Stream Processing using Apache Flink in Zalando's World of Microservices - Re...Stream Processing using Apache Flink in Zalando's World of Microservices - Re...
Stream Processing using Apache Flink in Zalando's World of Microservices - Re...
Zalando Technology
 

Destacado (20)

Web application development using Play Framework (with Java)
Web application development using Play Framework (with Java)Web application development using Play Framework (with Java)
Web application development using Play Framework (with Java)
 
Why Play Framework is fast
Why Play Framework is fastWhy Play Framework is fast
Why Play Framework is fast
 
Using Play Framework 2 in production
Using Play Framework 2 in productionUsing Play Framework 2 in production
Using Play Framework 2 in production
 
Play framework - Human Talks Grenoble - 12.02.2013
Play framework - Human Talks Grenoble - 12.02.2013Play framework - Human Talks Grenoble - 12.02.2013
Play framework - Human Talks Grenoble - 12.02.2013
 
Enib cours c.a.i. web - séance #5 : scala play! framework
Enib   cours c.a.i. web - séance #5 : scala play! frameworkEnib   cours c.a.i. web - séance #5 : scala play! framework
Enib cours c.a.i. web - séance #5 : scala play! framework
 
Vert.x - Tehran JUG meeting Aug-2014 - Saeed Zarinfam
Vert.x - Tehran JUG meeting Aug-2014 - Saeed ZarinfamVert.x - Tehran JUG meeting Aug-2014 - Saeed Zarinfam
Vert.x - Tehran JUG meeting Aug-2014 - Saeed Zarinfam
 
Baromètre Apec Andrh Bilan 2013
Baromètre Apec Andrh Bilan 2013Baromètre Apec Andrh Bilan 2013
Baromètre Apec Andrh Bilan 2013
 
Scala and Play with Gradle
Scala and Play with GradleScala and Play with Gradle
Scala and Play with Gradle
 
Réseaux sociaux - Utilisation tout au long de d’un parcours professionnel
Réseaux sociaux - Utilisation tout au long de d’un parcours professionnelRéseaux sociaux - Utilisation tout au long de d’un parcours professionnel
Réseaux sociaux - Utilisation tout au long de d’un parcours professionnel
 
MOOC EcoDem - présentation du parcours professionnel par équipe
MOOC EcoDem - présentation du parcours professionnel par équipeMOOC EcoDem - présentation du parcours professionnel par équipe
MOOC EcoDem - présentation du parcours professionnel par équipe
 
Auto-scaling your API: Insights and Tips from the Zalando Team
Auto-scaling your API: Insights and Tips from the Zalando TeamAuto-scaling your API: Insights and Tips from the Zalando Team
Auto-scaling your API: Insights and Tips from the Zalando Team
 
Zalando Tech: From Java to Scala in Less Than Three Months
Zalando Tech: From Java to Scala in Less Than Three MonthsZalando Tech: From Java to Scala in Less Than Three Months
Zalando Tech: From Java to Scala in Less Than Three Months
 
How We Made our Tech Organization and Architecture Converge Towards Scalability
How We Made our Tech Organization and Architecture Converge Towards ScalabilityHow We Made our Tech Organization and Architecture Converge Towards Scalability
How We Made our Tech Organization and Architecture Converge Towards Scalability
 
Flink in Zalando's World of Microservices
Flink in Zalando's World of Microservices  Flink in Zalando's World of Microservices
Flink in Zalando's World of Microservices
 
Powering Radical Agility with Docker
Powering Radical Agility with Docker Powering Radical Agility with Docker
Powering Radical Agility with Docker
 
Akka http 2
Akka http 2Akka http 2
Akka http 2
 
Camunda BPM at Zalando: Order Processing at scale
Camunda BPM at Zalando: Order Processing at scaleCamunda BPM at Zalando: Order Processing at scale
Camunda BPM at Zalando: Order Processing at scale
 
Stream Processing using Apache Flink in Zalando's World of Microservices - Re...
Stream Processing using Apache Flink in Zalando's World of Microservices - Re...Stream Processing using Apache Flink in Zalando's World of Microservices - Re...
Stream Processing using Apache Flink in Zalando's World of Microservices - Re...
 
Radical Agility with Autonomous Teams and Microservices in the Cloud
Radical Agility with Autonomous Teams and Microservices in the CloudRadical Agility with Autonomous Teams and Microservices in the Cloud
Radical Agility with Autonomous Teams and Microservices in the Cloud
 
An Introduction to Akka http
An Introduction to Akka httpAn Introduction to Akka http
An Introduction to Akka http
 

Similar a Play! Framework for JavaEE Developers

Writing robust Node.js applications
Writing robust Node.js applicationsWriting robust Node.js applications
Writing robust Node.js applications
Tom Croucher
 

Similar a Play! Framework for JavaEE Developers (20)

soft-shake.ch - Hands on Node.js
soft-shake.ch - Hands on Node.jssoft-shake.ch - Hands on Node.js
soft-shake.ch - Hands on Node.js
 
Nodejs and WebSockets
Nodejs and WebSocketsNodejs and WebSockets
Nodejs and WebSockets
 
ActiveWeb: Chicago Java User Group Presentation
ActiveWeb: Chicago Java User Group PresentationActiveWeb: Chicago Java User Group Presentation
ActiveWeb: Chicago Java User Group Presentation
 
Introducing to node.js
Introducing to node.jsIntroducing to node.js
Introducing to node.js
 
A slightly advanced introduction to node.js
A slightly advanced introduction to node.jsA slightly advanced introduction to node.js
A slightly advanced introduction to node.js
 
hacking with node.JS
hacking with node.JShacking with node.JS
hacking with node.JS
 
Express Presentation
Express PresentationExpress Presentation
Express Presentation
 
Xitrum Web Framework Live Coding Demos / Xitrum Web Framework ライブコーディング
Xitrum Web Framework Live Coding Demos / Xitrum Web Framework ライブコーディングXitrum Web Framework Live Coding Demos / Xitrum Web Framework ライブコーディング
Xitrum Web Framework Live Coding Demos / Xitrum Web Framework ライブコーディング
 
Xitrum @ Scala Matsuri Tokyo 2014
Xitrum @ Scala Matsuri Tokyo 2014Xitrum @ Scala Matsuri Tokyo 2014
Xitrum @ Scala Matsuri Tokyo 2014
 
node.js: Javascript's in your backend
node.js: Javascript's in your backendnode.js: Javascript's in your backend
node.js: Javascript's in your backend
 
I Feel Pretty
I Feel PrettyI Feel Pretty
I Feel Pretty
 
Boston Computing Review - Java Server Pages
Boston Computing Review - Java Server PagesBoston Computing Review - Java Server Pages
Boston Computing Review - Java Server Pages
 
Java on Windows Azure
Java on Windows AzureJava on Windows Azure
Java on Windows Azure
 
Resthub lyonjug
Resthub lyonjugResthub lyonjug
Resthub lyonjug
 
Moving applications to the cloud
Moving applications to the cloudMoving applications to the cloud
Moving applications to the cloud
 
Jsp
JspJsp
Jsp
 
Spine.js
Spine.jsSpine.js
Spine.js
 
Writing robust Node.js applications
Writing robust Node.js applicationsWriting robust Node.js applications
Writing robust Node.js applications
 
GWT Extreme!
GWT Extreme!GWT Extreme!
GWT Extreme!
 
Accelerated Adoption: HTML5 and CSS3 for ASP.NET Developers
Accelerated Adoption: HTML5 and CSS3 for ASP.NET DevelopersAccelerated Adoption: HTML5 and CSS3 for ASP.NET Developers
Accelerated Adoption: HTML5 and CSS3 for ASP.NET Developers
 

Último

Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
WSO2
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
panagenda
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
?#DUbAI#??##{{(☎️+971_581248768%)**%*]'#abortion pills for sale in dubai@
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Safe Software
 

Último (20)

CNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In PakistanCNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In Pakistan
 
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot ModelMcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
 
WSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering DevelopersWSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering Developers
 
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWEREMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
 
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
Apidays New York 2024 - APIs in 2030: The Risk of Technological Sleepwalk by ...
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024
 
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
Elevate Developer Efficiency & build GenAI Application with Amazon Q​
Elevate Developer Efficiency & build GenAI Application with Amazon Q​Elevate Developer Efficiency & build GenAI Application with Amazon Q​
Elevate Developer Efficiency & build GenAI Application with Amazon Q​
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
Exploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusExploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with Milvus
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdfRising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
 
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ..."I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
 

Play! Framework for JavaEE Developers

  • 3. Who am I Exp : JSP/Servlet , Tapestry , Spring/Hibernate/JavaEE , Wicket , Android , Grails , Play! Framework http://gplus.to/smallufo http://twitter.com/smallufo smallufo@gmail.com
  • 4.
  • 5. Too old , cumbersome
  • 6.  Tapestry (old experience, T5 is very good)
  • 9. Too elaborate , fail to see the wood for the trees
  • 10. May lead to over-engineered architecture for OO-purism
  • 11. Spend too much time refactoring
  • 12. Maybe web component reuse is just a myth
  • 13. Grails (old experience, without Groovy++)
  • 14. Slow
  • 15. Too many inconsistent DSLs (URL-mapping , DB , logging...)
  • 16.
  • 17.
  • 19. And let Apache (or others) to implement Jakata Taglibs
  • 21. Let's define Java Server Faces (JSR-127)
  • 22. And let communities to implement MyFaces, PrimeFaces, ICEfaces...
  • 25.
  • 26. Specs
  • 30. Unless you use a full-fledged JavaEE Server (Glassfish or WebLogic ...)
  • 34.
  • 35. Play’s App Looks Like ? conf/routes app/App.java GET /hello App.hello public class App extends Controller { public static void hello() { User user = User.findById(1L); render(user); } } views/App/hello.html Hello World : ${user.name} http://localhost:9000/hello
  • 36.
  • 37. Totally independent of JavaEE environment
  • 42. Similar to Rails / Django
  • 44.
  • 45.
  • 46.
  • 52.
  • 53. Use HttpSessionListener to count sessions (online users)
  • 57.
  • 58. The most important feature you have to keep in mind
  • 60. Session is the source of all problems of the JavaEE platform!
  • 63.
  • 64.
  • 65. save(User u)Client.java @Inject UserDao userDao User u = new User(...) userDao.save(u) VS *JPA advocates eliminating the DAO layer
  • 66. Play's Architecture $ play new myproj myproj app controllers models conf application.conf views messages lib foo routes modules bar public images javascripts src stylesheets
  • 67. conf/application.conf application.name=myapp application.mode=dev application.secret=OOXXOOXXOOXXOOXXOOXX http.port=9000 java.source=1.6 db.url=jdbc:mysql:... db.driver=com.mysql.jdbc.Driver db.user=user db.pass=pass hibernate.use_sql_comments=true hibernate.format_sql = true XForwardedSupport=127.0.0.1
  • 68. Play's Architecture controllers app MyController.java public static void index() public static void show() models views MyController index.html foo show.html bar
  • 69. conf/routes HTTP method URI Pattern Action GET    /                      App.index POST   /login                 App.login GET    /tag/{name}            App.tag(name) GET    /list/{page}           App.list(page) GET    /list/{<[0-9]+>page}   App.list(page) GET    /list/{page}/{count}   App.list(page,count) GET    /public/               staticDir:public *      /{controller}/{action} {controller}.{action}
  • 71. Controllers and Redirections public class App extends play.mvc.Controller {   public static void index() {     render(); // views/App/index.html contains a login form   }   public static void login(String name,String passwd) {     if(...) // success       welcome();     else   // failed       index();   }   public static void welcome() {     render();  // renders views/App/welcome.html    } }
  • 72. Controller Interceptions public class App extends play.mvc.Controller {   @play.mvc.Before(unless={“index”, “login”})   public static void intercept() {     if (session.get("uid")==null)        index();   }   public static void index() {...}   public static void login(String name,Stringpasswd){..}   public static void welcome() {...} }
  • 73. Session : A Signed Cookie public static void login(String name , String passwd) {   User u = ...   if (...) {     session.put("uid" , u.id);   } } Only put index data to session Never store sensitive data signed,  uneditable!
  • 74. Controller Revisited public static void show(Long uid, String type) {   User u = ...   if (type.equals("json") {     renderJSON(u);   // provided by GSON   }    else if (type.equals("xml") {     renderXml(u);    // provided by XStream   }       render(u);   } Why not continue rendering? play.mvc.Controller throw new RenderJson(jsonString); throw new RenderXml(xml); throw new RenderTemplate(...);
  • 75. Controller and View controllers/App.java public static void showUser(Long uid) {   User u = ...   List<Car> cars = ...   renderArgs.put("user",u);   render(cars, company, job, ...);   } public static void showCar(Long id) {...} renderArgs.put(“cars”,car); renderArgs.put(“company”,company); renderArgs.put(“job”,job); same views/App/showUser.html Hello ${user.name} , these are your cars : #{list items:cars , as:'car'}   #{a @showCar(car.id)} ${car.name} #{/a} #{/list} template tag @App.showCar(car.id)
  • 76. How objects are passed to View !? controllers/App.java public static void showUser(Long uid) {   renderArgs.put("user",u);   render(cars , ...);   } !!?? views/App/showUser.html ${user.name} #{list items:cars , as:'car'} Let's decompile it...
  • 77. public static void showUser(Long uid) {   play.classloading.enhancers.LocalvariablesNamesEnhancer.LocalVariablesNamesTracer.enter();   play.classloading.enhancers.LocalvariablesNamesEnhancer.LocalVariablesNamesTracer.addVariable("uid", uid);   if(!play.classloading.enhancers.ControllersEnhancer.ControllerInstrumentation.isActionCallAllowed())   {     Controller.redirect("controllers.App.showUser", new Object[] {       uid     });   } else   {     play.classloading.enhancers.ControllersEnhancer.ControllerInstrumentation.stopActionCall();     User u = (User)User.findById(uid);     play.classloading.enhancers.LocalvariablesNamesEnhancer.LocalVariablesNamesTracer.addVariable("u", u);     List cars = Car.all().fetch();     play.classloading.enhancers.LocalvariablesNamesEnhancer.LocalVariablesNamesTracer.addVariable("cars", cars);     Object obj = null;     play.mvc.Scope.RenderArgs renderargs = null;     renderargs = (play.mvc.Scope.RenderArgs)Java.invokeStatic(Desc.getType("Lplay/mvc/Scope$RenderArgs;"), "current");     renderargs.put("user", u);     render(new Object[] {       cars     });   }   break MISSING_BLOCK_LABEL_120;   Exception exception;   exception;   Object obj1 = null;   play.classloading.enhancers.LocalvariablesNamesEnhancer.LocalVariablesNamesTracer.exit();   throw exception;   Object obj2 = null;   play.classloading.enhancers.LocalvariablesNamesEnhancer.LocalVariablesNamesTracer.exit();   return; }
  • 78.
  • 79.
  • 83.
  • 84. Rich Domain Object Model package models; @javax.persistence.Entity public class User extends play.db.jpa.Model {   public String username;   public String password; } Support JPA's annotations : @Column , @ManyToOne , @OneToMany ... NO more getters & setters... Great !
  • 85. Rich Domain Object Model BUT... The underlayer is hibernate & hibernate needs getter/setter Again... Who modifies my model ?
  • 86. Rich Domain Object Model In Fact...     Your model still contains getter/setter , modified by Play's custom classloader & JDT & javassist User.java public String getUsername() {   return "overridden"; } ${user.username} will be ??
  • 87. Rich Domain Object User u = User.findById(1); User u = User.find("byUsernameAndPassword", username , password).first(); User u = User.find("select u from User u where u.username = :username and u.password = :password")   .bind("username",username)   .bind("password",password)   .first(); List<User> users = User.all().fetch(); User.em().createQuery(...);
  • 88. Validations : Controller #{form @App.login()} <p> username <input type=“text” name=“username” value=“${flash.username}” /> <span class=“error”>#{error 'username'/}</span> </p> <p> password <input type=“password” name=“password” value=“${flash.password}” /> <span class=“error”>#{error 'password'/}</span> </p> <input type="submit" value=“Login" /> <span class=“error”>#{error ‘other'/}</span> #{/form} username 請輸入帳號 password 請輸入密碼 Login 帳號或密碼輸入錯誤
  • 89. Validations : Controller public static void login( @Required(message ="請輸入帳號")String username, @Required(message ="請輸入密碼")String password) { User user = User.login(username , password); if (validation.hasErrors()){ params.flash(); // add parameters to flash scope validation.keep(); // keeps the errors flash.error(validation.errors().get(0).toString()); render(“pleaseLogin.html”); } flash.success(“welcome : “ + user.username); render(); }
  • 90. Validation : Model public class User extends Model { @Required @MinSize(6) public username; @Required @MinSize(6) public password; public static User login(String username , String password) { Validation validation = Validation.current(); User user = ... validation.isTrue(user!=null) .key(“other”).message(“帳號或密碼輸入錯誤”); return user; }} Will @MinSize affect login() ?
  • 91. Validations @Required , @Min , @Max , @MinSize , @MaxSize , @Range , @Email , @URL ... Custom validation annotation extends AbstractAnnotationCheck & implements isSatisfied() i18n messages /conf/messages
  • 92. Cache Conventional JavaEE's Way public User getUser(String name) {   Session s = (Session)em.getDelegate();   Criteria c = s.createCriteria(User.class);   c.add(Restrictions.eq("username",name);   c.setMaxResults(1);   c.setCacheable(true);   if (c.uniqueResult() == null)     return null;   return (User) c.uniqueResult(); }
  • 93. Cache Play's Way : Not In Favor of 2nd Level public static User getUser(String name) {   String key="username_"+name;   User user = Cache.get(key,User.class);   if (user != null)     return user;   user = User.find("byUsername",name).first();   Cache.set(key,user,"30mn");   return user; }
  • 94. Cache - Problem ! User.java {   public static User getUser(Long id) {     String key = "userId_"+id;     ...   }   public static List<User> getUsers(Long page, int cnt) {     String key="users_"+page+"_"+cnt;     ...   } } public interface UserDao.java { public User getUser(Long id); public List<User> getUsers(Long page, int cnt); }
  • 95. Conventional JavaEE's Way User u1 = userDao.getUsers(1,10).get(0); User u2 = userDao.get(1L); assertTrue(u1.equals(u2)); // PASSED u2.modifySomething(...); userDao.save(u2); User u3 = userDao.getUsers(1,10).get(0); assertTrue(u3.equals(u2)); // PASSED Play's Way User u1 = User.getUsers(1,10).get(0); User u2 = User.getUser(1L); assertTrue(u1.equals(u2)); // PASSED u2.modifySomething(...); u2.save(); User u3 = User.getUsers(1,10).get(0); assertTrue(u3.equals(u2)); // FAILED!
  • 96. Cache Problem : Reason users_1_10 cache key : TIME u u u u u u u u u u u1 userId_1 cache key : u modified / updated u2 users_1_10 cache key : ? u u u u u u u u u u3
  • 97.
  • 99. Two phase list retrieval
  • 100. Cache object ids instead of objectspublic static List<User> getUsers(Long page, int cnt) {   String key="users_"+page+"_"+cnt;     List<Long> userIds =      User.find("select u.id from User u)     .fetch(page,cnt);   Cache.set(key, userIds, "1mn");   // iterate each id in result and query cache or fetch }
  • 101. Cache : Wait... I saw Model.em() ? How about get underlaying Hibernate’s session and setCacheable(true) ? Session s = (Session) User.em().getDelegate(); Critieria c = s.createCriteria(...); c.add(... criterions ... ); c.setCacheable(true);
  • 103. Module : CRUD package models; public class User extends Model { ... } package controllers; public class Users extends CRUD { ... } Cars , Photos , Logs even ... Boxs , Buss, Kisss
  • 104. Module GAE + Module Siena public class User extends siena.Model {    public String uid;   public static User getUser(String uid) {     return User.all(User.class).filter("uid",uid).get();   }   public static User getUsers(int page , int count) {     return User       .all(User.class)       .fetch(count,(page-1)*count);   } } Don't forget war/WEB-INF/appengine-web.xml $ play gae:deploy  Done !
  • 105.
  • 107. Less than 10 seconds
  • 108. Cache is wrapped to GAE's memcache
  • 109.
  • 110. Passing these query results in every action is cumbersome
  • 111. Solution : @Before and renderArgs.put()@Before static void addDefaults() {   renderArgs.put("brands", Brand.all().fetch());   renderArgs.put("forums", Forum.getAll());    renderArgs.put("tags" , Tag.getAll()); }
  • 112. Issue : High Availability <VirtualHost *:80>  ServerName myapp.com  <Location /balancer-manager>   SetHandler balancer-manager   Order Deny,Allow   Deny from all   Allow from .myapp.com  </Location>  <Proxy balancer://mycluster>    BalancerMember http://localhost:9002    BalancerMember http://localhost:9003 status=+H  </Proxy>  <Proxy *>    Order Allow,Deny    Allow From All  </Proxy>  ProxyPreserveHost on  ProxyPass /balancer-manager !  ProxyPass / balancer://mycluster/  ProxyPassReverse / http://localhost:9002/  ProxyPassReverse / http://localhost:9003/ </VirtualHost> Apache Web Server localhost:9002 localhost:9003 Same directory structures & application.secret , only different http.port
  • 113. Issue : Action Burst controllers/App controllers/App login() logout() register() myaccount() mybooks() index() page() search() showbook() login() logout() register() myaccount() mybooks() index() page() search() showBook() listUsers() editUser() editBook() controllers/Admin listUsers() editUser() editBook()
  • 114. Issues : Validation Dilemma Validation in controllers ? validation in models ? or hybrid ?
  • 115. Issue : DI Dependency Injection is not so useful in Play’s Rich Domain Object environment
  • 116. Case Study : VAGTW.COM VW/Audi Car Problem Stats
  • 118.
  • 119. Modified from Play's YABE sample
  • 120. 10 days learning Play! & modeling & coding
  • 121. 20 days tuning HTML & CSS(3)
  • 123. Peak 4x users in 15 mins
  • 124. Indexed by Google in 2 days
  • 125. Indexed by Yahoo in 2 weeks
  • 126.
  • 127. Loose
  • 131.
  • 134. Strict
  • 137.