Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
SlideShare a Scribd company logo
Lecture 19 
Application Architecture
Agenda 
 Layering 
 Application Architecture 
 Play! implementation 
 Introduction to REST
Architecture Considerations
Three Layers 
 Presentation Layer for the User Interface 
 Domain Layer for the domain logic 
 Data Source Layer for the data access 
Client 
Client 
Domain Data Source 
– Separation of concern
Presentation Layer 
 Consideration 
– Separating the Presentation Logic from the Domain 
Logic 
– Simple vs. Rich user interface 
– Should content be editable frequently
User Interfaces 
 Clear separation of concerns is important 
– Define the Presentation Logic 
– Design the domain layer so the presentation can get 
the information needed 
– Semantics – or the meaning of things is important 
– Presentation logic must avoid making assumptions on 
the domain – the semantics should be a part of the 
domain 
• Use Data Transfer Objects to store semantics
Client Types 
 Native OS Applications 
– Windows, iOS, Android, Linux 
 Embedded 
– Run inside Web Browsers 
– Flash, Java Applets 
 Interactive Web Applications 
– HTML with JavaScript 
 HTML Presentation in Browsers 
– Simple HTML
Client Types 
 Mobile is not a client type 
– It’s just smaller screen 
– Which 60% people hold vertically 
 People have their phones with them all the time 
 Check their phone about110 times per day
L19 Application Architecture
Different user motivations
Responsive Web Design 
 Web pages that automatically adjust to the 
screen size 
– Should be the default design 
 Problems with RWD 
– Does not deal with context 
– What would a persons be 
looking for when using 
a mobile phone? 
– Excuse to avoid apps, when app might be a better 
choice
Native vs. Web 
 Debate
MOBILE WEB MOBILE APP 
Downloaded, runs 
Using a mobile 
on native hardware 
web browser 
PROS 
Content is indexable 
Device independent (almost) 
Easier/Faster development & update 
Easier to measure 
CONS 
Connection Dependence 
Limited hardware integration 
Bandwidth & browser limited UX 
PROS 
Connection independence 
Better hardware integration 
Better graphic performance & UX 
CONS 
Content is not web indexable 
Device dependence 
More expensive development & update 
More complex to measue 
Source: moz.com/blog/
Content Delivery 
 Native, Embedded and Interactive Web Apps 
– Require HTTP API call for dynamic content 
– For example SOAP, REST with Json or XML 
 HTML Presentation in Browsers 
– Server side generated
Content Type 
 Static Content such as graphic assets, doesn’t 
change frequently 
 Editable Content such as text, layout, mashed-up 
content, editable by content owners, 
frequently 
 Dynamic Content stored in database and 
manipulated by the domain logic
Content Management Systems 
 Content is separated form the Enterprise system 
– Managed by CMS software with its own database 
– HTTP API calls for dynamic content from the 
enterprise system 
CLIENT 
Web Browser 
HTML 
JavaScript CMS 
Enterprise 
Application 
HTTP/REST/Json 
OPERATOR 
Editable 
content 
Static 
content 
Dynamic 
content 
Static 
content
Domain Layer 
 Where is the domain logic? 
– Application Servers 
– Lightweight Containers
Application Servers 
 Domain Components are deployed on 
Application Servers 
– Distributed Multi-tiered Applications 
– Example: 
• Web Servers, EJB Servers
Lightweight Containers 
 Assemble components from different projects 
into a cohesive application 
– Wiring is done with “Inversion of Control” - config 
– Provide life-cycle management of objects 
– Provide context 
Web Browser 
(User Interface) 
Web Browser 
(User Interface) 
Web Server 
Web Layer 
Lightweight Container 
Domain 
Layer 
Data 
Source 
Layer 
Database
Data Source Layer 
 How to create the mapping from the domain to 
the Data Source Layer 
– Gateways with no domain logic 
– Records managed with some domain logic 
– Data Mappers
Data Source Layer 
 Domain Model uses gateway 
Domain 
Layer 
Data 
Source 
Layer
Object Relational Mapping (ORM) 
 Use a mapping layer to map between objects 
and tables 
– Mapping a data representation from an object model 
to a relational data model with a SQL-based schema 
 Mapping requires 
metadata 
– XML 
 Authoring and 
