Beyond J2EE 1.4 Peter Trger Hasso-Plattner-Institute University of - - PowerPoint PPT Presentation
Beyond J2EE 1.4 Peter Trger Hasso-Plattner-Institute University of - - PowerPoint PPT Presentation
Beyond J2EE 1.4 Peter Trger Hasso-Plattner-Institute University of Potsdam Agenda J2EE Future JSR Process, EE 5, EJB 3 Sun AppServer 9, JBoss 5, OpenEJB Dependency Injection & Inversion of Control Hivemind, Spring,
Agenda
J2EE Future
JSR Process, EE 5, EJB 3 Sun AppServer 9, JBoss 5, OpenEJB
Dependency Injection & Inversion of Control
Hivemind, Spring, PicoContainer, Plexus, Yan,
Avalon, Tapestry
Object-relational persistence
Hibernate, XMLBeans, Castor
Servlet-based frameworks - Struts Sources: Sun JSR & GlassFish material, Martin
Fowler homepage, different project sites
JSR Process
Java 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 platform Review / approval process
Java EE 5 Platform
Next version of J2EE platform Latest versions of Java technology
Enterprise JavaBeans (EJB) 3.0 (JSR-220) JavaServer Faces (JSF) 1.2 (JSR-252) Servlet 2.5 JavaServer Pages (JSP) 2.1 Java 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 support More web service standards support Simplified EJB development New persistence API Easier web applications with JavaServer Faces Most specs available for review
Spec at Proposed Final Draft state - Q4 2005 Java EE 5 SDK Beta release - Q1 2006 Java EE 5 Final release - Q2 2006
Project GlassFish
Open Source Java EE 5 Application Server Sun AppServer Platform Edition 9
Open access to code and binaries
Integrates with NetBeans, Sun Java Studio
Enterprise, Eclipse
Standard Edition
Advanced security, self-managing, self-healing Clustering, multi-machine administration
Enterprise Edition
Support for high availability
Grizzly HTTP Framework
Highly scalable HTTP path Thousands of connections with few Java threads Uses lower level Java NIO primitives
Easy-to-use, high-performance APIs for socket
communication
Brings non-blocking sockets to the HTTP processing
layer
Integrates 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 services
Transparently used by web service
communication stack
TS-7187
GlassFish JBI Integration
Java Business Integration (JBI) standard
JSR 208 SOA-way of Enterprise Application Integration Normalized Message Router OpenESB - 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 Router
JAXWS communication can be routed in-process to
Normalized Message Router
EJB 3.0
Coordinated in JSR 220 POJO-based programming (Plain Old Java Object)
No more Home interfaces
Backward compatibility Extensive use of annotations, reduced need for deployment
descriptors
Specification of default behavior, reduces configuration overhead Dependency injection with annotations Improved EJB-QL (Update, Delete, Inner / Outer Join, SQL) Manager concept for entity bean POJOs Less checked exceptions Improved performance
- Read-only beans
- Relationship pre-fetching
Annotations as Descriptors
- Only RUNTIME annotations used
- Available in class file, read by runtime, simplifies container development
- Deployment descriptors overwrite annotation configuration
- Annotation for business interface and references
- Business interfaces are optionally generated
- Lifetime management through annotated functions
(@PreDestroy, @PostConstruct)
@Stateless @Remote public 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 { @WebMethod public 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 Interceptors
public class MyInterceptor { @AroundInvoke public Object myInterceptionMethod( InvocationContext inv) throws Exception { // Code for advice return inv.proceed(); } @Interceptors({„org.example.MyInterceptor"}) public class HelloWorldBean {...}
Java 6 (“Mustang”)
Coordinated in JSR 270 Development snapshots / sources available New bytecode verifier for improved performance JFC / Swing / AWT improvement, Java 2D API,
better internationalization
Java 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 features Sources 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 complexity Component wiring
as main problem lightweight containers
Component Wiring – The Problem
public 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 component
Prevents tight coupling of specific interface
implementation and interface users
„Dependency Injection“ pattern
Dependency Injection – Constructor Injection
Parameterized constructor of interface user
takes injected implementation
Configuration code about injected objects
In different class (PicoContainer project) In XML file (NanoContainer project)
Client asks IoC framework for instance
public void testWithPico() { MutablePicoContainer pico = configureContainer(); MovieLister lister = (MovieLister)pico.getComponentInstance(MovieLister.class); Movie[] movies = lister.moviesDirectedBy("Sergio Leone"); ...}
PicoContainer Example
class 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 interface ColonMovieFinder.class, // the implementation finderParams); pico.registerComponentImplementation(MovieLister.class); return pico; }
Dependency Injection – Setter Injection
Assembler hands dependency instances
through a setter method after instantiation
No atomic setting like with constructor injection Main 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 Example
class 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 instance
Injection-interface is implemented by plugin-
interface user
Used 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 Example
class 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 Example
class 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 Example
class 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 Example
class 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 Example
class 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
implementation
Service Locator
Application class asks explicitly for implementation Every plugin depends on a specific locator –
non-planned application usage might be hard
Dependency Injection
Implicit availability of interface implementation Hard to debug Very easy testing (stubs / mocks for implementation)
Other discussions
Constructor vs. setter injection (related to OO principles) Code vs. configuration files
Pico Container
Small container Configuration support through Java objects Preferred mode of constructor injection Nice autowiring
Spring Framework 1.2
Based on J2EE practice book:
Rod Johnson, Expert One-on-One J2EE Design and Development, WROX, October 2002, ISBN: 0-7645-4385-7
Layered Java/J2EE application framework
- Use only parts of it if you like to
Open Source project since 2003
Functionality can be used in any J2EE server, most also in
non-managed environments
Reusable business POJOs, based on layered Spring
architecture features
JavaBeans for application configuration (IoC) Better testability of developed code Strict usage of interface approach Avoid checked exception concept
Spring Framework Features
Lightweight container
- Centralized, automated configuration and plumbing
- POJOs as components
Common abstraction layer for transactions, not tied to J2EE (in
contrast to JTA / EJB)
JDBC abstraction layer with better error handling AOP support for all objects Integration of other technologies (Commons Logging, Hibernate,
JDO)
MVC web application framework Independent from underlying application server Acts as ‚glue code‘ for J2EE APIs and open source frameworks
Spring Feature Stack
Layered Spring Application
Remoting Usage Scenario
POJO Reuse Scenario
Wrap existing POJOs in stateless session EJBs Access and abstraction layer
Spring Packages
Core: bean container functionality, support for
dependency injectiob
Context: resembling of JNDI, supports event
propagation, text messaging and wiring
DAO: JDBC abstraction layer ORM: Integration layers for O/R solutions AOP: Method interceptors, pointcuts Web / Web MVC: Web-oriented integration
features
Spring Lightweight Container
BeanFactory as container
(instantiation, configuration, management)
Multiple implementations (e.g. XmlBeanFactory) Uses configuration data about dependencies Supports different injection paradigms Supports 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 container Solution: Refactor business logic into POJOs behind EJB
facades, including IoC pattern
Spring superclass implements EJB lifecylce methods Still needed to write according ejb-jar.xml
import org.springframework.ejb.support.AbstractStatelessSessionBean; public class MyEJB extends AbstractStatelessSessionBean implements MyBusinessInterface { private MyPOJO myPOJO; protected void onEjbCreate() { this.myPOJO = getBeanFactory().getBean("myPOJO"); } public void myBusinessMethod() { this.myPOJO.invokeMethod(); }}
Jakarta HiveMind
Apache Jakarta project Service and configuration framework
HiveMind services are POJOs Framework covers instantiation and configuration
Supports application development, HiveMind is not
an application server
Service collaboration through dependency injection
microkernel
Conversion of user-defined configuration data into
data objects
Module deployment descriptors parsed by startup
logic, the ‚core‘ of HiveMind
Controlled 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 framework
HiveMind might be used to front EJBs, and therefore
is thread-safe
Dependency injection for
beans or larger components, called modules
Enforces interface usage Strong relation to
Apache Jakarta Tapestry (Howard Lewis Ship)
HiveMind Responsibilities
Code
Obtain a reference to the registry Singleton Know the ID / class type of the service to access Pass the interface class
HiveMind
Find and create the according implementation object Operate in a thread-safe manner Do useful error reporting Support 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 Interceptor
public 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 databases
Crucial for persistency implementation
Hibernate
Popular open source (LGPL) O/R mapping tool Usable standalone, for POJOs and for EJBs Portable SQL extension as query language (HQL) Mapping definition through XML configuration files,
with own type identifiers
Easier than hand-written SQL/JDBC, more powerful that EJB 2.1
entity beans, over 15 databases supported
Integrated caching and monitoring architecture Usable from servlets or EJB session bean façade Compatible with open source connection pools No backward-compatibility between versions Contributors to JSR 220 specification, implementation in JBoss
EJB3 container
Part of JBoss Enterprise Middleware System
Hibernate Approaches
Top-Down: Start with JavaBeans Bottom-Up: Start with relational schema Middle-Out: Start with mapping definition Meet-In-Middle: Start with JavaBeans and Schema
Using Hibernate Mappings in Applications
SessionFactory: Manages all mappings, configurable
through files
Session: Boundary between database and application Transaction: 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 Relations
One-to-one
- No foreign key specification
- Cascade definition regarding Update and Delete
Many-to-one / many-to-many
- Needs 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 SessionFactory Configuration
<?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 Language
OO-dialect of SQL – classes, properties,
polymorphism, relational operations, subqueries
Native SQL with pass-through still allowed
Criteria queries (QBC)
Framework for query objects Includes ‘query by example’
Hibernate Query Language
List allAuctions = session.createQuery(“from AuctionItem”).list(); select item from AuctionItem item join item.bids as bid where item.description like “Hibernate%” and bid.amount > 100
XML Beans
Apache XMLBeans project, donated by BEA Binding tool for Java object-view on XML data Major APIs
Strongly-typed access with XMLObject base type XML infoset access through XMLCursor interface XML schema object model acces (SchemaType interface)
XML infoset is FULLY preserved
XML data is still represented in memory
JAXB supports only parts of XML schema No marshalling / demarshalling needed
XMLBeans Steps
Compile schema definition
scomp -out employeeschema.jar employeeschema.xsd
Write 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 Struts
Application framework for building web applications
- n-top-of J2EE web container
Prebuild components to be assembled to web
applications -> time saving
MVC design pattern as basic approach
Model components are Java classes View 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 Bean
import 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 ActionForm public void reset(ActionMapping mapping, HttpServletRequest request) { this.person = null;} // overriden from ActionForm public 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 Component
package 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 bean HttpServletRequest 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 model hm.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>