Upload
margery-douglas
View
213
Download
0
Embed Size (px)
Citation preview
Domain Driven Web Development With WebJinn
Sergei KojarskiCollege of Computer & Information Science
Northeastern University
joint work withDavid H. Lorenz
http://webjinn.org
Web Application
WebApp
WebApp
Client HTTP Server
Browser Resource
• An HTTP gateway to a server–side resource
• HTTP Request/Response model
• Converts between HTTP and Resource terms
BACKGROUNDBACKGROUND
Web Development
Written in two programming languages:
Functionality (e.g., Java, C, Perl)
Presentation (e.g., XML, HTML)
BACKGROUNDBACKGROUND
Theory and Practice
Well-understood Simple
functionality Interactions
patterns
BACKGROUNDBACKGROUND
Difficult to create Complicated
implementations No reusable
components
Concept State of the art
Schema
HTTP ResourceSchema
Functionality
server-side operations
Presentation
HTML response
Control
high-level control-flow
Functionality
Presentation
Control
<%@ page import="java.sql.*" %> <%try{
Class.forName("org.gjt.mm.mysql.Driver").newInstance(); java.sql.Connection conn; conn = DriverManager.getConnection( "jdbc:mysql://localhost/database?user=login&password=pass"); try { Statement st = conn.createStatement(); ResultSet rs = st.executeQuery("select name,email,message from guestbook");%>
<%if (rs.next() {%>
<!--BEGIN-CONTENT-VIEW------------><table width=100% border=0 cellspacing=1 cellpadding=1><%do {%> <tr><td>Visitor: <a href='mailto: <%=rs.getString("emai")%>'> <%=rs.getString("name")%></a></td></tr> <tr><td><%=rs.getString("message")%></td></tr><%} while (rs.next());%></table><!--END-CONTENT-VIEW-------------->
<%} else {%> <!--BEGIN-NO RECORDS-VIEW-------> Guest book is empty. <!--END-NO RECORDS-VIEW---------> <%} } finally {conn.close();} } catch (Exception e) {%><!--BEGIN-SERVICE-NOT-AVAILABLE-VIEW------------------------> Server error: <%=e.getMessage()%><!--END-SERVICE-NOT-AVAILABLE-VIEW--------------------------><%}%>
The Problem: Tangling and Scattering
page code example:
name email message
Visitor: <%=rs.getString(“email”)%><%=rs.getString(“name”)%>
<%=rs.getString(“message”)%>
OVERVIEWOVERVIEW
<!--BEGIN-FAIL-VIEW------------------------> Server error: <%=e.getMessage()%><!--END-FAIL-VIEW-------------------------->
<!--BEGIN-SERVICE-NOT-AVAILABLE-VIEW------------------------> Server error: <%=e.getMessage()%><!--END-SERVICE-NOT-AVAILABLE-VIEW-------------------------->
Separation of concerns
<%@ page import="java.sql.*" %> <%try{ Class.forName("org.gjt.mm.mysql.Driver").newInstance(); java.sql.Connection conn; conn = DriverManager.getConnection( "jdbc:mysql://localhost/database?user=login&password=pass"); try { PreparedStatement pst = conn.prepareStatement( (“insert into guestbook (name,email,message) values (?,?,?)”); pst.setString(1,request.getParameter(“name”); pst.setString(2,request.getParameter(“email”); pst.setString(3,request.getParameter(“message”); pst.execute(); %>
<!--BEGIN-SUCCESS-VIEW------------>Message was successfully added<!--END-SUCCESS-VIEW-------------->
} finally {conn.close();} } catch (Exception e) {%>
<%}%>
<%@ page import="java.sql.*" %> <%try{
Class.forName("org.gjt.mm.mysql.Driver").newInstance(); java.sql.Connection conn; conn = DriverManager.getConnection( "jdbc:mysql://localhost/database?user=login&password=pass"); try { Statement st = conn.createStatement(); ResultSet rs = st.executeQuery("select name,email,message from guestbook");%>
<%if (rs.next() {%>
<!--BEGIN-CONTENT-VIEW------------><table width=100% border=0 cellspacing=1 cellpadding=1><%do {%> <tr><td> Visitor: <a href='mailto: <%=rs.getString("emai")%> '> <%=rs.getString("name")%> </a></td></tr> <tr><td> <%=rs.getString("message")%> </td></tr><%} while (rs.next());%></table><!--END-CONTENT-VIEW-------------->
<%} else {%> <!--BEGIN-NO RECORDS-VIEW-------> Guest book is empty. <!--END-NO RECORDS-VIEW---------> <%} } finally {conn.close();} } catch (Exception e) {%>
<%}%>
<form action="doInsert.jsp"><tr><th colspan=2>New Message</th></tr><tr><td>Your Name</td><td><input type=text name="name"></tr><tr><td>E-mail</td><td><input type=text name="email"></tr><tr><td>Message</td><td><textarea name="message"></textarea><tr><td colspan=2><input type=submit value="Add"></td></tr></form>
select.jsp doInsert.jsp
insertForm.jsp
name email message
name email message pst.setString(1,request.getParameter(“name”);
<input type=text name="name">Your Name
pst.setString(1,request.getParameter(“email”); pst.setString(1,request.getParameter(“message”);
E-mailMessage
<input type=text name=“email"><textarea name=“message"></textarea>
?,?,?
Visitor: <%=rs.getString(“email”)%><%=rs.getString(“name”)%>
<%=rs.getString(“message”)%>
Main contribution: schema concern modularization
OVERVIEWOVERVIEW
Example: Guestbook
• Typical client-server interaction• Typical components (select, insert)• Typical problems
• intra-crosscutting• inter-crosscutting
PROBLEMPROBLEM
Guestbook Architecture
Browser guestbook database table
SQL queries
select.jsp
doInsert.jsp
insertForm.jsp
HTTP
PROBLEMPROBLEM
Retrieves messagesRetrieves messages
A form for adding a message
A form for adding a message
Posts a new messagePosts a new message
Select records from guestbook table
Print “Content”
Load driver and connect to database
If table is not empty then
Else
Print “No records”
Close database connection
Catch exception
Print “Service not available”
select.jsp
<%@ page import="java.sql.*" %> <%try{
Class.forName("org.gjt.mm.mysql.Driver").newInstance(); java.sql.Connection conn; conn = DriverManager.getConnection( "jdbc:mysql://localhost/database?user=login&password=pass"); try { Statement st = conn.createStatement(); ResultSet rs = st.executeQuery("select name,email,message from guestbook");%>
<%if (rs.next() {%>
<!--BEGIN-CONTENT-VIEW------------><table width=100% border=0 cellspacing=1 cellpadding=1><%do {%> <tr><td>Visitor: <a href='mailto: <%=rs.getString("emai")%>'> <%=rs.getString("name")%></a></td></tr> <tr><td><%=rs.getString("message")%></td></tr><%} while (rs.next());%></table><!--END-CONTENT-VIEW-------------->
<%} else {%> <!--BEGIN-NO RECORDS-VIEW-------> Guest book is empty. <!--END-NO RECORDS-VIEW---------> <%} } finally {conn.close();} } catch (Exception e) {%><!--BEGIN-SERVICE-NOT-AVAILABLE-VIEW------------------------> Server error: <%=e.getMessage()%><!--END-SERVICE-NOT-AVAILABLE-VIEW--------------------------><%}%>
page code description
name email message
Visitor: <%=rs.getString(“email”)%><%=rs.getString(“name”)%>
<%=rs.getString(“message”)%>
select name, email, message from …name email message
<%=rs.getString(“name”)%>
href=“ <%=rs.getString(“email”)%>
> </a>
<%=rs.getString(“message”)%> </td>
PROBLEMPROBLEM
Construct and execute SQL insert statement
Print “Fail”
Print “Message added”
doInsert.jsp
<%@ page import="java.sql.*" %> <%try{ Class.forName("org.gjt.mm.mysql.Driver").newInstance(); java.sql.Connection conn; conn = DriverManager.getConnection( "jdbc:mysql://localhost/database?user=login&password=pass"); try { PreparedStatement pst = conn.prepareStatement( (“insert into guestbook (name, email, message) values (?,?,?)”); pst.setString(1,request.getParameter(“name”); pst.setString(2,request.getParameter(“email”); pst.setString(3,request.getParameter(“message”); pst.execute(); %>
<!--BEGIN-SUCCESS-VIEW------------>Message was successfully added<!--END-SUCCESS-VIEW-------------->
} finally {conn.close();} } catch (Exception e) {%><!--BEGIN-FAIL-VIEW------------------------> Server error: <%=e.getMessage()%><!--END-FAIL-VIEW--------------------------><%}%>
Load driver and connect to database
Close connection
Catch exception
page code description
name email messagepst.setString(1,request.getParameter(“name”);pst.setString(1,request.getParameter(“email”);
pst.setString(1,request.getParameter(“message”);
?,?,?
PROBLEMPROBLEM
insertForm.jsp
Return an HTML formthat the visitor can fill in order to add a new message into the guestbook.
<form action="doInsert.jsp"><table> <tr><th colspan=2>New Message</th></tr> <tr> <td>Your Name</td> <td><input type=text name="name"> </tr> <tr> <td>E-mail</td> <td><input type=text name="email"> </tr> <tr> <td>Message</td> <td><textarea name="message"></textarea> </tr><tr><td colspan=2><input type=submit value="Add"></td></tr></table></form>
page code description
<input type=text name="name">
Your Name
Message
<input type=text name=“email">
<textarea name=“message"></textarea>
PROBLEMPROBLEM
Intra- versus inter-crosscutting
Intra Tangling Dynamic pages Page scoped OOP solution
Inter Scattering Dynamic and static Crosscuts pages AOP solution
All scheme expressions relate to
the same instance
insertForm.jsp
select.jsp doInsert.jspIllustration
<form action="doInsert.jsp"><tr><th colspan=2>New Message</th></tr><tr><td>Your Name</td><td><input type=text name="name"></tr><tr><td>E-mail</td><td><input type=text name="email"></tr><tr><td>Message</td><td><textarea name="message"></textarea><tr><td colspan=2><input type=submit value="Add"></td></tr></form>
<%@ page import="java.sql.*" %>
<%try{
Class.forName("org.gjt.mm.mysql.Driver").newInstance(); java.sql.Connection conn; conn = DriverManager.getConnection( "jdbc:mysql://localhost/database?user=login&password=pass"); try { Statement st = conn.createStatement(); ResultSet rs = st.executeQuery("select name,email,message from guestbook");%>
<%if (rs.next() {%>
<!--BEGIN-CONTENT-VIEW------------><table width=100% border=0 cellspacing=1 cellpadding=1><%do {%> <tr><td> Visitor: <a href='mailto: <%=rs.getString("emai")%> '> <%=rs.getString("name")%> </a></td></tr> <tr><td> <%=rs.getString("message")%> </td></tr><%} while (rs.next());%></table><!--END-CONTENT-VIEW-------------->
<%} else {%>
<!--BEGIN-NO RECORDS-VIEW-------> Guest book is empty. <!--END-NO RECORDS-VIEW--------->
<%}
} finally {conn.close();}
} catch (Exception e) {%>
<!--BEGIN-SERVICE-NOT-AVAILABLE-VIEW------------------------> Server error: <%=e.getMessage()%><!--END-SERVICE-NOT-AVAILABLE-VIEW-------------------------->
<%}%>
<%@ page import="java.sql.*" %> <%try{
Class.forName("org.gjt.mm.mysql.Driver").newInstance(); java.sql.Connection conn; conn = DriverManager.getConnection( "jdbc:mysql://localhost/database?user=login&password=pass"); try { PreparedStatement pst = conn.prepareStatement( (“insert into guestbook (name,email,message) values (?,?,?)”); pst.setString(1,request.getParameter(“name”); pst.setString(2,request.getParameter(“email”); pst.setString(3,request.getParameter(“message”); pst.execute(); %>
<!--BEGIN-SUCCESS-VIEW------------>Message was successfully added<!--END-SUCCESS-VIEW-------------->
} finally {conn.close();} } catch (Exception e) {%>
<!--BEGIN-FAIL-VIEW------------------------> Server error: <%=e.getMessage()%><!--END-FAIL-VIEW-------------------------->
<%}%>
TanglingTangling
ScatteringScattering
Dynamic pagesDynamic pages
Dynamic and staticDynamic and static
Page scopedPage scoped
Crosscuts pagesCrosscuts pages
OOP solutionOOP solution
AOP solutionAOP solution
PROBLEMPROBLEM
High development cost
High maintenance cost
Loss of reuse opportunities
Increases dependency between developer groups, error-prone, etc.
Natural language
Correct?
Consequence of inter-crosscutting
PROBLEMPROBLEM
High development cost
High development cost
High maintenance cost
High maintenance cost
Loss of reuse opportunitiesLoss of reuse opportunities
Changes to the schema trigger complex code updates
Cost of schema changes out-weights reuse benefits
<%@ page import="java.sql.*" %> <%try{
Class.forName("org.gjt.mm.mysql.Driver").newInstance(); java.sql.Connection conn; conn = DriverManager.getConnection( "jdbc:mysql://localhost/database?user=login&password=pass"); try { PreparedStatement pst = conn.prepareStatement( (“insert into guestbook (name,email,message) values (?,?,?)”); pst.setString(1,request.getParameter(“name”); pst.setString(2,request.getParameter(“email”); pst.setString(3,request.getParameter(“message”); pst.execute(); %>
<!--BEGIN-SUCCESS-VIEW------------>Message was successfully added<!--END-SUCCESS-VIEW-------------->
} finally {conn.close();} } catch (Exception e) {%><!--BEGIN-FAIL-VIEW------------------------> Server error: <%=e.getMessage()%><!--END-FAIL-VIEW--------------------------><%}%>
Unweaving inter-crosscutting
<%@ page import="java.sql.*" %> <%try{
Class.forName("org.gjt.mm.mysql.Driver").newInstance(); java.sql.Connection conn; conn = DriverManager.getConnection( "jdbc:mysql://localhost/database?user=login&password=pass"); try { Statement st = conn.createStatement(); ResultSet rs = st.executeQuery("select name,email,message from guestbook");%>
<%if (rs.next() {%>
<!--BEGIN-CONTENT-VIEW------------><table width=100% border=0 cellspacing=1 cellpadding=1><%do {%> <tr><td> Visitor: <a href='mailto: <%=rs.getString("emai")%> '> <%=rs.getString("name")%> </a></td></tr> <tr><td> <%=rs.getString("message")%> </td></tr><%} while (rs.next());%></table><!--END-CONTENT-VIEW-------------->
<%} else {%>
<!--BEGIN-NO RECORDS-VIEW-------> Guest book is empty. <!--END-NO RECORDS-VIEW--------->
<%} } finally {conn.close();} } catch (Exception e) {%>
<!--BEGIN-SERVICE-NOT-AVAILABLE-VIEW------------------------> Server error: <%=e.getMessage()%><!--END-SERVICE-NOT-AVAILABLE-VIEW-------------------------->
<%}%>
<form action="doInsert.jsp"><tr><th colspan=2>New Message</th></tr><tr><td>Your Name</td><td><input type=text name="name"></tr><tr><td>E-mail</td><td><input type=text name="email"></tr><tr><td>Message</td><td><textarea name="message"></textarea><tr><td colspan=2><input type=submit value="Add"></td></tr></form>
name email message
name email message pst.setString(1,request.getParameter(“name”);
<input type=text name="name">Your Name
pst.setString(1,request.getParameter(“email”); pst.setString(1,request.getParameter(“message”);
E-mailMessage
<input type=text name=“email"><textarea name=“message"></textarea>
?,?,?
Visitor: <%=rs.getString(“email”)%><%=rs.getString(“name”)%>
<%=rs.getString(“message”)%>
Schema-related expressions are clustered by operationselect.jsp doInsert.jsp
insertForm.jsp
Constructing SQL select statement
Constructing SQL insert statement
Rendering guest book messages as HTML table
Rendering HTML form for inserting a message
XP1
XP2
XP4
1. Substitute clusters with schema-shy extension points1. Substitute clusters with schema-shy extension points
To unweave inter-crosscutting we…
2. Specify schema-related code in a separate module2. Specify schema-related code in a separate module
<%@ page import="java.sql.*" %> <%try{
Class.forName("org.gjt.mm.mysql.Driver").newInstance(); java.sql.Connection conn; conn = DriverManager.getConnection( "jdbc:mysql://localhost/database?user=login&password=pass"); try { PreparedStatement pst = conn.prepareStatement( (“insert into guestbook (name,email,message) values (?,?,?)”); pst.setString(1,request.getParameter(“name”); pst.setString(2,request.getParameter(“email”); pst.setString(3,request.getParameter(“message”); pst.execute(); %>
<!--BEGIN-SUCCESS-VIEW------------>Message was successfully added<!--END-SUCCESS-VIEW-------------->
} finally {conn.close();} } catch (Exception e) {%><!--BEGIN-FAIL-VIEW------------------------> Server error: <%=e.getMessage()%><!--END-FAIL-VIEW--------------------------><%}%>
<%@ page import="java.sql.*" %> <%try{
Class.forName("org.gjt.mm.mysql.Driver").newInstance(); java.sql.Connection conn; conn = DriverManager.getConnection( "jdbc:mysql://localhost/database?user=login&password=pass"); try { Statement st = conn.createStatement(); ResultSet rs = st.executeQuery("select name,email,message from guestbook");%>
<%if (rs.next() {%>
<!--BEGIN-CONTENT-VIEW------------><table width=100% border=0 cellspacing=1 cellpadding=1><%do {%> <tr><td> Visitor: <a href='mailto: <%=rs.getString("emai")%> '> <%=rs.getString("name")%> </a></td></tr> <tr><td> <%=rs.getString("message")%> </td></tr><%} while (rs.next());%></table><!--END-CONTENT-VIEW-------------->
<%} else {%>
<!--BEGIN-NO RECORDS-VIEW-------> Guest book is empty. <!--END-NO RECORDS-VIEW--------->
<%} } finally {conn.close();} } catch (Exception e) {%>
<!--BEGIN-SERVICE-NOT-AVAILABLE-VIEW------------------------> Server error: <%=e.getMessage()%><!--END-SERVICE-NOT-AVAILABLE-VIEW-------------------------->
<%}%>
<form action="doInsert.jsp"><tr><th colspan=2>New Message</th></tr><tr><td>Your Name</td><td><input type=text name="name"></tr><tr><td>E-mail</td><td><input type=text name="email"></tr><tr><td>Message</td><td><textarea name="message"></textarea><tr><td colspan=2><input type=submit value="Add"></td></tr></form>
XP1
XP2
XP3
XP4
Abstract application SchemaWeaver
XP33. Employ weaver to produce executable code 3. Employ weaver to produce executable code
XP ModelXP Model
SOLUTIONSOLUTION
Solution space
SOLUTIONSOLUTION
Problem Model Framework
Intra-crosscutting
MVC Apache Struts
Inter-crosscutting
XP WebJinn/XP
Intra- and Inter-
crosscuttingDDD WebJinn
WebJinn Architecture
Resource
ModelController
View
request
response
Java classes
JSP pages
Controller servlet
Schema
SOLUTIONSOLUTION
Benefits of WebJinn
Decreased dependency between developer groups
Adaptability to schema changes High code reusability
SOLUTIONSOLUTION
Dynamicpage
DDDevolution
Conclusion
CONCLUSIONCONCLUSION
Intra-crosscutting
Inter-crosscutting
Staticpage
CG
I scripts
MVC
XP