Beyond J2EE 1 - uni-potsdam.de · Java EE 5 Platform zNext version of J2EE platform zLatest...

Post on 02-Jun-2020

9 views 0 download

transcript

Beyond J2EE 1.4

Peter TrögerHasso-Plattner-Institute

University of Potsdam

AgendaJ2EE Future

JSR Process, EE 5, EJB 3Sun AppServer 9, JBoss 5, OpenEJB

Dependency Injection & Inversion of ControlHivemind, Spring, PicoContainer, Plexus, Yan, Avalon, Tapestry

Object-relational persistenceHibernate, XMLBeans, Castor

Servlet-based frameworks - Struts

Sources: Sun JSR & GlassFish material, Martin Fowler homepage, different project sites

JSR ProcessJava Community Process (JCP) for development of specifications (since 1995)

Initiation (approved by executive committee)Early draft (for review by the public domain)Public draft (reference implementation, compatibility toolkit)Maintenance (document updates)

Java Specification Request (JSR)Proposed and final specifications for Java platformReview / approval process

Java EE 5 PlatformNext version of J2EE platformLatest versions of Java technology

Enterprise JavaBeans (EJB) 3.0 (JSR-220)JavaServer Faces (JSF) 1.2 (JSR-252)Servlet 2.5JavaServer Pages (JSP) 2.1Java API for Web Services (JAX-WS) 2.0 (JSR-224)Web Services Metadata (JSR-181)Java Architecture for XML Binding (JAXB) 2.0 (JSR-222)Java Persistence 1.0 (JSR-220)Common Annotations 1.0 (JSR-250)Streaming API for XML (StAX) 1.0 (JSR-173)

Java Enterprise System Application Platform Suite

Zur Anzeige wird der QuickTime™ Dekompressor „TIFF (LZW)“

benötigt.

Java EE 5 Major Features

Simplified web service supportMore web service standards supportSimplified EJB developmentNew persistence APIEasier web applications with JavaServer FacesMost specs available for review

Spec at Proposed Final Draft state - Q4 2005Java EE 5 SDK Beta release - Q1 2006Java EE 5 Final release - Q2 2006

Project GlassFishOpen Source Java EE 5 Application ServerSun AppServer Platform Edition 9

Open access to code and binariesIntegrates with NetBeans, Sun Java Studio Enterprise, EclipseStandard Edition

Advanced security, self-managing, self-healingClustering, multi-machine administration

Enterprise EditionSupport for high availability

Grizzly HTTP FrameworkHighly scalable HTTP pathThousands of connections with few Java threadsUses lower level Java NIO primitives

Easy-to-use, high-performance APIs for socket communication

Brings non-blocking sockets to the HTTP processing layerIntegrates with current Apache Tomcat HTTP Connector architecture (Tomcat 3,4,5) Replaces Apache Tomcat Coyote HTTP front-end and thread pool

High-performance buffers and parsing classes

Fast Infoset

Optimized Binary XML transport mechanism -fast web servicesTransparently used by web service communication stackTS-7187

GlassFish JBI IntegrationJava Business Integration (JBI) standard

JSR 208SOA-way of Enterprise Application IntegrationNormalized Message RouterOpenESB - Enterprise Service Bus product, out-of-box support for SOAP and JMS

Java EE web services (EJBs and Servlets) are automatically enabled in Normalized Message RouterJAXWS communication can be routed in-process to Normalized Message Router

EJB 3.0Coordinated in JSR 220POJO-based programming (Plain Old Java Object)

No more Home interfacesBackward compatibilityExtensive use of annotations, reduced need for deployment descriptorsSpecification of default behavior, reduces configuration overheadDependency injection with annotationsImproved EJB-QL (Update, Delete, Inner / Outer Join, SQL)Manager concept for entity bean POJOsLess checked exceptionsImproved performance

Read-only beansRelationship pre-fetching

Annotations as DescriptorsOnly RUNTIME annotations used

Available in class file, read by runtime, simplifies container developmentDeployment descriptors overwrite annotation configurationAnnotation for business interface and referencesBusiness interfaces are optionally generatedLifetime management through annotated functions (@PreDestroy, @PostConstruct)

