Play Framework makes it easy to build web applications with Java & Scala. This presentation give a idea of how play is implemented using Netty, how routes work. How we get calls in controller's action. Walk through guice and logging.
2. Play Framework
Based on Netty
Stateless play framework
Full stack web framework
Includes model persistence, template (views), controllers, testing
Developer friendly
Hot reload: Framework listens for changes and compiles & deploys in background
Fully compiled and type safe
Nice features:
4. Netty Server
Netty is :
IO library
Asynchronous
Non-blocking
Multi-protocol
Netty gives:
Good Performance
Low resource consumption
5. Netty Server Asynchronous
All I/O operations do not block
Get notified when operation completed
Be able to share threads across many connections
In OS:
select()/poll() : traditional POSIX polling
epoll() : event based polling, on Linux 2.5.44+
Kqueue : on FreeBSD, MacOS X
6. How Netty works?
NIO ServerSocketChannel is a channel that can listen for incoming TCP
connections
How threads work: boss threads and worker threads.
Boss Thread:
Each bound ServerSocketChannel has its own boss thread
if you opened two server ports such as 80 and 443, you will have two boss threads
A boss thread accepts incoming connections until the port is unbound.
Once a connection is accepted successfully, the boss thread passes the accepted Channel to one
of the worker threads
7. Main Components
Bootstrap and ServerBootstrap
EventLoop
Channel
ChannelFuture
ChannelPipeline
ChannelHandlers
ChannelHandlerContext
10. Project Structure
app/
Contains application’s core in models, controllers and views
conf/
Application config files, route definition file, message file for internationalization etc.
project/
Contains the build script
public/
Contains all publically available resources like javascripts, stylesheets and images
14. Introduction
Component that translates each incoming HTTP request to an action call
Made up of HTTP Verb, path and action function
All calls go to right method with help of routers
18. Controllers, Actions and Result
Controllers are classes
Located in apps/controllers folder
Inherit from abstract controllers class
Methods which handle request inside controllers are called actions
Return Result object
20. Play Views
Scala comes with Twirl, a scala based template engine
Twirl engine is:
Compact, expressive and fluid
Easy to learn
Easy to edit
It is a simple text file which contains small scala code blocks
Very close to HTML
Simple naming convention views/filename.scala.html
22. Object Relational Mapping
During application development, we want to focus on business concepts, not
relational database structure
Provide abstraction during communication with database
Allow automatic synchronization between java objects and database tables
Database independent
Query abstraction, database specific queries are autogenerated
Object and query caching is done by ORM
23. Java Persistence API (JPA)
Specification for management of persistence and object relational mapping with
java
Provide object relational mapping by mapping java POJOs to relational
databases
POJO based persistence model
Support for enriched domain modeling i.e. inheritance, polymorphism etc
Expanded query language
Support for pluggable persistence provider
24. JPA: Persistence Entity
Annotated POJO
Lightweight persistent domain model
Persistent identity field
Provide support for
Abstract class and inheritance
Relationships (OneToOne, OneToMany, ManyToMany)
Each entity is typically represented by one table
Each entity can have both persistent and nonpersistent state
25. Data Model
Set of concepts to describe structure of database
Specify constraints that database should follow
Operations on data model may include basic operations and user defined
operations
Building blocks
Entity : data will be stored and collected in them
Attribute: Characteristics of entity
Relationship: association between entities
27. Evolutions
Helps track and organize your database schema (in case of relational databases)
Play tracks your database evolutions using several evolutions script.
Scripts located at:
conf/evolutions/{database name}
Each script contains two parts:
The Ups part the describe the required transformations.
The Downs part that describe how to revert them.
Evolutions are automatically activated if a database is configured in
29. Filters
The filter API is intended for cross cutting concerns that are applied
indiscriminately to all routes.
Filters wrap the action after the action has been looked up by the router.
Cannot use a filter to transform a path, method or query parameter to impact the
router.
Can direct the request to a different action by invoking that action directly from
the filter
Common use case of filters:
Logging/metrics collection
31. Introduction
Dependency Injection is ability to inject external dependency into software
component
Benefits:
Easier testing and refactoring
Easier maintenance
Loose coupling
Managing object lifetime
Better design and use
Hide implementation details
32. Guice
Dependency injection framework
Convention over configuration
Easier to use, test, maintain, refactor and learn
Static and compile time verification
Favor good design with immutability, valid object and thread safe object
Basic Annotations
@Inject
@ImplementedBy
34. Why we need logging?
Monitoring
Debugging
Error Tracking
Business Intelligence
Play provides an API for logging which is accessed through the Logger object and
uses Logback as the default logging engine.
35. Logback Logging Architecture
Different components:
Logger
Default logger named “application”
Can create our own logger
Log Level :
OFF : use to turn off logging
ERROR: Runtime error, or unexpected exception
WARN: Deprecated Api, unexpected situation
36. Logback Logging Architecture
Appender
Handle responsibility to write event to component
Kinds of appender:
OutputStreamAppender: Append events to OutputStream
ConsoleAppender: Append events to console, or System.out or System.err
FileAppender: Append events to file
RollingFileAppender: Append events to file with the capability to rollover log files
Time based rolling policy
Size and time based rolling policy
38. Logback Logging Architecture
Encoder
Accept events and transform these events into byte array
Write into output stream
Total control of what and when bytes gets written to the output stream
Layout
Transform an incoming event into a String
Has no control over when events get written out
Layouts can not aggregate events into batches
39. Using Logger
Import play.Logger
Logger.debug("Result={}", result)
Never do Logger.debug(“Result=”+result), as it will do string concatenation
every time without we actually adding it in log file based on Log level.
Play puts both the console and the file logger behind the logback
AsyncAppender
Config file path : conf/logback.xml
41. MDC: Map Diagnostic Context
Help uniquely stamp request
Manages contextual information on a per thread basis
MDC.put(“userkey”, value)
MDC.remove(“userkey”)
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%coloredLevel %logger{15} %X{userkey} - %message%n%xException{10}</pattern>
</encoder>
</appender>
42. Best Practices
Always keep date on log file name
Always add some name to your log file name, which help in distinguish it from
other log files.
Always log time and date of events
Store date in YYYYMMDDHHMMSS format (ideally) as it helps in sorting.
Use 24 hour time format.
In multi threaded system, use thread id.
Use different name of logger, depending on kind of logs as that help in
43. Best Practices
Log single event in single line, stack trace kind of thing can be multiline.
Log with a delimiter between fields so logs can be easily parsed. Don’t skip
empty fields add something like - or delimiter to identify it.
Log identification information as that helps in debugging.
Don’t log sensitive information like passwords etc.