maintaining 
metadata is less work than maintaining SQL
The Big Picture 
Client 
Web 
Data 
Domain 
Server Source 
DB 
CMS 
REST
The Big Picture in SOA 
Client 
Web 
SERVICE Data 
Domain 
Server Source 
DB 
CMS 
REST 
Web 
Data 
REST 
SERVICE Domain 
Server Source 
DB 
Frameworks Libraries 
Shared 
Objects
Architecture Decisions
Advice is a dangerous gift 
There are no right answers 
“Use the advice to prod your thinking, but don’t use it as 
a replacement for your thinking”
Three Layers 
 Presentation Layer for the User Interface 
 Domain Layer for the domain logic 
 Data Source Layer for the data access 
Presentation 
Layer 
Domain Data Source 
– What patterns to use?
Domain Layer 
 Transaction Script 
 Domain Model 
 Table Module
Domain Layer 
 Transaction Script 
– Procedural 
– Encapsulates the logic of each transaction 
– Works well for systems that are transactional in 
nature 
 Drawbacks 
– Does not handle complexity of logic 
– Code duplications
Domain Layer 
 Domain Model 
– Works nicely for any type of domain logic 
– Flexibility in creating an object oriented classes that 
use abstractions and polymorphism 
– Beautiful code 
 Drawbacks 
– Learning curve – understanding the model 
– Requires skills 
– Doesn’t map easily to relational database
Domain Layer 
 Table Module 
– Works well for data driven applications 
– Fits well with relational databases 
– Requires Record Set functionality 
 Drawbacks 
– Structured around the database 
– Needs tooling support, for example Record Set 
– Can become dependent on the environment
Data Source Layer 
 Data Source for Transaction Script 
– Fits well to use the Gateway patterns 
– Row Data Gateway or Table Data Gateway 
– Depends on the applications 
– If the transactions are dealing with each row per 
transactions, then Row Data Gateway works 
– If working with tables, Table Data Gateway works
Data Source Layer 
 Data Source for Table Module 
– Table Module requires good support from Record 
Set 
– Table Data Gateway fits this well
Data Source Layer 
 Data Source for Domain Model 
– If the Domain Model is fairly simple, and maps the 
database, Active Record works well 
– If you want to provide abstraction the gateway 
patterns become better choice, Row Data Gateway 
and Table Data Gateway 
– If things get more complication and there is need to 
keep the model independent from the data source, 
Data Mapper should be considered
Model View Controller 
 For all types MVC architectural patterns applies 
 Web Frameworks are usually implemented 
using the Front Controller pattern 
 Each request has an Action or a Controller 
 Views are handle by Template View
The Big Picture 
Domain Layer 
Presentation 
Layer 
Service 
Layer 
Data Source 
Domain 
DB
QUIZ 
We have a relatively simple domain logic that maps nicely to 
the data schema, and we have good tools for Record Set 
handling. What Domain Layer pattern would make sense? 
A) Service Layer 
B) Domain Model 
C) Transaction Script 
D) Table Module 
✔
Play! Framework 
38
Exercise 
 Design Web Application RuNews 
– Front page displays RSS news items 
– Content read with ImportContentProcess 
– User can sign up and login
Overivew 
Controller 
View 
Service Layer 
Domain Model 
Table Data 
Gateway 
routes ApplicationConext.xml 
users
Signup 
 As a user, I want to be able to sign up 
Registration 
Fields: name, username, password, email 
Validtaion: 
all fields are required 
username must be at least 4 characters 
password must be confirmed (typed in twice)
L19 Application Architecture
Play setup 
43 
 Project is created: RuNews 
 Structure 
controllers 
is.ru.honn.news 
views
The Database 
 Table users 
44 
CREATE TABLE users 
( 
id int Identity (1, 1) primary key NOT NULL, 
name varchar(128), 
username varchar(128) unique, 
password varchar(128), 
email varchar(128), 
)
Application.java 
45 
package controllers; 
import play.*; 
import play.mvc.*; 
import views.html.*; 
public class Application extends Controller 
{ 
public static Result index() 
{ 
return ok(index.render()); 
} 
}
index 
 View is views/index.scala.html 
 Compiled: views/html/index 
46 
@main(Html("RuNews")) { 
<h2>Registration</h2> 
<p> 
Here you can sign up: <a class="btn” 
href="@routes.SignUp.blank">Sign up</a> 
</p> 
}
Routing 
 conf/routes contains the routing information 