@Stateless@Remotepublic class HelloWorldBean {

public String getHello() {return „Hello World“; }

@PreDestroy cleanUp() {// logic before destruction of the instance

}}

EJB 3 Example@Stateless public class PayrollBean

implements Payroll { @Resource DataSource empDB; public void setBenefitsDeduction

(int empId, double deduction) { ... Connection conn = empDB.getConnection();... } ... }

----------------------------------------------------@EJB ShoppingCart myCart;

Collection widgets = myCart.startToShop(“widgets”);

EE 5 Web Service Example@WebService(name=”MySimpleWS”);public class RandomClass {

@WebMethodpublic String sayHello(String s) {...} public void unpublished() {...} }

-------------------------------------------------------@WebServiceRef( wsdlLocation=

”http://localhost:8080/SayHelloService?WSDL”);)

static javaone.SayHelloService wsService;

public static void main(String[] args) { javaone.SayHello wsPort = wsService.getHello(); wsPort.sayHello(“FOSS.in Attendees”); }

AOP through Interceptorspublic class MyInterceptor {@AroundInvokepublic Object myInterceptionMethod(

InvocationContext inv) throws Exception {// Code for advicereturn inv.proceed();

}

@Interceptors({„org.example.MyInterceptor"})public class HelloWorldBean {...}

Java 6 (“Mustang”)Coordinated in JSR 270Development snapshots / sources availableNew bytecode verifier for improved performanceJFC / Swing / AWT improvement, Java 2D API, better internationalizationJava Compiler API (JSR 199)XML and Web Services (XML Signatures, JAX-WS 2.0, JAXB 2.0, JDBC 4.0, JMX 1.3)Set of improvements for Java 5 featuresSources available

Open Source Efforts beyond J2EE 1.4

Huge amount of activities to build alternatives to the J2EE 1.4 technologies

Interfaces are good abstraction, but where does the interface implementation class come from ?Heavyweight complexityComponent wiring as main problem

lightweight containers

Component Wiring –The Problempublic interface MovieFinder {

List findAll();

class MovieLister { private MovieFinder finder;

public MovieLister() {finder = new ColonDelimitedMovieFinder("movies1.txt"); }

public Movie[] moviesDirectedBy(String arg) { List allMovies = finder.findAll();for (Iterator it = allMovies.iterator(); it.hasNext();) {

Movie movie = (Movie) it.next(); if (!movie.getDirector().equals(arg)) it.remove();

} return (Movie[]) allMovies.toArray(new

Movie[allMovies.size()]);}

}

Component Wiring Through Dependency Injection

Assembling of ‚plugin‘-style components through „Inversion of Control“ (IoC)

Separate assembler object injects an implementation into the plugin-using componentPrevents tight coupling of specific interface implementation and interface users„Dependency Injection“ pattern

Dependency Injection –Constructor Injection

Parameterized constructor of interface user takes injected implementationConfiguration code about injected objects

In different class (PicoContainer project) In XML file (NanoContainer project)

Client asks IoC framework for instancepublic void testWithPico() {

MutablePicoContainer pico = configureContainer(); MovieLister lister =

(MovieLister)pico.getComponentInstance(MovieLister.class);

Movie[] movies = lister.moviesDirectedBy("Sergio Leone"); ...}

PicoContainer Exampleclass MovieLister...

public MovieLister(MovieFinder finder) {this.finder = finder;

}

class ColonMovieFinder...public ColonMovieFinder(String filename) {

this.filename = filename;}

private MutablePicoContainer configureContainer() {MutablePicoContainer pico = new DefaultPicoContainer();Parameter[] finderParams =

{new ConstantParameter("movies1.txt")};pico.registerComponentImplementation(

MovieFinder.class, // the interfaceColonMovieFinder.class, // the implementationfinderParams);

pico.registerComponentImplementation(MovieLister.class);return pico;

}

Dependency Injection –Setter Injection

Assembler hands dependency instances through a setter method after instantiationNo atomic setting like with constructor injectionMain concept in the Spring framework

public void testWithSpring() throws Exception {

ApplicationContext ctx =

new FileSystemXmlApplicationContext("spring.xml");

MovieLister lister = (MovieLister) ctx.getBean("MovieLister");

Movie[] movies = lister.moviesDirectedBy("Sergio Leone");

}

Spring Framework Exampleclass MovieLister...

private MovieFinder finder;public void setFinder(MovieFinder finder) {

this.finder = finder;}

class ColonMovieFinder...public void setFilename(String filename) {

this.filename = filename;}

<beans><bean id="MovieLister" class="spring.MovieLister">

<property name="finder"><ref local="MovieFinder"/></property></bean><bean id="MovieFinder" class="spring.ColonMovieFinder">

<property name="filename"><value>movies1.txt</value></property></bean>

</beans>

Dependency Injection –Interface Injection

Specific interface for injection of an interface-implementing instanceInjection-interface is implemented by plugin-interface userUsed in Apache Avalon project

class IfaceTester {

public void testIface() {

configureContainer();

MovieLister lister =

(MovieLister)container.lookup("MovieLister");

Movie[] movies = lister.moviesDirectedBy("Sergio Leone");}

}

Avalon Example

public interface InjectFinder { void injectFinder(MovieFinder finder);

} class MovieLister implements InjectFinder {

public void injectFinder(MovieFinder finder) {this.finder = finder;

}}

public interface InjectFinderFilename {void injectFilename (String filename);

}class ColonMovieFinder implements MovieFinder, InjectFinderFilename {

public void injectFilename(String filename) {this.filename = filename;

}}

Avalon Configuration Exampleclass Tester {

private Container container;private void configureContainer() {

container = new Container();registerComponents();registerInjectors();container.start(); }

private void registerComponents() {container.registerComponent("MovieLister",

MovieLister.class);container.registerComponent("MovieFinder",

ColonMovieFinder.class); }

private void registerInjectors() {container.registerInjector(InjectFinder.class,

container.lookup("MovieFinder"));container.registerInjector(InjectFinderFilename.class,

new FinderFilenameInjector());}

Component Wiring Through Service Locator

One well-known registry object knows how to get hold of all the objects the application might need

Service Locator Exampleclass MovieLister {

MovieFinder finder = ServiceLocator.movieFinder(); }

class ServiceLocator {private static ServiceLocator soleInstance; private MovieFinder movieFinder;

public static void load(ServiceLocator arg) { soleInstance = arg; }

public ServiceLocator(MovieFinder movieFinder) {this.movieFinder = movieFinder;

}

public static MovieFinder movieFinder() {return soleInstance.movieFinder;

}}

Service Locator Client Exampleclass Tester {

private void configure() {ServiceLocator.load(

new ServiceLocator(new ColonMovieFinder("movies1.txt")));

}

public void testSimple() {

configure();

MovieLister lister = new MovieLister();Movie[] movies = lister.moviesDirectedBy("Sergio Leone");

}

}

Dynamic Service Locator Exampleclass ServiceLocator {

private static ServiceLocator soleInstance;

private Map services = new HashMap();

public static void load(ServiceLocator arg) {

soleInstance = arg; }

public static Object getService(String key){

return soleInstance.services.get(key); }

public void loadService (String key, Object service) {services.put(key, service); }

Dynamic Service Locator Client Exampleclass Tester {

private void configure() {

ServiceLocator locator = new ServiceLocator(); locator.loadService("MovieFinder",

new ColonMovieFinder("movies1.txt")); ServiceLocator.load(locator);

}

class MovieLister() {MovieFinder finder = (MovieFinder)

ServiceLocator.getService("MovieFinder");}

Service Locator vs. Dependency Injection

Decoupled application code and interface implementationService Locator

Application class asks explicitly for implementationEvery plugin depends on a specific locator –non-planned application usage might be hard

Dependency InjectionImplicit availability of interface implementationHard to debugVery easy testing (stubs / mocks for implementation)

Other discussionsConstructor vs. setter injection (related to OO principles)Code vs. configuration files

Pico Container

Small containerConfiguration support through Java objectsPreferred mode of constructor injectionNice autowiring

Spring Framework 1.2Based on J2EE practice book:Rod Johnson, Expert One-on-One J2EE Design and Development, WROX, October 2002, ISBN: 0-7645-4385-7Layered Java/J2EE application framework

Use only parts of it if you like toOpen Source project since 2003Functionality can be used in any J2EE server, most also in non-managed environmentsReusable business POJOs, based on layered Spring architecture featuresJavaBeans for application configuration (IoC)Better testability of developed codeStrict usage of interface approachAvoid checked exception concept

Spring Framework FeaturesLightweight container

Centralized, automated configuration and plumbingPOJOs as components

Common abstraction layer for transactions, not tied to J2EE (in contrast to JTA / EJB)JDBC abstraction layer with better error handlingAOP support for all objectsIntegration of other technologies (Commons Logging, Hibernate, JDO)MVC web application frameworkIndependent from underlying application serverActs as ‚glue code‘ for J2EE APIs and open source frameworks

Spring Feature Stack

Layered Spring Application

Remoting Usage Scenario

POJO Reuse ScenarioWrap existing POJOs in stateless session EJBsAccess and abstraction layer

Spring PackagesCore: bean container functionality, support for dependency injectiobContext: resembling of JNDI, supports event propagation, text messaging and wiringDAO: JDBC abstraction layerORM: Integration layers for O/R solutionsAOP: Method interceptors, pointcutsWeb / Web MVC: Web-oriented integration features

Spring Lightweight ContainerBeanFactory as container (instantiation, configuration, management)

Multiple implementations (e.g. XmlBeanFactory)Uses configuration data about dependenciesSupports different injection paradigmsSupports autowiring (by inject property name, by property type, by constructor argument type) Supports dependency checking

Resource res = new FileSystemResource("beans.xml");XmlBeanFactory factory = new XmlBeanFactory(res);

Spring DataSource Example<beans>

<bean id="myDataSource"class="org.apache.commons.dbcp.BasicDataSource"destroy-method="close"><property name="driverClassName" value="com.mysql.jdbc.Driver" /><property name="url" value="jdbc:mysql://localhost:3306/mydb" /><property name="username" value="someone" />

</bean><bean id="exampleDataAccessObject"

class="example.ExampleDataAccessObject"><property name="dataSource" ref="myDataSource" />

</bean><bean id="exampleBusinessObject"

class="example.ExampleBusinessObject"><property name="dataAccessObject">

<ref bean="exampleDataAccessObject"/></property><property name="exampleParam"><value>10</value></property>

</bean></beans>

Spring DataSource Example

<beans><bean id="myDataSource"

class="org.springframework.jndi.JndiObjectFactoryBean"><property name="jndiName" value="jdbc/myDataSource" />

</bean><bean id="exampleDataAccessObject"

class="example.ExampleDataAccessObject"><property name="dataSource" ref="myDataSource" />

</bean><bean id="exampleBusinessObject"

class="example.ExampleBusinessObject"><property name="dataAccessObject">

<ref bean="exampleDataAccessObject"/></property><property name="exampleParam"><value>10</value></property>

</bean></beans>

Spring DataSource Client

public class ExampleBusinessObject implements MyBusinessObject {

private ExampleDataAccessObject dao;

private int exampleParam;

public void setDataAccessObject(ExampleDataAccessObject dao) {

this.dao = dao;}

public void setExampleParam(int exampleParam) {

this.exampleParam = exampleParam;

}

public void myBusinessMethod() {

// do stuff using dao}}

EJB Implementation with Spring

EJBs are hard to test outside the containerSolution: Refactor business logic into POJOs behind EJB facades, including IoC patternSpring superclass implements EJB lifecylce methodsStill needed to write according ejb-jar.xml

import org.springframework.ejb.support.AbstractStatelessSessionBean;

public class MyEJB extends AbstractStatelessSessionBeanimplements MyBusinessInterface { private MyPOJO myPOJO; protected void onEjbCreate() {

this.myPOJO = getBeanFactory().getBean("myPOJO"); } public void myBusinessMethod() {

this.myPOJO.invokeMethod(); }}

Jakarta HiveMindApache Jakarta projectService and configuration framework

HiveMind services are POJOsFramework covers instantiation and configuration

Supports application development, HiveMind is not an application serverService collaboration through dependency injection microkernelConversion of user-defined configuration data into data objectsModule deployment descriptors parsed by startup logic, the ‚core‘ of HiveMindControlled instantiation and initialization of Java code

HiveMind Details

Zur Anzeige wird der QuickTime™ Dekompressor „TIFF (Unkomprimiert)“

benötigt.

Flexible, loosely-coupled configuration management and services frameworkHiveMind might be used to front EJBs, and therefore is thread-safeDependency injection for beans or larger components, called modulesEnforces interface usageStrong relation to Apache Jakarta Tapestry(Howard Lewis Ship)

HiveMind ResponsibilitiesCode

Obtain a reference to the registry SingletonKnow the ID / class type of the service to accessPass the interface class

HiveMindFind and create the according implementation objectOperate in a thread-safe mannerDo useful error reportingSupport documentation of linked extension points (HiveDoc)

HiveMind Service Referring

private SomeOtherService _otherService;public String myMethod(String param){if (_otherService == null)

_otherService = // Lookup other service . . ._otherService.doSomething(. . .);. . .

}

private SomeOtherService _otherService;public void setOtherService(SomeOtherService otherService){ _otherService = otherService; }

public String myMethod(String param){_otherService.doSomething(. . .);. . .

}

HiveMind Wiring Example (1)

package hivemind.examples;public interface Adder {

public int add(int arg0, int arg1); }

package hivemind.examples.impl;import hivemind.examples.Adder;public class AdderImpl implements Adder { public int add(int arg0, int arg1) {return arg0 + arg1;}

}

package hivemind.examples;public interface Calculator extends Adder, Subtracter{

}

HiveMind Wiring Example (2)package hivemind.examples.impl;import hivemind.examples.*;

public class CalculatorImpl implements Calculator{private Adder _adder; private Subtracter _subtracter;

public void setAdder(Adder adder){ _adder = adder; }

public void setSubtracter(Subtracter subtracter){ _subtracter = subtracter; }

public int add(int arg0, int arg1){ return _adder.add(arg0, arg1); }

public int subtract(int arg0, int arg1){ return _subtracter.subtract(arg0, arg1); }

}

HiveMind Wiring Example (3)

<?xml version="1.0"?><module id="hivemind.examples" version="1.0.0" package="hivemind.examples">

<service-point id="Adder" interface="Adder"><create-instance class="impl.AdderImpl"/><interceptor service-id="hivemind.LoggingInterceptor"/>

</service-point>

<service-point id="Subtracter" interface="Subtracter"><create-instance class="impl.SubtracterImpl"/><interceptor service-id="hivemind.LoggingInterceptor"/>

</service-point>

<service-point id="Calculator" interface="Calculator"><invoke-factory><!-- Autowires service properties based on interface! --><construct class="impl.CalculatorImpl"/>

</invoke-factory><interceptor service-id="hivemind.LoggingInterceptor"/>

</service-point></module>

HiveMind Wiring Example (4)package hivemind.examples;

import org.apache.hivemind.Registry;import org.apache.hivemind.impl.RegistryBuilder;

public class Main{public static void main(String[] args){int arg0 = Integer.parseInt(args[0]);int arg1 = Integer.parseInt(args[1]);

Registry registry = RegistryBuilder.constructDefaultRegistry();

Calculator c = (Calculator) registry.getService(Calculator.class);

System.out.println("Inputs " + arg0 + " and " + arg1);

System.out.println("Add : " + c.add(arg0, arg1));System.out.println("Subtract: " + c.subtract(arg0, arg1));

}}

HiveMind Logging Interceptorpublic String myMethod(String param) {

if (LOG.isDebugEnabled())

LOG.debug("myMethod(" + param + ")"); String result =

// . . .

if (LOG.isDebugEnabled())

LOG.debug("myMethod() returns " + result);

return result;

}

<service-point id="MyService" interface="com.myco.MyServiceInterface">

<create-instance class="com.myco.impl.MyServiceImpl"/>

<interceptor service-id="hivemind.LoggingInterceptor"/>

</service-point>

O/R Mapping Projects

Object-relational mapping allows OO-view on tables and relations from databasesCrucial for persistency implementation

HibernatePopular open source (LGPL) O/R mapping toolUsable standalone, for POJOs and for EJBsPortable SQL extension as query language (HQL)Mapping definition through XML configuration files, with own type identifiersEasier than hand-written SQL/JDBC, more powerful that EJB 2.1 entity beans, over 15 databases supportedIntegrated caching and monitoring architectureUsable from servlets or EJB session bean façadeCompatible with open source connection poolsNo backward-compatibility between versionsContributors to JSR 220 specification, implementation in JBossEJB3 containerPart of JBoss Enterprise Middleware System

Hibernate ApproachesTop-Down: Start with JavaBeansBottom-Up: Start with relational schemaMiddle-Out: Start with mapping definitionMeet-In-Middle: Start with JavaBeans and Schema

Using Hibernate Mappings in Applications

SessionFactory: Manages all mappings, configurable through filesSession: Boundary between database and applicationTransaction: JDBC, JTA or CORBA transactions, created from session

try {SessionFactory sf =

new Configuration().configure().buildSessionFactory();} catch (HibernateException e) {…}

Session sess = sf.openSession();Transaction trx = sess.beginTransaction();Band band = new Band();band.setName("deCON");

sess.save(band);trx.commit();sess.close();

Hibernate XML Mapping File<hibernate-mapping schema="allschools"><class name="net.allschools.hbn.manual.Comment“

table="COMMENT"><id name="id" column="ID" type="integer"><generator class="sequence">

<param name="sequence">allschools.comment_id_seq</param></generator>

</id><property name="commentDate" column="COMMENT_DATE"

type="date" not-null="true" /><property name="title" column="TITLE" type="string“

not-null="true"/><property name="text" column="COMMENT_TEXT" type="string"

not-null="true"/><property name="userName" column="USER_NAME" type="string"

not-null="true"/><many-to-one name="release" column="RELEASE_ID“

class="net.allschools.hbn.manual.Release"/></class>…

</hibernate-mapping>

Hibernate RelationsOne-to-one

No foreign key specificationCascade definition regarding Update and Delete

Many-to-one / many-to-manyNeeds collection class member in the JavaBean representation

<class name="net.allschools.hbn.manual.Release" table="RELEASE"><one-to-one name="cover"

class="net.allschools.hbn.manual.Image“ cascade="none"/>

<set name="comments" cascade="none" lazy="true"><key column="release_id"/><one-to-many class="net.allschools.hbn.manual.Comment"/>

</set>

<set name="bands" table="RELEASE_BANDS" cascade="none" lazy="true"><key column="RELEASE_ID"/><many-to-many class="net.allschools.hbn.manual.Band“ column="BAND_ID"/>

</set></class>

Hibernate SessionFactoryConfiguration

<?xml version='1.0' encoding='utf-8'?><!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD

2.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-2.0.dtd"><hibernate-configuration><session-factory name="java:comp/env/hibernate/SessionFactory"><!-- properties --><property name="hibernate.connection.driver_class">org.postgresql.Driver</property><property name="hibernate.connection.url">jdbc:postgresql:allschools</property><property name="hibernate.connection.username">username</property><property name="hibernate.connection.password">passwort</property><property name="hibernate.connection.pool_size">5</property><property name="dialect">net.sf.hibernate.dialect.PostgreSQLDialect</property><property name="show_sql">true</property><property name="use_outer_join">true</property><!-- mapping files --><mapping resource="Mappings.hbm.xml"/></session-factory></hibernate-configuration>

Hibernate Features

Hibernate Query LanguageOO-dialect of SQL – classes, properties, polymorphism, relational operations, subqueriesNative SQL with pass-through still allowed

Criteria queries (QBC)Framework for query objectsIncludes ‘query by example’

Hibernate Query LanguageList allAuctions =

session.createQuery(“from AuctionItem”).list();

select itemfrom AuctionItem itemjoin item.bids as bid

where item.description like “Hibernate%”and bid.amount > 100

XML BeansApache XMLBeans project, donated by BEABinding tool for Java object-view on XML dataMajor APIs

Strongly-typed access with XMLObject base typeXML infoset access through XMLCursor interfaceXML schema object model acces (SchemaType interface)

XML infoset is FULLY preservedXML data is still represented in memory

JAXB supports only parts of XML schemaNo marshalling / demarshalling needed

XMLBeans StepsCompile schema definitionscomp -out employeeschema.jar employeeschema.xsdWrite code

File xmlFile = new File("c:\employees.xml");

// Bind the instance to the generated XMLBeans types. EmployeesDocument empDoc =

EmployeesDocument.Factory.parse(xmlFile);

// Get and print pieces of the XML instance. Employees emps = empDoc.getEmployees(); Employee[] empArray = emps.getEmployeeArray(); for (int i = 0; i < empArray.length; i++) {

System.out.println(empArray[i]); }

XMLBeans Mapping of Schema Built-In Types

Servlet-based Technology

Apache Jakarta StrutsApplication framework for building web applications on-top-of J2EE web containerPrebuild components to be assembled to web applications -> time savingMVC design pattern as basic approach

Model components are Java classesView components are JSP files (large support for Struts custom JSP tags)Controller components are special “action classes”Struts configuration file for assembling

Several forks, confusing amount of sub-projects

Struts View Component<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %> <%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %> <%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %><html:html locale="true"> <head><title><bean:message key="hello.jsp.title"/></title><html:base/> </head> <body bgcolor="white"><p> <h2><bean:message key="hello.jsp.page.heading"/></h2><p><html:errors/><p> <logic:present name="examples.hello" scope="request"> <h2> Hi <bean:write name="examples.hello" property="person" />!<p> </h2>

</logic:present> <html:form action="/HelloWorld.do?action=gotName" focus="username" ><bean:message key="hello.jsp.prompt.person"/> <html:text property="person" size="16" maxlength="16"/><br> <html:submit property="submit" value="Submit"/> <html:reset/>

</html:form><br> </body> </html:html>

Struts Form Beanimport javax.servlet.http.HttpServletRequest;import org.apache.struts.action.*;

public final class HelloForm extends ActionForm {private String person = null;public String getPerson() {return (this.person);}public void setPerson(String person) {this.person = person;}

// overriden from ActionFormpublic void reset(ActionMapping mapping, HttpServletRequest request) {this.person = null;}

// overriden from ActionFormpublic ActionErrors validate(ActionMapping mapping,HttpServletRequest request) {ActionErrors errors = new ActionErrors();if ((person == null) || (person.length() < 1))

errors.add("person", new ActionError("examples.hello.no.person.error"));return errors;

}}

Struts Controller Componentpackage examples.hello;import javax.servlet.*;import org.apache.struts.action.*; …

public final class HelloAction extends Action {public ActionForward execute(ActionMapping mapping, // config file

ActionForm form, // form beanHttpServletRequest request,HttpServletResponse response) throws Exception {

ActionErrors errors = new ActionErrors();String person = (String) PropertyUtils.getSimpleProperty(form, "person");String badPerson = "Atilla the Hun";if (person.equals(badPerson)) { // business logic

errors.add("person", new ActionError("dont.talk.to.atilla", badPerson ));saveErrors(request, errors);return (new ActionForward(mapping.getInput())); }

HelloModel hm = new HelloModel(); // interact with modelhm.setPerson(person); hm.saveToPersistentStore();request.setAttribute( Constants.HELLO_KEY, hm); // pass data to view component

return (mapping.findForward("SayHello")); // forward control}}

Struts Config File<?xml version="1.0" encoding="ISO-8859-1" ?> <struts-config>

<!-- === Form Bean Definitions === --> <form-beans>

<form-bean name="HelloForm“type="examples.hello.HelloForm"/>

</form-beans> <!-- === Action Mapping Definitions === --> <action-mappings>

<!-- Say Hello! --> <action path = "/HelloWorld"

type = "examples.hello.HelloAction" name = "HelloForm" scope = "request" validate = "true" input = "/hello.jsp">

<forward name="SayHello" path="/hello.jsp" /> </action>

</action-mappings> <message-resources parameter="examples.hello.Application"/>

</struts-config>