View
197
Download
0
Category
Preview:
DESCRIPTION
Das ist ja sooo 200x! Speaker: Jens Schumann Erinnert sich noch jemand an Java-Webentwicklung/Enterprise-Java-Entwicklung streng nach den Vorgaben der J2EE BluePrints und mit Struts als Web Application Framework? Ach! Nie gemacht? Glück gehabt. Diese Session wagt einen Blick zurück in die Enterprise-Java-Steinzeit und zeigt, wie viel Aufwand serverseitige Java-Entwicklung zu Zeiten von J2EE 1.3 und 1.4 wirklich bedeutete und was teilweise heute noch, wenn auch unter der Haube, bei der Verwendung von Java EE, EJB und Friends sowie klassischen Webframeworks passiert.
Citation preview
Das ist ja sooo 200x! Jens Schumann – open knowledge GmbH
(Sorry – kurzer Werbeblock)
Was wir heute (trotz Testspiel) machen
• Klagen auf hohem Niveau...
• Ja, genau da sind wir gestartet!
• Diese Irrwege haben wir uns erlaubt. Leider.
• Genau genommen gibt es vieles noch heute.
• Das können und sollten wir davon lernen.
Enterprise Java im Jahr 2014
Enterprise Java im Jahr 2014 - Wicket
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>Hello World</title>
</head>
<body>
<p wicket:id="message">Message goes here</p>
</body>
</html>
Enterprise Java im Jahr 2014 - JSF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE ...>
<html ...>
<f:view>
Hello World! Today is
<h:outputText
value="#{currentTimeBean.currentDate}">
<f:convertDateTime
dateStyle="long" timeStyle="long"/>
</h:outputText>
.
</f:view>
</html>
Enterprise Java im Jahr 2014 - Spring
@Named
public class CurrentTimeBean {
public Date getCurrentDate() {
return new Date();
}
}
Enterprise Java im Jahr 2014 - CDI
@Named
@ApplicationScoped
public class CurrentTimeBean {
public Date getCurrentDate() {
return new Date();
}
}
Was wir heute machen
• Jammern auf hohem Niveau...
• Ja, genau da sind wir gestartet!
• Diese Irrwege haben wir uns erlaubt. Leider.
• Genau genommen gibt es vieles noch heute.
• Das können und sollten wir davon lernen.
Am Anfang war...
New Economy
(na gut, nicht ganz am Anfang) (ob Henne oder Ei soll hier nicht geklärt werden)
Am Anfang war...
Web? Ja, mit Applets! Applets?!
public class HelloWorld extends Applet {
public void paint(Graphics g) {
Date currentDate = new Date();
DateFormat formatter =
DateFormat.getDateTimeInstance(...);
g.drawString(
"Hello world! Today is " +
formatter.format(currentDate) +
"." , 50, 25);
}
}
Ein Servlet ist ein Applet! Hmmm?!
Although servlets can respond
to any types of requests [...],
so they can be thought of
as Java applets
that run on servers instead of in web browsers!
Applets mit Java Backend*
public class AppletBackendServlet
extends HttpServlet {
protected void doGet(HSR req, HSR resp) throws ... {
ObjectOutputStream out = ...;
ObjectInputStream in = ...;
Integer customerId = (Integer) in.readObject();
Customer customer = getCustomer(customerId);
out.writeObject(customer);
out.flush();
resp.flushBuffer();
...
}
} *Exception and Stream Handling omitted
Web ist Web, also HTML
<html>
<head>
<title>Hello World!</title>
</head>
<body>
<script type="application/javascript">
document.write(
'Hello World! Today is ' +
new Date() +
+ '.')
</script>
</body>
</html>
Web ist Web, also HTML – Servlet
Style
public class DynamicContentServlet
extends HttpServlet {
protected void doGet(HSR req, HSR resp) throws ... {
...
PrintWriter writer = resp.getWriter();
writer.write("<html>");
writer.write("<head><title>Hello World</title>" +
"</head><body>");
writer.write("Hello World! Today is ");
writer.write(formatter.format(currentDate));
writer.write(".");
writer.write("</body></html>");
resp.flushBuffer();
}
}
Was wir heute machen
• Klagen auf hohem Niveau...
• Ja, genau da sind wir gestartet!
• Diese Irrwege haben wir uns erlaubt. Leider.
• Genau genommen gibt es vieles noch heute.
• Das können und sollten wir davon lernen.
Microsoft... to the rescue!
Java Server Pages. At it‘s best.
<html>
<head><title>Hello World!</title></head>
<body>
Hello World! Today is
! Dynamic content here ! .
</body>
</html>
Java Server Pages. At it‘s best.
<html>
<head><title>Hello World!</title></head>
<body>
<%
Locale locale = request.getLocale();
Date currentDate = new Date();
DateFormat formatter =
DateFormat.getDateTimeInstance(...);
%>
Hello World! Today is
<%= formatter.format(currentDate) %>.
</body>
</html>
Java Server Pages. Ahh! - JSTL
<html>
<head><title>Hello World!</title></head>
<body>
<jsp:useBean id="now" class="java.util.Date" />
Hello World! Today is
<fmt:formatDate value="${now}" ... />.
</body>
</html>
Wir hatten doch auch Frameworks!
FooBarWizzBangCompany Framework
„Sobald das Framework fertig gestellt ist,
wird alles wirklich gut!“
Open Source schließt die Lücke
public class TestAction extends Action {
public ActionForward execute(
ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response) throws E... {
request.setAttribute("currentTime", new Date());
return mapping.findForward("success");
}
}
Enterprise ist Enterprise
Enterprise ist Enterprise
The Enterprise JavaBeans architecture
will be the standard component architecture
for building distributed object-oriented
business applications in the JavaTM
programming language.
Enterprise ist Enterprise
The Enterprise JavaBeans architecture
will make it easy to write applications:
Application developers will not have to
understand low-level transaction and state
management details, multi-threading,
connection pooling, and other
complex low-level APIs.
Verteilte Persistenz – BMP 1.1
public class Bmp11CustomerBean
implements EntityBean {
private Integer customerId;
private String firstName;
private String lastName;
// getter/setter
public Integer ejbCreate(...)
throws CreateException {...}
public void ejbLoad() throws EJBException {...}
public void ejbStore() throws EJBException {...}
public void ejbRemove() throws EJBException {...}
...
}
Verteilte Persistenz – BMP 1.1*
public class Bmp11CustomerBean
implements EntityBean {
...
public void ejbStore() throws EJBException {
Connection con = dataSource.getConnection();
PreparedStatement ps = con.prepareStatement(
"UPDATE CUSTOMER " +
"CUS_FIRST_NAME=?, ... WHERE CUS_ID=?");
ps.setString(1, firstName);
...
ps.setInt(4, customerId);
int i = ps.executeUpdate();
...
}
} *Exception and Resource Handling omitted
Verteilte deklarative Persistenz – CMP 1.1
public class Cmp11CustomerBean
implements EntityBean {
private Integer customerId;
private String firstName;
private String lastName;
// getter/setter
public Integer ejbCreate(...)
throws CreateException {...}
public void ejbLoad() throws EJBException {...}
public void ejbStore() throws EJBException {...}
public void ejbRemove() throws EJBException {...}
...
}
Verteilte deklarative Persistenz – CMP 1.1
<enterprise-beans>
<entity>
...
<persistence-type>Container</persistence-type>
<prim-key-class>java.lang.Integer</prim-key-class>
<cmp-field>
<field-name>customerId</field-name>
</cmp-field>
...
<primkey-field>customerId</primkey-field>
</entity>
</enterprise-beans>
Verteilte deklarative Persistenz – CMP 1.1
<orion-ejb-jar>
<enterprise-beans>
<finder-method partial="false"
query="select * from CUSTOMER " +
"WHERE $customerId = $1">
<method>
<ejb-name>Cmp11CustomerEntity</ejb-name>
<method-name>findByPrimaryKey</method-name>
<method-params>
<method-param>...</method-param>
</method-params>
</method>
</finder-method>
</enterprise-beans>
</orion-ejb-jar>
Verteilte deklarative Persistenz – CMP 2.0
public abstract class Cmp20CustomerBean
implements EntityBean {
public abstract String getFirstName();
public abstract void setFirstName(...);
public abstract String getLastName();
public abstract void setLastName(...);
public Integer ejbCreate(String firstName,
String lastName)
throws CreateException {
this.setFirstName(firstName);
this.setLastName(lastName);
return null;
}
...
}
Verteilte (deklarative) Persistenz. Oh Gott!
Im Business Tier ist alles gut!*
public class CustomerServiceBean
implements SessionBean {
public void activate(Integer customerId) {
Cmp11CustomerHome home = ...;
Cmp11Customer customer =
home.findByPK(customerId);
customer.activate();
}
}
*Exception and Resource Handling omitted
Wir können auch lokal*.
public class CustomerServiceBean
implements SessionBean {
public void activate(Integer customerId) {
Cmp20CustomerLocalHome home = ...;
Cmp20CustomerLocal customer =
home.findByPK(customerId);
customer.activate();
}
}
So schlimm ist es nun doch gar nicht
Doch! Please repeat yourself!
If you can say it once,
you can say it
multiple times too!
EJB Interface
Home Interface
Bean Klasse
DD Spec
DD Special
Das Programmier-Modell – Never implement!
public interface BmpCustomerHome
extends EJBHome {
public BmpCustomer create(...) throws ...;
public BmpCustomer findByPK(...) throws ...;
}
public class BmpCustomerBean
implements EntityBean {
public Integer ejbCreate(...) throws ...;
public Integer ejbFindByPK(...) throws ...;
}
Das Programmier-Modell – Remoting!
public interface CustomerService
extends EJBObject {
public void activate(Integer customerId)
throws RemoteException;
}
public class CustomerServiceBean
implements SessionBean {
public void activate(Integer customerId) {...}
}
Und diese Infrastruktur – JNDI Lookup
try {
InitialContext ic = new InitialContext();
DataSource ds =
(DataSource) ic.lookup(".../customerDS");
Connection con = ds.getConnection();
// use SQL Connection
} catch (NamingException e) {
throw new EJBException(...);
}
// TODO Resource Handling
Und diese Infrastruktur – Lookup & Narrow
try {
InitialContext ctx = new InitialContext();
Object obj= ctx.lookup(".../CustomerHome");
CustomerHome home =
(CustomerHome)PortableRemoteObject.narrow(
obj, CustomerHome.class);
// do something with the EJB
} catch (NamingException e) {
throw new EJBException(e);
}
API-Call? Wo ist da die Fachlichkeit?
try {
CmpCustomerHome home = ...; // lookup and narrow
CmpCustomer customer = home.findByPK(customerId);
customer.activate();
} catch (NamingException e) {...
} catch (FinderException e) {...
} catch (RemoteException e) {...
} finally {
if (ctx != null) {
try {
ctx.close();
} catch (NamingException e) {/* ignored */ }
}
}
Oh je! Try/catch/finally!
InitialContext ic = null;
DataSource ds = null;
try {
ic = new InitialContext();
ds = (DataSource) ic.lookup(".../customerDS");
} catch (NamingException e) {
throw new EJBException(...);
} finally {
if (ic != null) {
try {
ic.close();
} catch (NamingException e) {
// ignored
}
}
}
Zur Erinnerung: Das ist JDBC!
DataSource ds = ...; Connection con = null;
PreparedStatement ps = null; ResultSet rs = null;
try {
con = dataSource.getConnection();
ps = con.prepareStatement(...);
rs = ps.executeQuery();
...
} finally {
if (rs != null) {
try {rs.close();} catch (SQLException e){...}}
if (ps != null) {
try {ps.close();} catch (SQLException e){...}}
if (con != null) {
try {con.close();} catch (SQLException e){...}}
}
Mit Pattern wird alles einfacher.
Mit Pattern wird das alles einfacher
> The evil ValueObject,
SessionFacade,
BusinessDelegate Combo
> Aus 5 mach 10!
> ServiceLocator clearance!
> FastLaneReader makes you
scream.
Free
Who cares? Wir sind im Jahr 2014!
Was wir heute machen
• Klagen auf hohem Niveau...
• Ja, genau da sind wir gestartet!
• Diese Irrwege haben wir uns erlaubt. Leider.
• Genau genommen gibt es vieles noch heute.
• Das können und sollten wir davon lernen.
You care!
You care! Really!
„Java EE
Programmiermodell
versteckt
Java EE
Laufzeitmodell!“
You care! Really!
> Resource Lookup
> Ressource Handling
> Remote Lookup & Remoting
> Pooling
> Interceptoren
> Proxies & Delegates
Client
Routing
Routing
Dispatching
Security
Transaction
POJO
Was wir heute machen
• Klagen auf hohem Niveau...
• Ja, genau da sind wir gestartet!
• Diese Irrwege haben wir uns erlaubt. Leider.
• Genau genommen gibt es vieles noch heute.
• Das können und sollten wir davon lernen.
Und was lernen wir daraus?
Beware of obtrusiveness
> Anforderungen und Fachlichkeit
stehen im Vordergrund
> Frameworks und Technologien mit
großen Auswirkungen auf das
Programmiermodell sind die falschen
Frameworks und Technologien
Und was lernen wir daraus?
Beware of abstractions
> Die Zeit des Versteckens ist längst
vorbei
> Frameworks und Technologie, die
abstrahiert werden müssen, sind die
falschen Frameworks und
Technologien
Und was lernen wir daraus?
Monitor infrastructure code
> Gute Frameworks und Technologien
benötigen wenig Infrastruktur-Code
> Erfordern Frameworks und
Technologien einen hohen Anteil an
Infrastruktur-Code, so sind es die
falschen Frameworks und
Technologien
Und was lernen wir daraus?
Avoid code generation
> Auch generierter Infrastruktur-Code ist
schlechter Code
> q.e.d
> (Dazu gehört auch ein anemic domain
Model)
Und was lernen wir daraus?
If something is too complex
to use or to introduce
and focuses on technology
rather than business requirements
it‘s just too complex!
Gibt es noch
Fragen?
Dann los ...
Das ist ja sooo 200x!
Recommended