47 
# Routes 
# This file defines all application routes (Higher priority routes first) 
# ~~~~ 
# Home page 
GET / controllers.Application.index() 
# Sign Up 
GET /signup controllers.SignUp.blank() 
POST /signup controllers.SignUp.submit() 
# Map static resources from the /public folder to the /assets URL path 
GET /assets/*file controllers.Assets.at(path="/public", file)
RuNews Example 
 User 
48 
public class User 
{ 
protected int id; 
protected String name; 
protected String username; 
protected String password; 
protected String email; 
public User() 
{ 
} 
public User(int id, String name, String username, String password, 
String email) 
{ 
this.id = id; 
this.name = name; 
this.username = username;
RuNews Example 
 UserService is a Service Layer interface 
 UserServiceData contains the implementation 
49 
public interface UserService 
{ 
public int signup(User user); 
public User login(String username, String password); 
public void setUserDataGateway(UserDataGateway userDataGateway); 
}
Adding Domain and Data Layers 
 Implementation of Service 
Layer, Domain and Data 
Source Layers added 
– Added as is 
– Should be in model 
50
Adding Domain and Data Layers 
 ApplicationContext.xml added to conf 
– Drop data.xml 
51 
<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation="http://www.springframework.org/schema/beans 
http://www.springframework.org/schema/beans/spring-beans.xsd"> 
<bean id="userService" class="is.ru.honn.news.service.UserServiceData"> 
<property name="userDataGateway" ref="userDataGateway"/> 
</bean> 
<bean id="userDataGateway" class="is.ru.honn.news.data.UserData"> 
<property name="dataSource" ref="dataSource"/> 
</bean> 
<bean id="dataSource" 
class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 
<property name="driverClassName" value="net.sourceforge.jtds.jdbc.Driver"/> 
<property name="url" value="jdbc:jtds:sqlserver://hrnem.ru.is:1433"/>
Adding Domain and Data Layers 
 Table Data Gateway injected into service 
52 
public class UserServiceData implements UserService 
{ 
RuDataAccessFactory factory; 
UserDataGateway userDataGateway; 
public UserServiceData() 
{ 
} 
public void setUserDataGateway(UserDataGateway UserDataGateway) 
{ 
this.userDataGateway = UserDataGateway; 
}
RuNews Example 
 Signup is a Controller 
53 
import views.html.signup.*; 
import is.ru.honn.news.domain.UserRegistration; 
public class SignUp extends Controller 
{ 
final static Form<UserRegistration> signupForm 
= Form.form(UserRegistration.class); 
public static Result blank() 
{ 
return ok(form.render(signupForm)); 
}
RuNews Example 
 Signup is a Controller 
54 
public static Result submit() 
{ 
Form<UserRegistration> filledForm = signupForm.bindFromRequest(); 
... 
if (filledForm.hasErrors()) { 
return badRequest(form.render(filledForm)); 
} 
else { 
User created = filledForm.get(); 
ApplicationContext ctx = new FileSystemXmlApplicationContext 
("/conf/ApplicationContext.xml"); 
UserDataGateway userDataGateway = 
(UserDataGateway)ctx.getBean("userDataGateway"); 
userDataGateway.addUser((User)created); 
return ok(summary.render(created)); 
} 
} 
}
RuNews Example 
 form.scala.html is the view 
55 
@(signupForm: Form[is.ru.honn.news.domain.UserRegistration]) 
@import helper._ 
@import helper.twitterBootstrap._ 
@title = { 
Sign Up 
} 
@main(title, nav = "signup") { 
@helper.form(action = routes.SignUp.submit) { 
<fieldset> 
<legend>Account informations</legend> 
@inputText( 
signupForm("name"), 
'_label -> "Name", 
'_help -> "Please enter your name.", 
'_error -> signupForm.globalError 
)
RuNews Example 
 form.scala.html is the view 
56 
@inputText( 
signupForm("username"), 
'_label -> "Username", 
'_help -> "Please choose a valid username.", 
'_error -> signupForm.globalError 
) 
@inputText( 
signupForm("email"), '_label -> "Email", 
'_help -> "Enter a valid email address." 
) 
@inputPassword( 
signupForm("password"), 
'_label -> "Password", 
'_help -> "A password must be at least 6 characters. " 
)... 
</fieldset>
RuNews Example 
 forms.scala.html is the view 
57 
<fieldset> 
@checkbox( 
signupForm("accept"), 
'_label -> None, '_text -> "You agree the Terms and conditions", 
'_showConstraints -> false 
) 
</fieldset> 
<div class="actions"> 
<input type="submit" class="btn primary" value="Sign Up"> 
<a href="@routes.Application.index" class="btn">Cancel</a> 
</div> 
} 
}
RuNews Example 
 summary.scala.html displayes the user 
58 
@(user: is.ru.honn.news.domain.User) 
@main(Html("Account created!"), nav = "signup") { 
<h2>Your account:</h2> 
<p>Name: @user.getName()</p> 
<p>Username: @user.getUsername()</p> 
<p>Email: @user.getEmail()</p> 
}
59
L19 Application Architecture
L19 Application Architecture
L19 Application Architecture
L19 Application Architecture
L19 Application Architecture

More Related Content

L19 Application Architecture

  • 1. Lecture 19 Application Architecture
  • 2. Agenda  Layering  Application Architecture  Play! implementation  Introduction to REST
  • 4. Three Layers  Presentation Layer for the User Interface  Domain Layer for the domain logic  Data Source Layer for the data access Client Client Domain Data Source – Separation of concern
  • 5. Presentation Layer  Consideration – Separating the Presentation Logic from the Domain Logic – Simple vs. Rich user interface – Should content be editable frequently
  • 6. User Interfaces  Clear separation of concerns is important – Define the Presentation Logic – Design the domain layer so the presentation can get the information needed – Semantics – or the meaning of things is important – Presentation logic must avoid making assumptions on the domain – the semantics should be a part of the domain • Use Data Transfer Objects to store semantics
  • 7. Client Types  Native OS Applications – Windows, iOS, Android, Linux  Embedded – Run inside Web Browsers – Flash, Java Applets  Interactive Web Applications – HTML with JavaScript  HTML Presentation in Browsers – Simple HTML
  • 8. Client Types  Mobile is not a client type – It’s just smaller screen – Which 60% people hold vertically  People have their phones with them all the time  Check their phone about110 times per day
  • 11. Responsive Web Design  Web pages that automatically adjust to the screen size – Should be the default design  Problems with RWD – Does not deal with context – What would a persons be looking for when using a mobile phone? – Excuse to avoid apps, when app might be a better choice
  • 12. Native vs. Web  Debate
  • 13. MOBILE WEB MOBILE APP Downloaded, runs Using a mobile on native hardware web browser PROS Content is indexable Device independent (almost) Easier/Faster development & update Easier to measure CONS Connection Dependence Limited hardware integration Bandwidth & browser limited UX PROS Connection independence Better hardware integration Better graphic performance & UX CONS Content is not web indexable Device dependence More expensive development & update More complex to measue Source: moz.com/blog/
  • 14. Content Delivery  Native, Embedded and Interactive Web Apps – Require HTTP API call for dynamic content – For example SOAP, REST with Json or XML  HTML Presentation in Browsers – Server side generated
  • 15. Content Type  Static Content such as graphic assets, doesn’t change frequently  Editable Content such as text, layout, mashed-up content, editable by content owners, frequently  Dynamic Content stored in database and manipulated by the domain logic
  • 16. Content Management Systems  Content is separated form the Enterprise system – Managed by CMS software with its own database – HTTP API calls for dynamic content from the enterprise system CLIENT Web Browser HTML JavaScript CMS Enterprise Application HTTP/REST/Json OPERATOR Editable content Static content Dynamic content Static content
  • 17. Domain Layer  Where is the domain logic? – Application Servers – Lightweight Containers
  • 18. Application Servers  Domain Components are deployed on Application Servers – Distributed Multi-tiered Applications – Example: • Web Servers, EJB Servers
  • 19. Lightweight Containers  Assemble components from different projects into a cohesive application – Wiring is done with “Inversion of Control” - config – Provide life-cycle management of objects – Provide context Web Browser (User Interface) Web Browser (User Interface) Web Server Web Layer Lightweight Container Domain Layer Data Source Layer Database
  • 20. Data Source Layer  How to create the mapping from the domain to the Data Source Layer – Gateways with no domain logic – Records managed with some domain logic – Data Mappers
  • 21. Data Source Layer  Domain Model uses gateway Domain Layer Data Source Layer
  • 22. Object Relational Mapping (ORM)  Use a mapping layer to map between objects and tables – Mapping a data representation from an object model to a relational data model with a SQL-based schema  Mapping requires metadata – XML  Authoring and maintaining metadata is less work than maintaining SQL
  • 23. The Big Picture Client Web Data Domain Server Source DB CMS REST
  • 24. The Big Picture in SOA Client Web SERVICE Data Domain Server Source DB CMS REST Web Data REST SERVICE Domain Server Source DB Frameworks Libraries Shared Objects
  • 26. Advice is a dangerous gift There are no right answers “Use the advice to prod your thinking, but don’t use it as a replacement for your thinking”
  • 27. Three Layers  Presentation Layer for the User Interface  Domain Layer for the domain logic  Data Source Layer for the data access Presentation Layer Domain Data Source – What patterns to use?
  • 28. Domain Layer  Transaction Script  Domain Model  Table Module
  • 29. Domain Layer  Transaction Script – Procedural – Encapsulates the logic of each transaction – Works well for systems that are transactional in nature  Drawbacks – Does not handle complexity of logic – Code duplications
  • 30. Domain Layer  Domain Model – Works nicely for any type of domain logic – Flexibility in creating an object oriented classes that use abstractions and polymorphism – Beautiful code  Drawbacks – Learning curve – understanding the model – Requires skills – Doesn’t map easily to relational database
  • 31. Domain Layer  Table Module – Works well for data driven applications – Fits well with relational databases – Requires Record Set functionality  Drawbacks – Structured around the database – Needs tooling support, for example Record Set – Can become dependent on the environment
  • 32. Data Source Layer  Data Source for Transaction Script – Fits well to use the Gateway patterns – Row Data Gateway or Table Data Gateway – Depends on the applications – If the transactions are dealing with each row per transactions, then Row Data Gateway works – If working with tables, Table Data Gateway works
  • 33. Data Source Layer  Data Source for Table Module – Table Module requires good support from Record Set – Table Data Gateway fits this well
  • 34. Data Source Layer  Data Source for Domain Model – If the Domain Model is fairly simple, and maps the database, Active Record works well – If you want to provide abstraction the gateway patterns become better choice, Row Data Gateway and Table Data Gateway – If things get more complication and there is need to keep the model independent from the data source, Data Mapper should be considered
  • 35. Model View Controller  For all types MVC architectural patterns applies  Web Frameworks are usually implemented using the Front Controller pattern  Each request has an Action or a Controller  Views are handle by Template View
  • 36. The Big Picture Domain Layer Presentation Layer Service Layer Data Source Domain DB
  • 37. QUIZ We have a relatively simple domain logic that maps nicely to the data schema, and we have good tools for Record Set handling. What Domain Layer pattern would make sense? A) Service Layer B) Domain Model C) Transaction Script D) Table Module ✔
  • 39. Exercise  Design Web Application RuNews – Front page displays RSS news items – Content read with ImportContentProcess – User can sign up and login
  • 40. Overivew Controller View Service Layer Domain Model Table Data Gateway routes ApplicationConext.xml users
  • 41. Signup  As a user, I want to be able to sign up Registration Fields: name, username, password, email Validtaion: all fields are required username must be at least 4 characters password must be confirmed (typed in twice)
  • 43. Play setup 43  Project is created: RuNews  Structure controllers is.ru.honn.news views
  • 44. The Database  Table users 44 CREATE TABLE users ( id int Identity (1, 1) primary key NOT NULL, name varchar(128), username varchar(128) unique, password varchar(128), email varchar(128), )
  • 45. Application.java 45 package controllers; import play.*; import play.mvc.*; import views.html.*; public class Application extends Controller { public static Result index() { return ok(index.render()); } }
  • 46. index  View is views/index.scala.html  Compiled: views/html/index 46 @main(Html("RuNews")) { <h2>Registration</h2> <p> Here you can sign up: <a class="btn” href="@routes.SignUp.blank">Sign up</a> </p> }
  • 47. Routing  conf/routes contains the routing information 47 # Routes # This file defines all application routes (Higher priority routes first) # ~~~~ # Home page GET / controllers.Application.index() # Sign Up GET /signup controllers.SignUp.blank() POST /signup controllers.SignUp.submit() # Map static resources from the /public folder to the /assets URL path GET /assets/*file controllers.Assets.at(path="/public", file)
  • 48. RuNews Example  User 48 public class User { protected int id; protected String name; protected String username; protected String password; protected String email; public User() { } public User(int id, String name, String username, String password, String email) { this.id = id; this.name = name; this.username = username;
  • 49. RuNews Example  UserService is a Service Layer interface  UserServiceData contains the implementation 49 public interface UserService { public int signup(User user); public User login(String username, String password); public void setUserDataGateway(UserDataGateway userDataGateway); }
  • 50. Adding Domain and Data Layers  Implementation of Service Layer, Domain and Data Source Layers added – Added as is – Should be in model 50
  • 51. Adding Domain and Data Layers  ApplicationContext.xml added to conf – Drop data.xml 51 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="userService" class="is.ru.honn.news.service.UserServiceData"> <property name="userDataGateway" ref="userDataGateway"/> </bean> <bean id="userDataGateway" class="is.ru.honn.news.data.UserData"> <property name="dataSource" ref="dataSource"/> </bean> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="net.sourceforge.jtds.jdbc.Driver"/> <property name="url" value="jdbc:jtds:sqlserver://hrnem.ru.is:1433"/>
  • 52. Adding Domain and Data Layers  Table Data Gateway injected into service 52 public class UserServiceData implements UserService { RuDataAccessFactory factory; UserDataGateway userDataGateway; public UserServiceData() { } public void setUserDataGateway(UserDataGateway UserDataGateway) { this.userDataGateway = UserDataGateway; }
  • 53. RuNews Example  Signup is a Controller 53 import views.html.signup.*; import is.ru.honn.news.domain.UserRegistration; public class SignUp extends Controller { final static Form<UserRegistration> signupForm = Form.form(UserRegistration.class); public static Result blank() { return ok(form.render(signupForm)); }
  • 54. RuNews Example  Signup is a Controller 54 public static Result submit() { Form<UserRegistration> filledForm = signupForm.bindFromRequest(); ... if (filledForm.hasErrors()) { return badRequest(form.render(filledForm)); } else { User created = filledForm.get(); ApplicationContext ctx = new FileSystemXmlApplicationContext ("/conf/ApplicationContext.xml"); UserDataGateway userDataGateway = (UserDataGateway)ctx.getBean("userDataGateway"); userDataGateway.addUser((User)created); return ok(summary.render(created)); } } }
  • 55. RuNews Example  form.scala.html is the view 55 @(signupForm: Form[is.ru.honn.news.domain.UserRegistration]) @import helper._ @import helper.twitterBootstrap._ @title = { Sign Up } @main(title, nav = "signup") { @helper.form(action = routes.SignUp.submit) { <fieldset> <legend>Account informations</legend> @inputText( signupForm("name"), '_label -> "Name", '_help -> "Please enter your name.", '_error -> signupForm.globalError )
  • 56. RuNews Example  form.scala.html is the view 56 @inputText( signupForm("username"), '_label -> "Username", '_help -> "Please choose a valid username.", '_error -> signupForm.globalError ) @inputText( signupForm("email"), '_label -> "Email", '_help -> "Enter a valid email address." ) @inputPassword( signupForm("password"), '_label -> "Password", '_help -> "A password must be at least 6 characters. " )... </fieldset>
  • 57. RuNews Example  forms.scala.html is the view 57 <fieldset> @checkbox( signupForm("accept"), '_label -> None, '_text -> "You agree the Terms and conditions", '_showConstraints -> false ) </fieldset> <div class="actions"> <input type="submit" class="btn primary" value="Sign Up"> <a href="@routes.Application.index" class="btn">Cancel</a> </div> } }
  • 58. RuNews Example  summary.scala.html displayes the user 58 @(user: is.ru.honn.news.domain.User) @main(Html("Account created!"), nav = "signup") { <h2>Your account:</h2> <p>Name: @user.getName()</p> <p>Username: @user.getUsername()</p> <p>Email: @user.getEmail()</p> }
  • 59. 59