127
- Page i Document Version 0.401 dated 12/04/2005 EUROPEAN COMMISSION DIRECTORATE-GENERAL INFORMATICS Infrastructure Directorate Technical solutions and office systems Reference Application Architecture

Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

  • Upload
    others

  • View
    6

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

- Page i Document Version 0.401 dated 12/04/2005

EUROPEAN COMMISSION DIRECTORATE-GENERAL INFORMATICS Infrastructure Directorate Technical solutions and office systems

Reference Application Architecture

Page 2: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 2 of 127

1. TABLE OF CONTENTS

1. TABLE OF CONTENTS.......................................................................................................................... 2

2. DEFINITION ............................................................................................................................................ 4

3. WHAT ARE THE OPTIONS? ................................................................................................................ 4

4. WHAT IS GENERATED?....................................................................................................................... 5

4.1. Ant ........................................................................................................................................................... 6 4.2. Database scripts ....................................................................................................................................... 7 4.3. Libraries ................................................................................................................................................... 7 4.4. Sources..................................................................................................................................................... 7

5. ARCHITECTURE.................................................................................................................................... 9

5.1. Tiers ......................................................................................................................................................... 9 5.2. Layers..................................................................................................................................................... 10 5.2.1. Data Access Layer .............................................................................................................................. 11 5.2.1.1. Domain package............................................................................................................................... 11 5.2.1.2. DAO package................................................................................................................................... 14 5.2.1.3. Participants and responsibilities....................................................................................................... 15 5.2.1.4. Example: getNotes ........................................................................................................................... 16 5.2.1.5. Dependencies and configuration...................................................................................................... 18 5.2.1.6. DataSource....................................................................................................................................... 24 5.2.1.6.1. Basic:............................................................................................................................................................... 24 5.2.1.6.2. Jndi: ................................................................................................................................................................. 24 5.2.1.7. DataAccess....................................................................................................................................... 27 5.2.1.7.1. JDBC:.............................................................................................................................................................. 27 5.2.1.7.2. Hibernate: ........................................................................................................................................................ 27 5.2.1.7.3. Ejb2cmp: ......................................................................................................................................................... 32 5.2.1.8. Logging............................................................................................................................................ 46 5.2.2. Services Layer..................................................................................................................................... 49 5.2.2.1. Services Package.............................................................................................................................. 49 5.2.2.2. Participants and responsibilities....................................................................................................... 50 5.2.2.3. Example: getNotes ........................................................................................................................... 51 5.2.2.4. Dependencies and configuration...................................................................................................... 54 5.2.2.5. Transaction Management................................................................................................................. 55 5.2.2.6. Logging (AOP) ................................................................................................................................ 62 5.2.2.7. Remote EJB Business Logic ............................................................................................................ 68 5.2.3. User Interface Layer ........................................................................................................................... 73 5.2.3.1. Controller Package........................................................................................................................... 73 5.2.3.2. Participants and responsibilities....................................................................................................... 75 5.2.3.3. Example: getNotes ........................................................................................................................... 76

Page 3: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 3 of 127

5.2.3.4. Dependencies and configuration...................................................................................................... 78 5.2.3.5. Error Handling ................................................................................................................................. 85 5.2.3.6. Context information ......................................................................................................................... 86 5.2.3.7. Taglibs ............................................................................................................................................. 89 5.2.3.8. Security: Ecas authentication ........................................................................................................... 91 5.2.3.9. Internationalization (i18n) ............................................................................................................... 98 5.2.3.9.1. Request Character Encoding ........................................................................................................................... 98 5.2.3.9.2. File encoding................................................................................................................................................... 98 5.2.3.9.3. Language Selection ......................................................................................................................................... 99 5.2.3.9.4. DatabaseMessageSource ............................................................................................................................... 103 5.2.3.10. Struts MVC .................................................................................................................................. 108 5.2.3.10.1. Tiles............................................................................................................................................................. 119 5.2.3.10.2. Validator...................................................................................................................................................... 121

6. APPENDIX A - NAMING CONVENTIONS..................................................................................... 123

7. INDEX.................................................................................................................................................... 124

7.1. Figures ................................................................................................................................................. 124 7.2. Configuration Files .............................................................................................................................. 125

8. REFERENCES...................................................................................................................................... 127

8.1. Books ................................................................................................................................................... 127 8.2. Links .................................................................................................................................................... 127

Page 4: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 4 of 127

2. DEFINITION

The reference application is an application that generates a java web application project skeleton based on selected technologies, strategies and functionalities.

3. WHAT ARE THE OPTIONS?

The preferences.properties file is located in the root directory of the refapp project. It is a standard java properties file. Most of the modules can simply be switched on or off by setting the corresponding use.* property to true or false. E.g.: use.hibernate = true

The contents of the file looks like this: #------------ # preferences #------------ # an application name in lower case app.name = sampleapp # The use.* preferences can be 'true' or 'false'. use.cactus = false use.canoo = false use.codechecking = true use.databaseMessageSource = false use.dbunit = true use.documentation = true use.ecas = true use.ejb = false use.ergonomics = true use.ftp = true use.hsql = false use.junit = true use.logging = false use.metadata = false use.oracle = true use.samples = true use.spring = true use.springMVC = true use.struts = false use.transaction = false

Page 5: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 5 of 127

# The webserver can be 'weblogic' or 'tomcat'. webserver = weblogic webserver.port = 7001 webserver.port.ssl = 7002 # FTP specific values; only fill in when use.ftp is true! ftp.server = localhost ftp.port = 21 ftp.user = anonymous ftp.password = ftp.dir = / # Spring specific values; only fill in when use.spring is true! spring.log4j.logfile = ${app.name}.log spring.jdbc.driverClassName = oracle.jdbc.driver.OracleDriver spring.jdbc.url = jdbc:oracle:thin:@devora.cc.cec.eu.int:1522:WEBUCOMD spring.jdbc.username = SCOTT spring.jdbc.password = TIGER #spring.jdbc.driverClassName = org.hsqldb.jdbcDriver #spring.jdbc.url = jdbc:hsqldb:hsql://localhost/${app.name} #spring.jdbc.username = sa #spring.jdbc.password = # The dataAccess can be 'jdbc', 'hibernate' or 'ejb2cmp' dataAccess = jdbc # The dataSource can be 'basic' or 'jndi'. dataSource = basic dataSource.jndiName = jdbc/${app.name} # Tomcat specific values; only fill in when tomcat is chosen as webserver preference! tomcat.manager.url = http://localhost:8080/manager tomcat.manager.username = tomcat tomcat.manager.password = tomcat # Weblogic specific values; only fill in when weblogic is chosen as webserver preference! weblogic.manager.url = t3://localhost:7001 weblogic.manager.username = system weblogic.manager.password = security weblogic.manager.target.servers = myserver

4. WHAT IS GENERATED?

In the picture below you can see the general directory structure of the generated project.

Page 6: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 6 of 127

There are 4 major parts. Ant related (ant distribution, build scripts and configuration files), database (sql scripts), libraries (jar files) and sources (java, jsp, …)

4.1. Ant

1. Ant Distribution

The ant directory contains a complete ant binary distribution.

There are several reasons why we make the ant distribution part of the project. First of all you can work on several projects each of them working with a different version of ant. Depending on the selected modules some extra libraries are copied in the ant/lib subdirectory. Different projects will need different libraries or different versions of the same libraries.

2. Main build script and properties file

The project root directory contains the main ant build script and properties file.

The setenv.bat batch file sets the ant_home and path environment variables for ant.

3. Sub build scripts and ant configuration files.

The conf directory contains sub ant build scripts and various configuration files.

Page 7: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 7 of 127

4.2. Database scripts

The db directory contains the sql scripts to create and drop the tables in the database.

4.3. Libraries

The lib directory contains all the required jar files for building and deploying the application.

4.4. Sources

1. Java sources

The src directory contains all java source files and other resources (xml and properties files) that will be located using the classpath loader.

Page 8: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 8 of 127

2. Web sources

The web directory contains all web related sources such as images (gif, jpeg), scripts (js), styles (css), html and jsp

Page 9: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 9 of 127

5. ARCHITECTURE

5.1. Tiers

The web application is modelled in 5 tiers: client, presentation, business, integration and resources tier. This multi-tiered model allows us to logically separate concerns and responsibilities, creating a loosely coupled and modular solution. Actual development is mainly concentrated in the presentation, business and integration tiers so we will focus on those three. These tiers are represented in the application by the User Interface, the Services and the Data Access Layer.

Tier Location Layer

Client Client

Presentation Application Server User Interface

Business Application Server Services (aka Business Logic)

Integration Application Server Data Access (incl Domain Model)

Resources Data(base) Server

Figure 1 Deployment Diagram

Page 10: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 10 of 127

5.2. Layers

The component diagram shows the dependencies between the three layers and between the layers and some of the used libraries. In a layered model the upper layer depends on the lower layer. There should never be a dependency in the other direction. Given this constraint, an upper layer can be replaced without having to change the lower layer. The user interface (web interface in this case) for example can be replaced by an awt, swing or web service interface. Bear in mind that this dependency is also relevant for the content of the data that is exchanged between the layers. The service layer should not return html tags or even regular text to the user interface because it is not aware that the user interface uses html and it is the responsibility of the user interface to take care of translations. A key should be passed instead.

Figure 2 Component Diagram

Page 11: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 11 of 127

5.2.1. Data Access Layer The main responsibilities of the data access layer are to provide a domain model, to provide a set of services to access the domain model (CRUD operations) and to hide data access implementation details. The service layer should not be aware of the fact that the data is stored in database or in xml files or that it is using hibernate, jdbc or equivalent technology.

Figure 3 Data Access Layer Component Diagram

5.2.1.1. Domain package The domain package contains POJOs (Plain Old Java Objects) that represent the entities in the domain. Only data and no business logic is implemented in these classes (= Data Transfer Objects). The Country, Note and NoteRemark classes in the figures below are examples generated by the reference application if you set the “use.samples” option to true.

Page 12: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 12 of 127

Figure 4 Domain Class Diagram

Remark: The relation between the Note and the NoteRemark class in the samples is a logical relation. There is no reference attribute in either of the classes. A NoteRemark object is associated with a Note object by having the same value in the noteId property.

Page 13: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 13 of 127

Source Code: public class Note { private Long noteId; private String title; private String message; private String reference; private Date creationDate; private Date lastModificationDate; public Long getNoteId() { return noteId; } public void setNoteId(Long noteId) { this.noteId = noteId; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } public String getReference() { return reference; } public void setReference(String reference) { this.reference = reference; } public Date getCreationDate() { return creationDate; } public void setCreationDate(Date creationDate) { this.creationDate = creationDate; }

public Date getLastModificationDate() { return lastModificationDate; } public void setLastModificationDate(Date lastModificationDate) { this.lastModificationDate = lastModificationDate; } } public class NoteRemark { private Long noteRemarkId; private Long noteId; private String remark; public Long getNoteRemarkId() { return noteRemarkId; } public void setNoteRemarkId(Long noteRemarkId) { this.noteRemarkId = noteRemarkId; } public Long getNoteId() { return noteId; } public void setNoteId(Long noteId) { this.noteId = noteId; } public String getRemark() { return remark; } public void setRemark(String remark) { this.remark = remark; } }

Page 14: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 14 of 127

5.2.1.2. DAO package The DAO (Data Access Object) package contains data access objects for each domain class: one dao interface, one dao implementation and optionally some helper classes. DAO classes can be generated partially by XDoclet but for the time being the Reference Apllication does not provide support for that.

Figure 5 Notes DAO Class Diagram

Page 15: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 15 of 127

5.2.1.3. Participants and responsibilities

Client

Client represents a client of the NotesDao service that needs to Create, Read, Update or Destroy notes.

NotesDao

Interface containing the CRUD operations that can be performed for note objects.

NotesDaoImplementation

This is the class that implements the NotesDao interface using direct JDBC calls. This is done by using jdbc helper classes: AddNoteStatement, EditNoteStatement, DeleteNoteStatement and NotesQuery.

AddNoteStatement

Helper class that contains the sql statement and the logic to Create a note record in the database

NotesQueryFactory

Factory for creating NotesQuery objects based on NotesQueryCriteria.

EditNoteStatement

Helper class that contains the sql statement and the logic to Update a note record in the database

DeleteNoteStatement

Helper class that contains the sql statement and the logic to Delete a note record in the database

NotesQuery

Helper class that contains the logic to Read note records from the database. It uses a NotesQueryCriteria object to determine which records to read and depends on the spring and springext library.

NotesQueryCriteria

This class is a data transfer object that holds the dynamic query criteria for Notes. It depends on the spring and springext library

Page 16: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 16 of 127

5.2.1.4. Example: getNotes The example shows how a client can retrieve a list of Note objects from the NotesDAO given some query criteria.

Sequence Diagram:

Figure 6 Notes DAO - getNotes Sequence Diagram

Flow Description:

1. The client creates a new NotesQueryCriteria object.

2. The client sets some query criteria by calling the corresponding setter methods.

3. The client invokes the method getNotes on the NotesDao object passing the notesQueryCriteria object as parameter. A list with Note objects is returned as a result

3.1. The NotesDao object requests a notesQuery object from the notesQueryFactory passing the notesQueryCriteria as a parameter.

3.1.1 The NotesQueryFactory creates a new notesQuery object and returns it to the caller (NotesDao).

3.2. The NotesDao object calls the execute method on the notesQuery object it just retrieved from the factory, passing notesQueryCriteria as a parameter. A list with Note objects is returned as a result

Page 17: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 17 of 127

Source Code: public class NotesDaoImplementation implements NotesDao { private NotesQueryFactory notesQueryFactory; … public List getNotes() { return notesQueryFactory.getQuery().execute(); } public List getNotes(NotesQueryCriteria criteria) { // 3 return notesQueryFactory .getNotesQuery(criteria) // 3.1 .execute(criteria); // 3.2 } … } public class NotesQueryCriteria extends DynamicQueryCriteria { public void setNoteId(Long noteId) { putConditionalParam("note_id", noteId); } public void setReference(String reference) { putConditionalParam("reference", reference); } public void setMessage(String message) { // 2 putConditionalParam("message", message); } } public class NotesQueryFactory extends DynamicSqlQueryFactory { public NotesQuery getNotesQuery(NotesQueryCriteria notesQueryCriteria){ // 3.1 return (NotesQuery) getQuery(notesQueryCriteria); // 3.1.1 } } public class NotesQuery extends DelegatingRangeMappingDynamicSqlQuery { public NotesQuery() { declareParameter(new SqlParameter("note_id", Types.BIGINT)); declareParameter(new SqlParameter("reference", Types.VARCHAR)); declareParameter(new SqlParameter("message", Types.VARCHAR)); } public Note find(NotesQueryCriteria notesQueryCriteria){ return (Note) findObject(notesQueryCriteria); } }

Page 18: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 18 of 127

5.2.1.5. Dependencies and configuration As you can see in “Figure 5 Notes DAO Class Diagram” there are dependencies between NotesDaoImplementation and the CRUD helper classes (AddNoteStatement, EditNoteStatement, DeleteNoteStatement and NotesQueryFactory) and between NotesQueryFactory and NotesQuery. These dependencies are injected by spring. This means that the dependencies between beans are declared in a configuration file and that the spring framework takes care of realizing the dependency (reference) at runtime. The beans are no longer responsible for looking up their dependent beans and lose control on that aspect => “inversion of control” or “dependency injection”. The configuration file for injecting these dependencies is put in the web/WEB-INF/dao directory and is named notes.xml.

Have a look inside the notes.xml file (see “Configuration File 1 Notes DAO spring-beans” below). The “autowire="byName"” attribute of the notesDao bean tells the spring framework to iterate through all the properties of the bean, find a bean with the same name as the property and if it finds one to assign it to the property. When spring instantiates the notesDao bean it will assign a reference to the addNoteStatment bean to the addNoteStatement property by calling the setAddNoteStatement() method … . The automatic wiring causes no performance decay because these beans are singletons and reflection needs only to be performed once when starting the application. If you don’t like this automatic wiring then you can use manual wiring similar to the queryBeanName assignment in the notesQueryFactory bean definition.

The dataSource property of the statement beans are assigned with a reference to the dataSource bean. This dataSource bean is not defined in the notes.xml file but in the dataAccessContext.xml file in the web/WEB-INF directory. (Dependency between notes.xml and dataContext.xml)

The values that are put in the properties of the dataSource bean are read from the properties file named “jdbc.properties” that is located in the web/WEB-INF directory. (Dependency between dataContext.xml and jdbc.properties)

The propertyConfigurer bean defined in the applicationContext.xml file in the web/WEB-INF directory takes care of loading the jdbc.properties file. (Dependency between applicationContext.xml and jdbc.properties)

Page 19: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 19 of 127

The web.xml file from the web/WEB-INF directory is loaded by the application server at deployment time. One of the servlets defined in the web.xml file is the ContextLoaderServlet. This servlet is loaded on startup and takes care –as the name predicts- of loading the spring application context. The context-param “contextConfigLocation” tells the servlet which xml spring bean definition files should be loaded. In our case /WEB-INF/dataAccessContext.xml, /WEB-INF/applicationContext.xml, /WEB-INF/dao/notes.xml, … (Dependency between web.xml and notes.xml, dataAccessContext.xml, applicationContext.xml, …)

In the “Data Access Layer Component Diagram” you can see a graphical overview of the dependencies between the configuration files used in the data access layer.

Page 20: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 20 of 127

[/web]/WEB-INF/dao/notes.xml (Web.xml: Context Loader) <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean id="notesDao" class="eu.cec.sampleapp.dao.notes.NotesDaoImplementation" autowire="byName" /> <bean id="notesQueryFactory" class="eu.cec.sampleapp.dao.notes.NotesQueryFactory"> <property name="queryBeanName"><idref local="notesQuery"/></property> </bean> <bean id="notesQuery" singleton="false" class="eu.cec.sampleapp.dao.notes.NotesQuery"> … </bean> <bean id="addNoteStatement" class="eu.cec.sampleapp.dao.notes.AddNoteStatement"> <property name="dataSource"><ref bean="dataSource"/></property> </bean> <bean id="editNoteStatement" class="eu.cec.sampleapp.dao.notes.EditNoteStatement"> <property name="dataSource"><ref bean="dataSource"/></property> </bean> <bean id="deleteNoteStatement" class="eu.cec.sampleapp.dao.notes.DeleteNoteStatement"> <property name="dataSource"><ref bean="dataSource"/></property> </bean> </beans>

Configuration File 1 Notes DAO spring-beans

Page 21: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 21 of 127

[/web]/WEB-INF/dataAccessContext.xml (Web.xml: Context Loader) <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName"><value>${jdbc.driverClassName}</value></property> <property name="url"><value>${jdbc.url}</value></property> <property name="username"><value>${jdbc.username}</value></property> <property name="password"><value>${jdbc.password}</value></property> <property name="testOnBorrow"><value>true</value></property> <property name="validationQuery"><value><![CDATA[select min(NOTE_ID) from T_NOTES]]></value></property> </bean> <bean id="sqlParser" name="sqlParser" class="springext.jdbc.object.dynamic.classic.ClassicDynamicSqlParser"/> </beans>

Configuration File 2 Data Access Context spring-beans: DataSource properties

[/web]/WEB-INF/jdbc.properties (Application Context spring-beans: propertyConfigurer) # DataSource and JDBC configuration properties jdbc.driverClassName = oracle.jdbc.driver.OracleDriver jdbc.url = jdbc:oracle:thin:@devora.cc.cec.eu.int:1522:WEBUCOMD jdbc.username = SCOTT jdbc.password = TIGER

Configuration File 3 JDBC properties

Page 22: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 22 of 127

[/web]/WEB-INF/applicationContext.xml (Web.xml: Context Loader) <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> … <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="locations"> <list> <value>WEB-INF/jdbc.properties</value> </list> </property> </bean> … </beans>

Configuration File 4 Application Context spring-beans: propertyConfigurer

[/web]/WEB-INF/web.xml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd"> <web-app> … <context-param> <param-name>contextConfigLocation</param-name> <param-value> /WEB-INF/dataAccessContext.xml /WEB-INF/applicationContext.xml /WEB-INF/dao/notes.xml /WEB-INF/dao/noteRemarks.xml /WEB-INF/servicesContext.xml …

Page 23: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 23 of 127

</param-value> </context-param> … <servlet> <servlet-name>context</servlet-name> <servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> … </web-app>

Configuration File 5 Web.xml: Context Loader

Page 24: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 24 of 127

5.2.1.6. DataSource In the preferences.properties file of the refapp -before you generate your web application project template- you can select the type datasource you want to use. The 2 possible options are “basic” and “jndi”.

5.2.1.6.1. Basic:

The basic datasource option generates a datasource that is managed by your application and is based on the commons database connection pool library.

Configuration:

The dataAccessContext.xml file defines the dataSource as a bean of class BasicDataSource and sets the jdbc connection parameters.

The jdbc.properties file contains the jdbc connection properties: driver class, connection url, username and password.

Dependencies:

The basic datasource depends on commons-dbcp-1.2.1.jar and commons-pool-1.2.jar.

5.2.1.6.2. Jndi:

The jndi datasource option generates a datasource that is retrieved via a jndi lookup and is managed by the application server.

Using JNDI you can “plug-in” a datasource at runtime providing less dependency on the underlying datasource; or in other words, you’re not hardcoding your source code to a particular datasource providing more flexibility to the overall solution

Configuration:

The dataAccessContext.xml file defines the dataSource as a bean created by a jndi object factory. In other words: the factory looks up the object in the jndi tree and creates a proxy for it.

The jdbc.properties file contains the jndi name of the dataSource.

You need to configure a connection pool and datasource in your application server and put it in the JNDI tree with the same name as the one specified in the jdbc.properties file

Dependencies:

As the datasource is under control of the application server there are no dependencies except for the implicit dependency with the application server (JNDI)

Page 25: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 25 of 127

[/web]/WEB-INF/dataAccessContext.xml (Web.xml: Context Loader) <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> Basic: <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName"><value>${jdbc.driverClassName}</value></property> <property name="url"><value>${jdbc.url}</value></property> <property name="username"><value>${jdbc.username}</value></property> <property name="password"><value>${jdbc.password}</value></property> <property name="testOnBorrow"><value>true</value></property> <property name="validationQuery"> <value> <![CDATA[select min(NOTE_ID) from T_NOTES]]> </value> </property> </bean> Jndi: <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean"> <property name="jndiName"><value> ${dataSource.jndiName}</value></property> </bean> </beans>

Configuration File 6 Data Access Context: dataSource option

Page 26: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 26 of 127

[/web]/WEB-INF/jdbc.properties (Application Context spring-beans: propertyConfigurer) # DataSource and JDBC configuration properties Basic: jdbc.driverClassName = oracle.jdbc.driver.OracleDriver jdbc.url = jdbc:oracle:thin:@devora.cc.cec.eu.int:1522:WEBUCOMD jdbc.username = SCOTT jdbc.password = TIGER Jndi: dataSource.jndiName = jdbc/sampleapp

Configuration File 7 jdbc.properties: basic vs jndi

Remark:

With basic data access the username and password are visible in clear text. This is a security issue! Make sure that you protect this file from reading by any unauthorised individual.

Page 27: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 27 of 127

5.2.1.7. DataAccess In the preferences.properties file of the refapp -before you generate your web application project template- you can select the type data access you want to use. The 3 possible options are “jdbc”, “hibernate” and “ejb2cmp”.

5.2.1.7.1. JDBC:

The JDBC API is used directly without using an OR mapping tool such as hibernate, castor, entity beans... The use and configuration of jdbc data access has already been explained in previous chapters.

5.2.1.7.2. Hibernate:

Hibernate is a powerful, high performance object/relational persistence and query service for Java. Hibernate lets you persist classes developed following common Java idiom. The Hibernate Query Language provides an elegant bridge between the object and relational worlds. Hibernate is one of the most popular object/relational mapping solutions for Java. The beauty of Hibernate is that it releases a developer from worrying about persistency. The domain model is completely independent from the generated persistence code providing a loosely coupled solution. Changes in the generated code due to new versions of Hibernate or a different persistency model are completely transparent to the domain classes.

Configuration:

The sessionFactory bean is the most important bean. It has the responsibility for creating hibernate sessions based on the object relational mappings configured in the mappingResources property and the dataSource.

Each data access method should start by getting a hibernate session from the sessionFactory and closing and releasing it at the end. Because this is the same for all methods of all data access objects we can use aspect oriented programming and let the framework do the hard work.

The hibernateInterceptor binds a new Hibernate Session to the thread before a method call, closing and removing it afterwards in case of any method outcome. If there already was a pre-bound Session, the interceptor simply takes part in it. This bean depends on the sessionFactory and is automatically wired to it by name.

The daoBeanNameAutoProxyCreator will automatically create a proxy for all dao beans using the hibernateInterceptor. The dao beans are recognized by their name. The name should end with “Dao”.

Dependencies:

Hibernate depends on the following libraries:

• hibernate-2.1.jar

• dom4j-1.4.jar

• aopalliance-1.0.jar

• cglib-full-2.0.2.jar

Page 28: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 28 of 127

[/web]/WEB-INF/dataAccessContext.xml (Web.xml: Context Loader) <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> … <bean id="hibernateInterceptor" class="org.springframework.orm.hibernate.HibernateInterceptor" autowire="byName"> </bean> <bean id="daoBeanNameAutoProxyCreator" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"> <property name="beanNames"> <value>*Dao</value> </property> <property name="interceptorNames"> <list> <value>hibernateInterceptor</value> </list> </property> </bean> <bean id="sessionFactory" class="org.springframework.orm.hibernate.LocalSessionFactoryBean"> <property name="mappingResources"> <list> <value>hibernate/domain.hbm.xml</value> </list> </property> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">net.sf.hibernate.dialect.OracleDialect</prop> </props> </property>

Page 29: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 29 of 127

<property name="dataSource"> <ref bean="dataSource" /> </property> </bean> … </beans>

Configuration File 8 Data Access Context: Hibernate [/src]/hibernate/domain.hbm.xml (Data Access Context: Hibernate) <?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN" "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd" > <hibernate-mapping package="eu.cec.sampleapp.domain"> <class name="Note" table="T_NOTES"> <id name="noteId" type="long" column="NOTE_ID"> <generator class="sequence"> <param name="sequence">SEQ_NOTES</param> </generator> </id> <property name="title" column="TITLE" type="string" not-null="false" /> <property name="message" column="MESSAGE" type="string" not-null="false" /> <property name="reference" column="REFERENCE"

Page 30: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 30 of 127

type="string" not-null="false" /> <property name="creationDate" column="CREATION_DT" type="date" not-null="false" /> <property name="lastModificationDate" column="LAST_MODIFICATION_DT" type="date" not-null="false" /> </class> <class name="NoteRemark" table="T_NOTE_REMARKS"> <id name="noteRemarkId" type="long" column="NOTE_REMARK_ID"> <generator class="sequence"> <param name="sequence">SEQ_NOTE_REMARKS</param> </generator> </id> <property name="noteId" column="NOTE_ID" type="long" not-null="true" /> <property name="remark" column="REMARK" type="string" not-null="false" /> </class> </hibernate-mapping>

Page 31: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 31 of 127

Source: public class NotesDaoImplementation extends HibernateDaoSupport implements NotesDao { … public List getNotes(NotesQueryCriteria notesCriteria) { List result; Session session = SessionFactoryUtils.getSession(getSessionFactory(), false); Criteria criteria = HibernateQueryCriteria.createCriteria(session, notesCriteria); try { result = criteria.list(); } catch (HibernateException ex) { throw SessionFactoryUtils.convertHibernateAccessException(ex); } return result; } … }

Page 32: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 32 of 127

5.2.1.7.3. Ejb2cmp:

Ejb2cmp is short for Enterprise Java Beans 2.0 Container Managed Persistence Entity Beans.

Entity beans are server-side components that are persistent and transactional. They are used to model persistent data objects. It can let the EJB container manage its persistent state and relationships, in which case it is a container-managed persistence (CMP) entity bean.

Because EJBs need to run in an EJB container and not in a web container they need to be packaged in a separate ejb jar for distribution and it is not possible to deploy them on web servers such as Tomcat. The sources necessary to create the ejb package are put in the ejb map in the root directory of the project. These sources include java files of the dao and domain packages, spring bean configuration files for the data access layer and the application deployment descriptor: application.xml.

The web module (sampleapp.war) and the ejb module (sampleapp-ejb.jar) will be put together in an enterprise application archive (sampleapp.ear) when you build the application with the ant “distEar” target.

Page 33: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 33 of 127

Component Diagram:

Figure 7 EJB 2.0 CMP Component Diagram

Page 34: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 34 of 127

Class Diagram:

Figure 8 EJB 2.0 CMP Class Diagram

Remark:

The NotesqueryFactory and the NotesQuery are still in the picture. These classes provide the ability to bypass the EJB-QL. This is mainly for queries that return huge result sets and do not need to be transactional. Entity beans always need to be transactional and have problems handling large amounts of entities.

Page 35: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 35 of 127

Participants:

NotesDaoSessionBean

Stateless Session Bean that makes the NotesDao remote accessible. The session bean implements the NotesDao interface and delegates the execution to the NotesDaoImplementation object (POJO).

NotesDaoSession

NoteDaoSession is the Remote interface for NotesDao. The only difference with the NotesDao interface is the fact that it throws RemoteExceptions. This interface is generated by XDoclet using metadata in the NotesDaoSessionBean java source file.

NotesDaoSessionHome

NotesDaoSessionHome is the Remote Home interface for the NotesDao Session Bean. This interface is generated by XDoclet using metadata in the NotesDaoSessionBean java source file.

NoteBean

Entity Bean that makes the Note objects persistable.

NoteLocal

NoteLocal is the Local interface for the Note Entity Bean. This interface provides the methods to access data and related entity beans. This interface is generated by XDoclet using metadata in the NoteBean java source file.

NoteLocalHome

NoteLocalHome is the Local Home interface for the Note Entity Bean. This interface provides methods to create, remove and find Note Entity Beans. This interface is generated by XDoclet using metadata in the NoteBean java source file.

Source Code: /** * @ejb.bean jndi-name="ejb/NotesDao" type="Stateless" view-type="remote" * @ejb.transaction type="Required" * @weblogic.enable-call-by-reference True * @ejb.env-entry name="ejb/BeanFactoryPath" * value="eu/cec/sampleapp/dao/dataAccessContext.xml" * type="java.lang.String" */ public class NotesDaoSessionBean extends AbstractStatelessSessionBean implements NotesDao, SessionBean { private NotesDao notesDao; protected void onEjbCreate() throws CreateException { notesDao = (NotesDao) getBeanFactory().getBean("notesDao"); } /** * @ejb.interface-method view-type = "remote"

Page 36: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 36 of 127

*/ public List getNotes() { return notesDao.getNotes(); } /** * @ejb.interface-method view-type="remote" */ public List getNotes(NotesQueryCriteria criteria) { return notesDao.getNotes(criteria); } /** * @ejb.interface-method view-type="remote" */ public Note getNote(Long noteId) { return notesDao.getNote(noteId); } /** * @ejb.interface-method view-type="remote" */ public void addNote(Note note) { notesDao.addNote(note); } /** * @ejb.interface-method view-type="remote" */ public void editNote(Note note) { notesDao.editNote(note); } /** * @ejb.interface-method view-type="remote" */ public void deleteNote(Long noteId) { notesDao.deleteNote(noteId); } } /** * @ejb.bean * local-jndi-name="ejb/Note" * type="CMP" * cmp-version="2.x" * view-type="local" * schema="T_NOTES" * primkey-field="noteId" * * @ejb.persistence table-name="T_NOTES" * * @ejb.transaction type="Required" * * @ejb.finder * signature="java.util.Collection findAll()" * query="SELECT OBJECT (note) FROM T_NOTES AS note" * * @weblogic.automatic-key-generation * generator-type="ORACLE" * generator-name="seq_notes" * key-cache-size="1" * */ public abstract class NoteBean implements EntityBean { /** * @ejb.persistent-field * @ejb.interface-method view-type="local" * @ejb.persistence column-name="NOTE_ID" */

Page 37: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 37 of 127

public abstract Long getNoteId(); /** * @ejb.interface-method view-type="local" */ public abstract void setNoteId(Long noteId); /** * @ejb.persistent-field * @ejb.interface-method view-type="local" * @ejb.persistence column-name="MESSAGE" */ public abstract String getMessage(); /** * @ejb.interface-method view-type="local" */ public abstract void setMessage(String message); /** * @ejb.persistent-field * @ejb.interface-method view-type="local" * @ejb.persistence column-name="TITLE" */ public abstract String getTitle(); /** * @ejb.interface-method view-type="local" */ public abstract void setTitle(String title); /** * @ejb.persistent-field * @ejb.interface-method view-type="local" * @ejb.persistence column-name="REFERENCE" */ public abstract String getReference(); /** * @ejb.interface-method view-type="local" */ public abstract void setReference(String reference); /** * @ejb.persistent-field * @ejb.interface-method view-type="local" * @ejb.persistence column-name="CREATION_DT" */ public abstract Date getCreationDate(); /** * @ejb.interface-method view-type="local" */ public abstract void setCreationDate(Date creationDate); /** * @ejb.persistent-field * @ejb.interface-method view-type="local" * @ejb.persistence column-name="LAST_MODIFICATION_DT" */ public abstract Date getLastModificationDate(); /** * @ejb.interface-method view-type="local" */ public abstract void setLastModificationDate(Date lastModificationDate); /** The entity context */ private EntityContext context; public NoteBean() { super(); } /** * @ejb.create-method */ public Long ejbCreate() throws CreateException { return null; // The EJB framework will use DB to create a PK } public void ejbPostCreate() throws CreateException {

Page 38: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 38 of 127

} public void ejbActivate() throws EJBException, RemoteException { } public void ejbLoad() throws EJBException, RemoteException { } public void ejbPassivate() throws EJBException, RemoteException { } public void ejbRemove() throws RemoveException, EJBException, RemoteException { } public void ejbStore() throws EJBException, RemoteException { } public void setEntityContext(EntityContext newContext) throws EJBException { context = newContext; } public void unsetEntityContext() throws EJBException { context = null; } }

Dependencies and configuration:

The main configuration file of an ejb archive is the ejb-jar.xml. This file is located in the /META-INF directory. This vendor independent deployment descriptor is loaded by Bea WebLogic together with the weblogic-ejb-jar.xml and weblogic-cmp-rdbms-jar.xml files. These files are created by XDoclet at build time using the metadata from the ejb java source files. (Dependency between the ejb module and the deployment descriptors)

The Session Beans extend from the AbstractStatelessSessionBean from the springframework. The AbstractStatelessSessionBean automatically loads the BeanFactory specified in the jndi key “java:comp/env/ejb/BeanFactoryPath”. The value of the key is specified in an env-entry element of the bean in the ejb-jar.xml file and is generated by XDoclet from the ejb.env-entry metadata element in the java source of the bean: “eu/cec/sampleapp/dao/dataAccessContext.xml”. (Dependency between the ejb-jar.xml file and the dataAccessContext.xml file)

The dataAccesContext.xml file starts with importing spring bean definition files for each domain object (notes.xml, noteRemarks.xml …). These files contain a bean definition for the Dao implementation and for the localHome jndiFactoryBean which is injected in the former.

The servicesContext.xml defines the Dao beans as SimpleRemoteStatelessSessionProxyFactoryBean with the jndi name and business interface of the corresponding SessionBean. The spring framework will create a proxy bean that will lookup the session bean via the jndi context and will delegate all methods to that ejb. RemoteExceptions thrown by the EJB stub will automatically be converted to Spring's unchecked RemoteAccessException

Page 39: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 39 of 127

[/ejb/src]/eu/cec/sampleapp/dao/dataAccessContext.xml (ejb-jar.xml: EJB 2.0 CMP) <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <import resource="notes.xml" /> <import resource="noteRemarks.xml" /> <import resource="noteAttachments.xml" /> … </beans>

Configuration File 9 DataAccess Context: EJB 2.0 CMP

[/ejb/src]/eu/cec/sampleapp/dao/notes.xml (DataAccess Context: EJB 2.0 CMP) <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean id="notesDao" class="eu.cec.sampleapp.dao.notes.NotesDaoImplementation" autowire="byName" /> <bean id="noteLocalHome" class="org.springframework.jndi.JndiObjectFactoryBean"> <property name="jndiName"> <value>ejb/Note</value> </property> </bean> … </beans>

Configuration File 10 notes.xml: EJB 2.0 CMP

[/web]/WEB-INF/servicesContext.xml (Web.xml: Context Loader) <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean id="notesServices" class="eu.cec.sampleapp.services.impl.NotesServicesImpl">

Page 40: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 40 of 127

<property name="notesDao"> <ref bean="notesDao"/> </property> <property name="noteRemarksDao"> <ref bean="noteRemarksDao"/> </property> <property name="noteAttachmentsDao"> <ref bean="noteAttachmentsDao"/> </property> </bean> <bean id="notesDao" class="org.springframework.ejb.access.SimpleRemoteStatelessSessionProxyFactoryBean"> <property name="jndiName"><value>ejb/NotesDao</value></property> <property name="businessInterface"><value>eu.cec.sampleapp.dao.notes.NotesDao</value></property> </bean> <bean id="noteRemarksDao" class="org.springframework.ejb.access.SimpleRemoteStatelessSessionProxyFactoryBean"> <property name="jndiName"><value>ejb/NoteRemarksDao</value></property> <property name="businessInterface"><value>eu.cec.sampleapp.dao.notes.remarks.NoteRemarksDao</value></property> </bean> <bean id="noteAttachmentsDao" class="org.springframework.ejb.access.SimpleRemoteStatelessSessionProxyFactoryBean"> <property name="jndiName"><value>ejb/NoteAttachmentDao</value></property> <property name="businessInterface"><value>eu.cec.sampleapp.dao.notes.attachments.NoteAttachmentsDao</value></property> </bean> </beans>

Configuration File 11 serviceContext.xml: EJB 2.0 CMP

[/ejb]/META-INF/ejb-jar.xml (generated by XDoclet, loaded by ejb container) <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE ejb-jar PUBLIC "-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN" "http://java.sun.com/dtd/ejb-jar_2_0.dtd"> <ejb-jar > <enterprise-beans> <!-- Session Beans --> <session > <ejb-name>NotesDaoSession</ejb-name> <home>eu.cec.sampleapp.dao.notes.NotesDaoSessionHome</home> <remote>eu.cec.sampleapp.dao.notes.NotesDaoSession</remote>

Page 41: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 41 of 127

<ejb-class>eu.cec.sampleapp.dao.notes.NotesDaoSessionBean</ejb-class> <session-type>Stateless</session-type> <transaction-type>Container</transaction-type> <env-entry> <env-entry-name>ejb/BeanFactoryPath</env-entry-name> <env-entry-type>java.lang.String</env-entry-type> <env-entry-value><![CDATA[eu/cec/sampleapp/dao/dataAccessContext.xml]]></env-entry-value> </env-entry> </session> … <!-- Entity Beans --> <entity > <ejb-name>Note</ejb-name> <local-home>eu.cec.sampleapp.domain.NoteLocalHome</local-home> <local>eu.cec.sampleapp.domain.NoteLocal</local> <ejb-class>eu.cec.sampleapp.domain.NoteCMP</ejb-class> <persistence-type>Container</persistence-type> <prim-key-class>java.lang.Long</prim-key-class> <reentrant>False</reentrant> <cmp-version>2.x</cmp-version> <abstract-schema-name>T_NOTES</abstract-schema-name> <cmp-field > <field-name>noteId</field-name> </cmp-field> <cmp-field > <field-name>message</field-name> </cmp-field> <cmp-field > <field-name>title</field-name> </cmp-field> <cmp-field > <field-name>reference</field-name> </cmp-field> <cmp-field > <field-name>creationDate</field-name> </cmp-field> <cmp-field > <field-name>lastModificationDate</field-name> </cmp-field> <primkey-field>noteId</primkey-field> <query> <query-method> <method-name>findAll</method-name> <method-params> </method-params> </query-method>

Page 42: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 42 of 127

<ejb-ql><![CDATA[SELECT OBJECT (note) FROM T_NOTES AS note]]></ejb-ql> </query> </entity> … </enterprise-beans> <assembly-descriptor > <container-transaction > <method > <ejb-name>NotesDaoSession</ejb-name> <method-name>*</method-name> </method> <trans-attribute>Required</trans-attribute> </container-transaction> … <container-transaction > <method > <ejb-name>Note</ejb-name> <method-name>*</method-name> </method> <trans-attribute>Required</trans-attribute> </container-transaction> … </assembly-descriptor> </ejb-jar>

Configuration File 12 ejb-jar.xml: EJB 2.0 CMP

[/ejb]/META-INF/weblogic-cmp-rdbms-jar.xml (generated by XDoclet, loaded by Bea WebLogic) <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE weblogic-rdbms-jar PUBLIC "-//BEA Systems, Inc.//DTD WebLogic 8.1.0 EJB RDBMS Persistence//EN" "http://www.bea.com/servers/wls810/dtd/weblogic-rdbms20-persistence-810.dtd"> <weblogic-rdbms-jar> <weblogic-rdbms-bean> <ejb-name>Note</ejb-name> <data-source-name>jdbc/sampleapp</data-source-name> <table-map> <table-name>T_NOTES</table-name> <field-map> <cmp-field>noteId</cmp-field> <dbms-column>NOTE_ID</dbms-column> </field-map>

Page 43: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 43 of 127

<field-map> <cmp-field>message</cmp-field> <dbms-column>MESSAGE</dbms-column> </field-map> <field-map> <cmp-field>title</cmp-field> <dbms-column>TITLE</dbms-column> </field-map> <field-map> <cmp-field>reference</cmp-field> <dbms-column>REFERENCE</dbms-column> </field-map> <field-map> <cmp-field>creationDate</cmp-field> <dbms-column>CREATION_DT</dbms-column> </field-map> <field-map> <cmp-field>lastModificationDate</cmp-field> <dbms-column>LAST_MODIFICATION_DT</dbms-column> </field-map> </table-map> <weblogic-query> <query-method> <method-name>findAll</method-name> <method-params> </method-params> </query-method> <weblogic-ql><![CDATA[SELECT OBJECT (note) FROM T_NOTES AS note]]></weblogic-ql> </weblogic-query> <automatic-key-generation> <generator-type>ORACLE</generator-type> <generator-name>seq_notes</generator-name> <key-cache-size>1</key-cache-size> </automatic-key-generation> </weblogic-rdbms-bean> … <order-database-operations>True</order-database-operations> <enable-batch-operations>True</enable-batch-operations> <create-default-dbms-tables>Disabled</create-default-dbms-tables> </weblogic-rdbms-jar>

Configuration File 13 weblogic-cmp-rdbms-jar.xml

Page 44: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 44 of 127

[/ejb]/META-INF/weblogic-ejb-jar.xml (generated by XDoclet, loaded by Bea WebLogic) <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE weblogic-ejb-jar PUBLIC "-//BEA Systems, Inc.//DTD WebLogic 8.1.0 EJB//EN" "http://www.bea.com/servers/wls810/dtd/weblogic-ejb-jar.dtd"> <weblogic-ejb-jar> <weblogic-enterprise-bean> <ejb-name>NotesDaoSession</ejb-name> <stateless-session-descriptor> </stateless-session-descriptor> <reference-descriptor> </reference-descriptor> <enable-call-by-reference>True</enable-call-by-reference> <jndi-name>ejb/NotesDao</jndi-name> </weblogic-enterprise-bean> … <weblogic-enterprise-bean> <ejb-name>Note</ejb-name> <entity-descriptor> <persistence> <persistence-use> <type-identifier>WebLogic_CMP_RDBMS</type-identifier> <type-version>7.0</type-version> <type-storage>META-INF/weblogic-cmp-rdbms-jar.xml</type-storage> </persistence-use> </persistence> </entity-descriptor> <reference-descriptor> </reference-descriptor> <local-jndi-name>ejb/Note</local-jndi-name> </weblogic-enterprise-bean> … <idempotent-methods /> </weblogic-ejb-jar>

Configuration File 14 weblogic-ejb-jar.xml

[/ejb]/META-INF/application.xml <?xml version="1.0" encoding="UTF-8"?>

Page 45: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 45 of 127

<!DOCTYPE application PUBLIC "-//Sun Microsystems, Inc.//DTD J2EE Application 1.3//EN" "http://java.sun.com/dtd/application_1_3.dtd"> <application> <display-name>sampleapp</display-name> <module> <ejb>sampleapp-ejb.jar</ejb> </module> <module> <web> <web-uri>sampleapp.war</web-uri> <context-root>/sampleapp</context-root> </web> </module> </application>

Configuration File 15 application.xml: EJB 2.0 CMP

Page 46: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 46 of 127

5.2.1.8. Logging Logging provides the developer or administrator with detailed context for application failures.

Configuration:

The Log4jConfigServlet defined in the web.xml file is a Bootstrap servlet for custom Log4J initialization in a web environment. This servlet should have a lower load-on-startup value in web.xml than ContextLoaderServlet, when using custom Log4J initialization. It supports the following three init parameters at the servlet context level (that is, context-param entries in web.xml):

• "log4jConfigLocation": Location of the Log4J config file; either a "classpath:" location (e.g. "classpath:myLog4j.properties"), an absolute file URL (e.g. "file:C:/log4j.properties), or a plain path relative to the web application root directory (e.g. "/WEB-INF/log4j.properties"). If not specified, default Log4J initialization will apply ("log4j.properties" in the class path; see Log4J documentation for details).

• "log4jRefreshInterval": Interval between config file refresh checks, in milliseconds. If not specified, no refresh checks will happen, which avoids starting Log4J's watchdog thread.

• "log4jExposeWebAppRoot": Whether the web app root system property should be exposed, allowing for log file paths relative to the web application root directory. Default is "true"; specify "false" to suppress expose of the web app root system property. See below for details on how to use this system property in log file locations.

The log4j.properties file located in the src/eu/cec/sampleapp directory contains log4j configuration information. It specifies where (console, file, database, …) to log what level of information (debug, info, error, fatal, …) for which classes and how the information should be formatted (layout).

In the sample configuration all information is logged from fatal to debug level and is written to a log file called “sampleapp.log”. The logfile has a maximum filesize of 512KB. If the file exceeds the maximum filesize, the file is renamed to “sampleapp.log.1” and logging continues in a new file “sampleapp.log”. There is a maximum of 3 backup files. When this maximum is exceeded it overwrites the oldest backup file (so it cycles through the files: sampleapp.log.1, sampleapp.log.2 and sampleapp.log.3)

Page 47: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 47 of 127

[/web]/WEB-INF/web.xml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd"> <web-app> … <context-param> <param-name>log4jConfigLocation</param-name> <param-value>classpath:eu/cec/sampleapp/log4j.properties</param-value> </context-param> <context-param> <param-name>log4jExposeWebAppRoot</param-name> <param-value>false</param-value> </context-param> … <servlet> <servlet-name>Log4jConfigServlet</servlet-name> <servlet-class>org.springframework.web.util.Log4jConfigServlet</servlet-class> <load-on-startup>0</load-on-startup> </servlet> … </web-app>

Configuration File 16 Web.xml: Log4J

Page 48: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 48 of 127

[/src]/eu/cec/sampleapp/log4j.properties (Web.xml: Log4J) log4j.rootCategory=DEBUG, logfile log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n log4j.appender.logfile=org.apache.log4j.RollingFileAppender log4j.appender.logfile.File=sampleapp.log log4j.appender.logfile.MaxFileSize=512KB # Keep three backup files. log4j.appender.logfile.MaxBackupIndex=3 # Pattern to output: date priority [category] - message log4j.appender.logfile.layout=org.apache.log4j.PatternLayout log4j.appender.logfile.layout.ConversionPattern=%d %p [%c] - %m%n

Configuration File 17 log4j.properties Sample logging output 2005-04-08 16:54:06,604 DEBUG [org.springframework.jdbc.core.JdbcTemplate] - Executing SQL query [ SELECT note_id, title, message, reference, creation_dt, last_modification_dt FROM t_notes ]

Page 49: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 49 of 127

5.2.2. Services Layer The main responsibility of the services layer is to provide services to the client that go beyond simple CRUD operations (= Business Logic). It encapsulates the complexity of the underlying implementation details and presents the client a simpler coarse-grained service layer interface that is easy to understand and to use.

The services layer can centralize security management and transaction control. Because it is coarse-grained, it is easier to define and manage security policies and transaction control at this level rather than implementing them for each participating fine-grained business component.

Figure 9 Services Component Diagram

5.2.2.1. Services Package The services package contains the business interfaces, data transfer objects and the POJOs that implement the business logic. The interface of the layer and the implementation is separated by package name. Everything that is public to client is put in the client sub package. This includes the service interface classes and the transfer objects used as parameter or return value of the service methods. The implementations are put in the impl sub package.

Page 50: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 50 of 127

Figure 10 Services Class Diagram

5.2.2.2. Participants and responsibilities

NotesCriteria

This class is a data transfer object that holds the dynamic query criteria for Notes. It does not depend on any libraries and can be made serializable.

NotesServices

Business Logic interface for notes.

NotesServicesImpl

NotesServicesImpl is the implementation of the NotesServices interface. It is implemented as a POJO and interacts with business components such as application services and data access objects.

NotesQueryCriteria (data access layer)

This class is a data transfer object that holds the dynamic query criteria for Notes. It depends on the spring and springext library

NotesDao (data access layer)

Page 51: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 51 of 127

Interface containing the CRUD operations that can be performed for note objects.

Remark: The NotesServicesImpl acts as a Session Façade. It should contain little or no business logic. When business logic is present, it should be placed in an Application Service object, which is invoked by the Session Façade.

5.2.2.3. Example: getNotes Sequence Diagram:

Figure 11 Services - getNotes Sequence Diagram

Flow description:

1. The client creates a new notesCriteria object.

2. The client sets some query criteria by calling the corresponding setter methods.

3. The client invokes the getNotes method on the notesServices object passing the notesCriteria object as parameter. The result is a list of note objects.

3.1. The notesServices creates a NotesQueryCriteria object.

3.2. The notesServices object gets the data from the notesCriteria object.

3.3. The notesServices object puts the data from the notesCriteria object in the new NotesQueryCriteria object.

Page 52: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 52 of 127

3.4. The notesServices object calls the getNotes method of the notesDao object passing the notesQueryCriteria object and gets back a list of note objects.

Remark: You may wonder why the client creates a NotesCriteria instead of a NotesQueryCriteria. The notesServices would not need to create a NotesQueryCriteria object and copy the data from the NotesCriteria. Unfortunately the NotesQueryCriteria has a strong dependency with some third party libraries such as springext. We do not want to impose this dependency to the client of the services layer as this would expose a little bit of implementation details of the data access layer. Furthermore it is quite common to make the service layer remote accessible. Hence we should be able to make the NotesCriteria object serializable which is not possible if it extends from a third party object that is not implemented to be serializable.

Page 53: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 53 of 127

Source code: public interface NotesServices { public List getNotes(); public List getNotes(NotesCriteria criteria); public Note getNote(Long noteId); public void addNote(Note note); public void editNote(Note note); public void deleteNote(Long noteId); public Collection getRemarks(Long noteId); public NoteRemark getNoteRemark(Long noteRemarkId ); public void addRemark(NoteRemark noteRemark); public void editRemark(NoteRemark noteRemark); public void deleteRemark(Long noteRemarkId); } public class NotesServicesImpl implements NotesServices{ private NotesDao notesDao; private NoteRemarksDao noteRemarksDao; public void setNotesDao(NotesDao notesDao) { this.notesDao = notesDao; } public void setNoteRemarksDao(NoteRemarksDao noteRemarksDao) { this.noteRemarksDao = noteRemarksDao; } public List getNotes() { return notesDao.getNotes(); } public List getNotes( NotesCriteria criteria ) { NotesQueryCriteria notesQueryCriteria = new NotesQueryCriteria(); notesQueryCriteria.setNoteId( criteria.getNoteId() ); notesQueryCriteria.setMessage( criteria.getMessage() ); notesQueryCriteria.setReference( criteria.getReference() ); return notesDao.getNotes( notesQueryCriteria ); } public Note getNote( Long noteId ) { return notesDao.getNote(noteId); } public void addNote( Note note ) { notesDao.addNote(note); }

public void editNote( Note note ) { notesDao.editNote(note); } public void deleteNote( Long noteId ) { notesDao.deleteNote(noteId); } public Collection getRemarks( Long noteId ){ return noteRemarksDao.getRemarks( noteId ); } public NoteRemark getNoteRemark( Long noteRemarkId ){ return noteRemarksDao.getNoteRemark( noteRemarkId ); } … } public class NotesCriteria { private Long noteId; private String message; private String reference; public Long getNoteId() { return noteId; } public void setNoteId(Long noteId) { this.noteId = noteId; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } public String getReference() { return reference; } public void setReference(String reference) { this.reference = reference; } }

Page 54: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 54 of 127

5.2.2.4. Dependencies and configuration Both the Services Component Diagram and the Services Class Diagram show a dependency between the services layer and the data access layer. This dependency is injected by spring. The configuration file for injecting these dependencies is put in the web/WEB-INF directory and is named servicesContext.xml

The notesServices.xml file defines the notesServices bean and injects the properties notesDao and noteRemarksDao with the corresponding beans defined in the dataAccessContext.xml file. (Dependency between servicesContext.xml and dataAccessContext.xml)

The web.xml file from the web/WEB-INF directory is loaded by the application server at deployment time. One of the servlets defined in the web.xml file is the ContextLoaderServlet. This servlet is loaded on startup and takes care –as the name predicts- of loading the spring application context. The context-param “contextConfigLocation” tells the servlet which xml spring bean definition files should be loaded. In this case /WEB-INF/servicesContext.xml (Dependency between web.xml and servicesContext.xml)

Page 55: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 55 of 127

[/web]/WEB-INF/servicesContext.xml (Web.xml: Context Loader) <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean id="notesServices" class="eu.cec.sampleapp.services.impl.NotesServicesImpl"> <property name="notesDao"> <ref bean="notesDao"/> </property> <property name="noteRemarksDao"> <ref bean="noteRemarksDao"/> </property> </bean> </beans>

Configuration File 18 Services Context spring beans

5.2.2.5. Transaction Management The reference application offers the option to use declarative, metadata driven transaction management. Set the “use.transaction” and “use.metadata” options to true in the preferences.properties and generate a new web application. The only thing you need to do is to annotate your source code with transaction information. The attribute compiler invoked by the ant build script will put the transaction information from your source files into your classes. When starting the application the springframework will create proxies for all beans that have transaction attributes and let the transactionInterceptor handle all transactions using the selected transactionManager (DataSource, JTA …).

Figure 12 Transaction Class Diagram

Participants and responsibilities:

DefaultAdvisorAutoProxyCreator

The autoproxy bean is responsible for automatically creating proxy beans for all beans that have transaction attributes (annotations) in their source code.

Page 56: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 56 of 127

TransactionAttributeSourceAdvisor

The transactionAdvisor is an advisor driven by a transactionAttributeSource (dependency via transactionInterceptor), used to exclude transactionInterceptor from methods that are non-transactional.

TransactionInterceptor

The transactionInterceptor is a method interceptor providing declarative transaction management using the common Spring transaction infrastructure.

AttributesTransactionAttributeSource

AttributesTransactionAttributeSource is an implementation of TransactionAttributeSource that uses attributes from an Attributes implementation.

CommonsAttributes

CommonsAttributes is an implementation of the Spring Attributes facade for Commons Attributes

DataSourceTransactionManager

The transactionManager bean is a PlatformTransactionManager implementation for a single JDBC DataSource. It binds a JDBC connection from the specified DataSource to the thread, potentially allowing for one thread connection per data source

Service

Interface of the Service offered to the client.

ServiceProxyImpl

Proxy bean created by the DefaultAdvisorAutoProxyCreator that delegates the service interface to the ServiceImpl via the TransactionInterceptor

ServiceImpl

Implementation of the Service offered to the client. This class should contain transaction attribute information on class and/or method level.

Page 57: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 57 of 127

Sequence Diagram:

Figure 13 Transaction Sequence Diagram

Flow Description:

1. The client invokes a method on a service bean with transaction attributes.

1.1. The service proxy implementation calls the transactioninterceptor and passes information about the method to be invoked.

1.1.1. The transactionInterceptor checks with the transactionAttributeSource if the method should be transactional.

1.1.2. The transactionInterceptor asks for a new transaction from the transactionManager.

1.1.2.1. The transactionManager asks a new connection from the dataSource.

1.1.2.1.1 The dataSource creates a new connection (or gets one from the pool) and returns it to the transactionManager

1.1.2.2. The transactionManager creates a new transaction object.

Page 58: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 58 of 127

1.1.2.3. The connection is linked with the transaction and the transaction is returned to the transactionInterceptor.

1.1.3. The transactionInterceptor orders the transaction to bind with the current thread.

1.1.4. The transaction is started and the control is passed to the real implementation of the service.

1.1.4.1. The service asks for a connection to the DataSourceUtils. This is very important! The DataSourceUtils will get the connection that is bound to the thread instead of asking a new one to the DataSource.

1.1.4.2. The service executes some queries on the connection and when finished returns control to the transactionInterceptor.

1.1.5. The transactionInterceptor asks the transactionManager to commit the transaction.

1.1.5.1. The transactionManager gets the connection from the transaction.

1.1.5.2. The transactionManager commits the connection.

Usage:

Put the following attributes in your source code to declare the transaction management for your class and/or method.

• DefaultTransactionAttribute

– timeout (int: number of seconds)

– readonly (boolean)

– isolationLevel (int: see constants below)

– propagationBehavior (int: see constants below)

• RuleBasedTransactionAttribute

– timeout (int: number of seconds)

– readonly (boolean)

– isolationLevel (int: see constants below)

– propagationBehavior (int: see constants below)

– rollbackRules (list of rules specified as separate attributes: RollbackRuleAttribute & NoRollbackRuleAttribute)

• RollbackRuleAttribute(String: fully qualified exception name)

• NoRollbackRuleAttribute(String: fully qualified exception name)

isolationLevel constants:

• ISOLATION_READ_COMMITTED

• ISOLATION_READ_UNCOMMITTED

• ISOLATION_REPEATABLE_READ

• ISOLATION_SERIALIZABLE

propagationBehavior constants:

• PROPAGATION_MANDATORY

Page 59: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 59 of 127

• PROPAGATION_NESTED

• PROPAGATION_NEVER

• PROPAGATION_NOT_SUPPORTED

• PROPAGATION_REQUIRED

• PROPAGATION_REQUIRES_NEW

• PROPAGATION_SUPPORTS

Source Code: public class TestService { /** * @@RuleBasedTransactionAttribute( * isolationLevel=TransactionDefinition.ISOLATION_DEFAULT, * propagationBehavior=TransactionDefinition.PROPAGATION_REQUIRED) * @@RollbackRuleAttribute(java.lang.NullPointerException.class) * @@NoRollbackRuleAttribute(java.io.IOException.class) */ public void sayHello() { System.out.println("Hello"); } }

Page 60: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 60 of 127

[/web]/WEB-INF/servicesContext.xml () <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean id="autoproxy" class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"> </bean> <bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor"> <property name="transactionManager"> <ref bean="transactionManager"/> </property> <property name="transactionAttributeSource"> <ref bean="transactionAttributeSource"/> </property> </bean> <bean id="transactionAdvisor" class="org.springframework.transaction.interceptor.TransactionAttributeSourceAdvisor" autowire="constructor" > </bean> <bean id="transactionAttributeSource" class="org.springframework.transaction.interceptor.AttributesTransactionAttributeSource" autowire="constructor"> </bean> <bean id="attributes" class="org.springframework.metadata.commons.CommonsAttributes" /> … </beans>

Configuration File 19 Services Context: Transaction

Page 61: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 61 of 127

[/web]/WEB-INF/dataAccessContext.xml () <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <!-- Transaction manager for a single JDBC DataSource --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource"><ref local="dataSource"/></property> </bean> … </beans>

Configuration File 20 DataAccess Context: Transaction

Page 62: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 62 of 127

5.2.2.6. Logging (AOP) The reference application offers the option to automatically add logging to your code at method invocation level. Set the “use.logging” option to true in the preferences.properties and generate a new web application.

Participants and collaborations:

LogFactory

Factory for creating Log instances

Log

Log is a simple logging interface abstracting logging APIs.

LoggingAdvisor

LoggingAdvisor is a RegexpMethodPointcutAdvisor. The advisor takes the LoggingInterceptor as advice and the regular expression pattern as pointcut.

DefaultAdvisorAutoProxyCreator

The autoproxy bean is responsible for automatically creating proxy beans for all beans that have methods that match the regular expression pattern of the LoggingAdvisor

LoggingInterceptor

LoggingInterceptor is a MethodInterceptor implementation that logs information before and after method invocation. The information contains userID, timing, parameters …

Service

Interface of the Service offered to the client.

ServiceProxyImpl

Proxy bean created by the DefaultAdvisorAutoProxyCreator that delegates the service interface to the ServiceImpl via the LoggingInterceptor

ServiceImpl

Implementation of the Service offered to the client. This class should contain transaction attribute information on class and/or method level.

ThreadContext

ThreadContext is an object that holds context information and is bound to the current thread. This way context information is available along the call stack without having to explicitly pass it as method parameters. (See 5.2.3.6 Context information)

Page 63: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 63 of 127

Sequence Diagram:

Figure 14 Logging Sequence Diagram

Configuration:

Logging can be configured at 3 different levels:

The log4j logging framework is used by the LoggingInterceptor. Changing the log4j configuration file affects what is logged and where it is logged. As you can see in the source code of the LoggingInterceptor the Log instances are created using the classname of the service implementation as parameter. This means that you can enable/disable logging or change the appender on a per class base.

Page 64: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 64 of 127

The autoproxy creates proxies for all beans with methods that match the regular expression (Perl 5) pattern “.*”. In this case it means that it creates proxies for all beans and intercepts all methods. You can change the pattern to your needs. For example you can use “.*get.*” as a pattern. This will intercept and log only methods that contain “get”. Keep in mind that the pattern is matched with the fully qualified method name that includes the fully qualified classname. Besides configuring the RegexpMethodPointcutAdvisor you can always use another type of Advisor or another way of creating your proxies.

The LoggingInterceptor and the ThreadContext classes are part of the project. If you want to change the information to be logged then you can change the implementation of these classes.

Page 65: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 65 of 127

[/web]/WEB-INF/sampleapp-servlet.xml () <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> … <bean id="loggingInterceptor" class="eu.cec.sampleapp.support.logging.LoggingInterceptor" /> <bean id="loggingAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"> <property name="advice"> <ref local="loggingInterceptor" /> </property> <property name="pattern"> <value>.*</value> </property> </bean> <bean id="autoProxyCreator" class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" /> … </beans>

Configuration File 21 Sampleapp Servlet: Logging

Page 66: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 66 of 127

Source Code: public class LoggingInterceptor implements MethodInterceptor { private static long invocationID = 0; private static synchronized long getInvocationID() { return invocationID++; } public Object invoke(MethodInvocation methodInvocation) throws Throwable { Object result; ThreadContext context; long startMillis; long endMillis; long id; Log log; log = LogFactory.getLog(getClassName(methodInvocation)); id = getInvocationID(); context = ThreadContext.getInstance(); startMillis = System.currentTimeMillis(); logMethodStart(log, methodInvocation, id, context, startMillis); try { result = methodInvocation.proceed(); } catch (Throwable throwable) { endMillis = System.currentTimeMillis(); logMethodException(log, methodInvocation, id, context, startMillis, endMillis, throwable); throw throwable; } endMillis = System.currentTimeMillis(); logMethodEnd(log, methodInvocation, id, context, startMillis, endMillis, result); return result; } private static String getArguments(MethodInvocation methodInvocation) { String result; Object[] args; args = methodInvocation.getArguments(); if (args == null) { result = "[]"; } else { result = Arrays.asList(args).toString(); } return result; } private static String getMethodName(MethodInvocation methodInvocation) { return methodInvocation.getMethod().getName(); } private static String getClassName(MethodInvocation methodInvocation) { String result; Object target; target = methodInvocation.getThis(); if (target == null) { result = "null"; } else { result = target.getClass().getName(); } return result; }

Page 67: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 67 of 127

private void logMethodException(Log log, MethodInvocation methodInvocation, long id, ThreadContext context, long startMillis, long endMillis, Throwable throwable) { if (log.isInfoEnabled()) { StringBuffer sb = new StringBuffer(); sb.append("MethodInvocation " + id + " EXCEPTION"); sb.append("\n Class : " + getClassName(methodInvocation)); sb.append("\n Method : " + getMethodName(methodInvocation)); sb.append("\n Arguments : " + getArguments(methodInvocation)); sb.append("\n Start : " + startMillis + " ms"); sb.append("\n End : " + endMillis + " ms"); sb.append("\n Duration : " + (endMillis - startMillis) + " ms"); sb.append("\n User : " + context.getUserID()); sb.append("\n Result : " + throwable); log.info(sb); } } private void logMethodStart(Log log, MethodInvocation methodInvocation, long id, ThreadContext context, long startMillis) { if (log.isInfoEnabled()) { StringBuffer sb = new StringBuffer(); sb.append("MethodInvocation " + id + " START"); sb.append("\n Class : " + getClassName(methodInvocation)); sb.append("\n Method : " + getMethodName(methodInvocation)); sb.append("\n Arguments : " + getArguments(methodInvocation)); sb.append("\n Start : " + startMillis + " ms"); sb.append("\n User : " + context.getUserID()); log.info(sb); } } private static void logMethodEnd(Log log, MethodInvocation methodInvocation, long id, ThreadContext context, long startMillis, long endMillis, Object result) { if (log.isInfoEnabled()) { StringBuffer sb = new StringBuffer(); sb.append("MethodInvocation " + id + " END"); sb.append("\n Class : " + getClassName(methodInvocation)); sb.append("\n Method : " + getMethodName(methodInvocation)); sb.append("\n Arguments : " + getArguments(methodInvocation)); sb.append("\n Start : " + startMillis + " ms"); sb.append("\n End : " + endMillis + " ms"); sb.append("\n Duration : " + (endMillis - startMillis) + " ms"); sb.append("\n User : " + context.getUserID()); sb.append("\n Result : " + result); log.info(sb); } } }

Page 68: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 68 of 127

5.2.2.7. Remote EJB Business Logic

The services/business logic layer can be made remote accessible by means of EJB Stateless Session Beans.

Just like entity beans (see Ejb2cmp:) stateless session beans need to run in an EJB container and so need to be put in a separate ejb jar for distribution. The sources necessary to create the ejb module are put in the ejb map in the root directory of the project. These sources include java files of the services, dao and domain packages, spring bean configuration files and the application deployment descriptor: application.xml.

Page 69: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 69 of 127

Class Diagram:

Figure 15 EJB Services Class Diagram

Participants and Collaborations:

NotesServicesSessionBean

Stateless Session Bean that makes the NotesServices remote accessible. The session bean implements the NotesServices interface and delegates the execution to the NotesServicesImpl object (POJO).

NotesServicesSession

NoteServicesSession is the Remote interface for NotesServices. The only difference with the NotesServices interface is the fact that it throws RemoteExceptions. This interface is generated by XDoclet using metadata in the NotesServicesSessionBean java source file.

Page 70: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 70 of 127

NotesServicesSessionHome

NotesServicesSessionHome is the Remote Home interface for the NotesServices Session Bean. This interface is generated by XDoclet using metadata in the NotesDaoSessionBean java source file.

Source Code: /** * @ejb.bean jndi-name="ejb/NotesServices" type="Stateless" view-type="remote" * @ejb.transaction type="Required" * @ejb.home package="eu.cec.sampleapp.services.client" * @ejb.interface package="eu.cec.sampleapp.services.client" * @weblogic.enable-call-by-reference True * @ejb.env-entry name="ejb/BeanFactoryPath" * value="eu/cec/sampleapp/dao/dataAccessContext.xml; eu/cec/sampleapp/services/impl/servicesContext.xml" * type="java.lang.String" */ public class NotesServicesSessionBean extends AbstractStatelessSessionBean implements SessionBean, NotesServices { private NotesServices notesServices; protected void onEjbCreate() throws CreateException { notesServices = (NotesServices) getBeanFactory().getBean( "notesServices"); } /** * @ejb.interface-method view-type = "remote" */ public List getNotes() { return notesServices.getNotes(); } /** * @ejb.interface-method view-type = "remote" */ public List getNotes(NotesCriteria criteria) { return notesServices.getNotes(criteria); } /** * @ejb.interface-method view-type = "remote" */ public Note getNote(Long noteId) { return notesServices.getNote(noteId); } /** * @ejb.interface-method view-type = "remote" */ public void addNote(Note note) { notesServices.addNote(note); } /** * @ejb.interface-method view-type = "remote" */ public void editNote(Note note) { notesServices.editNote(note); } /** * @ejb.interface-method view-type = "remote" */ public void deleteNote(Long noteId) { notesServices.deleteNote(noteId);

Page 71: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 71 of 127

} … }

Remark:

The client code needs no modifications to use the session beans. Only the spring bean configuration needs to change. Instead of injecting the client code with an implementation class of the service, the client is now injected with a proxy of the service session bean. This proxy will handle the lookup of the session bean and will wrap any remote exception in a runtime exception.

Dependencies and configuration:

The main configuration file of an ejb archive is the ejb-jar.xml. This file is located in the /META-INF directory. This vendor independent deployment descriptor is loaded by Bea WebLogic together with the weblogic-ejb-jar.xml and weblogic-cmp-rdbms-jar.xml files. These files are created by XDoclet at build time using the metadata from the ejb java source files. (Dependency between the ejb module and the deployment descriptors)

The Session Beans extend from the AbstractStatelessSessionBean from the springframework. The AbstractStatelessSessionBean automatically loads the BeanFactory with the files specified in the jndi key “java:comp/env/ejb/BeanFactoryPath”. The value of the key is specified in an env-entry element of the bean in the ejb-jar.xml file and is generated by XDoclet from the ejb.env-entry metadata element in the java source of the bean: “eu/cec/sampleapp/dao/dataAccessContext.xml; eu/cec/sampleapp/services/impl/servicesContext.xml”. (Dependency between the ejb-jar.xml file and the servicesContext.xml file)

The spring bean definitions are split in 2 separate files. The first one contains the bean definition for the implementation of the notesServices. This file is stored in the ejb-module in the folder eu/cec/sampleapp/services/impl. The second one contains the bean definition for the proxy of the notesServices Session Bean. This file is stored in the web-module in the folder /WEB-INF.

[/ejb/src]/eu/cec/sampleapp/services/impl/servicesContext.xml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean id="notesServices" class="eu.cec.sampleapp.services.impl.NotesServicesImpl"> <property name="notesDao"> <ref bean="notesDao"/> </property> <property name="noteRemarksDao"> <ref bean="noteRemarksDao"/> </property> <property name="noteAttachmentsDao"> <ref bean="noteAttachmentsDao"/> </property> </bean> </beans>

Configuration File 22 EJB Services: Services Context Implementation

[/web]/WEB-INF/servicesContext.xml

Page 72: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 72 of 127

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean id="notesServices" class="org.springframework.ejb.access. SimpleRemoteStatelessSessionProxyFactoryBean"> <property name="jndiName"><value>ejb/NotesServices</value></property> <property name="businessInterface"> <value>eu.cec.sampleapp.services.client.NotesServices</value> </property> </bean> </beans>

Configuration File 23 EJB Services: Services Context Proxy

Page 73: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 73 of 127

5.2.3. User Interface Layer The responsibilities of the user interface layer are to transform objects between business logic and user interface representation, invoke the right services in the business logic, control the flow and generate the presentation views.

Transformation between business object model and user interface representation can concern type conversions (e.g.: Date to String) and conversion between codes or keys and captions or resource references (e.g.: “welcome.title” to “Bienvenue à l'application!” or “button.ok” to “/images/button/ok_fr.gif”). Most of the transformations are handled by the framework (springMVC, Struts and/or JSTL).

Figure 16 User Interface Component Diagram

5.2.3.1. Controller Package The controller package contains the controller implementations. Subpackages are used for organizing them according functionality. E.g.: notes, welcome, errors …

The controllers take the input data, call the right business logic service, prepare the result and select the view to display.

Page 74: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 74 of 127

Figure 17 Controller Class Diagram

Page 75: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 75 of 127

5.2.3.2. Participants and responsibilities

DispatcherServlet

DispatcherServlet is a servlet that takes care of dispatching incoming requests to the controllers via configurable HandlerMappings. After handling a request the dispatcher servlet takes care of resolving and rendering the view returned by the controller.

HandlerMapping

HandlerMapping defines a mapping between requests and handler objects (controllers).

ListNotesController

The ListNotesController class is responsible for executing the getNotes on the NotesServices class and passing the result to the notes list view. This class extends from ListController.

ListController

ListController is an abstract controller class that provides some generic list controller functionalities. A concrete implementation of a listcontroller only needs to implement an items method. The rest of the responsibilities have been taken care of by this class. This class extends from ViewController.

ViewController

ViewController is an abstract controller class that provides the possibility for spring to inject the view.

NotesCriteria (Services Layer)

This class is a data transfer object that holds the dynamic query criteria for Notes

NotesServices (Services Layer)

The NotesServices provides all services concerning notes objects.

JSTLView

View class for rendering JSP pages that use the JSTL tag libraries. Exposes JSTL-specific request attributes specifying locale and resource bundle for JSTL's formatting and message tags, using Spring's locale and message source.

Page 76: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 76 of 127

5.2.3.3. Example: getNotes The example shows how a request for a list of note objects is dispatched and handled by the user interface layer.

Sequence Diagram:

Figure 18 User Interface - getNotes Sequence Diagram

Flow Description:

1. The client sends a request. E.g.: “http://localhost:7001/sampleapp/examples/notes/list.do”

1.1. The dispatcherServlet passes the request to the handlerMapping and expects a handler in return. In this case the handler will be a listNotesController. These mappings between urls and controllers are defined in the sampleapp-servlet.xml file.

1.2. The dispatcherServlet calls the handleRequest method of the listNotesController.

1.2.1.1. The listNotesController creates a notesCriteria object

1.2.1.2. The listNotesController fills the notesCriteria object with data coming from the request.

1.2.2. The listNotesController calls the getNotes method of the notesServices object and passes the notesCriteria as a parameter. The notesServices should return a list of all notes matching the notes criteria. This list of notes and the “notesListView” name are returned to the dispatcherServlet as model and view.

Page 77: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 77 of 127

1.3. The dispatcherServlet asks to the viewResolver to resolve the view name “notesListView”.

1.4. The dispatcherServlet calls the render method of the view returned by the viewResolver.

Source code: public class ListNotesController extends ListController { private NotesServices notesServices; public void setNotesServices(NotesServices notesServices) { this.notesServices = notesServices; } public NotesCriteria getCriteria(HttpServletRequest request) { // 1.2.1 NotesCriteria criteria = new NotesCriteria(); // 1.2.1.1 String reference = request.getParameter("reference"); String message = request.getParameter("message"); if (reference != null && reference.trim().length() > 0) { criteria.setReference(reference); // 1.2.1.2 request.setAttribute("reference", reference); } else { request.removeAttribute("reference"); } if (message != null && message.trim().length() > 0) { criteria.setMessage(message); // 1.2.1.2 request.setAttribute("message", message); } else { request.removeAttribute("message"); } return criteria; } protected List items(HttpServletRequest request) { NotesCriteria criteria = getCriteria(request); // 1.2.1 return notesServices.getNotes(criteria); // 1.2.2 } protected void initModel(HttpServletRequest request, Map model) { model.put("pageTitleKey", "notes.list.title"); } } public abstract class ListController extends ViewController { private String itemsName; public void setItemsName(String itemsName){ this.itemsName = itemsName; } protected void initModel(HttpServletRequest request, Map model){ // empty implementation to be overridden. } protected abstract List items(HttpServletRequest request); public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { Map model = new HashMap(); model.put(itemsName, items(request));

Page 78: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 78 of 127

initModel(request, model); return new ModelAndView(getView(), model); } } public abstract class ViewController implements Controller { private String view; public String getView() { return view; } public void setView(String view) { this.view = view; } }

5.2.3.4. Dependencies and configuration Figure 17 Controller Class Diagram shows the dependencies between the controller classes and the classes from the services layer. For example the listNotesController uses the notesServices class. This dependency is injected by the spring framework and is described in the notes.xml file that you can find in the web/WEB-INF/controllers directory. (Dependency between notes.xml and Controller)

This directory contains multiple spring bean definition files, each of them containing controller definitions for a certain aspect of the application. The contextConfigLocation parameter in the web.xml file of the application tells spring to load these files. (Dependency between web.xml and controller xml files)

As described in Figure 18 User Interface - getNotes Sequence Diagram, the dispatcherservlet uses the handlerMapping object to match a request URL with a controller. These mappings are configured in the sampleapp-servlet.xml file in the bean named “urlMapping”. This bean has a “mappings” property that contains a map with url/controller pairs. For example the context relative URL “/examples/notes/list.do” maps to the listNotesController. (Dependency between sampleapp-servlet.xml and notes.xml)

When a controller has finished all necessary processing it returns the appropriate model and view to the dispatcherServlet. (Dependency between controller and view)

Most of the time the controller returns the name of a view rather than an actual view object. The DispatcherServlet uses a viewResolver to resolve the name to a view object. The viewResolver is

Page 79: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 79 of 127

configured in the sampleapp-servlet.xml file. The basenames property of the viewResolver contains a list of resource bundle basenames. The resource bundles contain the mapping between view name and class. The bundles are typically defined in properties files, located in the class path. For example: the basenames property contains views.Notes, views.Ecas … These resource bundles are defined as property files named Notes.properties, Ecas.properties … and are located in the src/views directory. (Dependency between sampleapp-servlet.xml and view properties files)

The view properties files contain the definitions of the views mapped to a class and to a URL. This can be done indirectly via parent. (Dependency between view properties file and views)

The application provides messaging functionality (i18n or internationalization). Message resolution is achieved by the implementation of the MessageSource and is configured in the applicationContext.xml file. In the example the messageSource accesses the resource bundles with basenames messages.Notes, messages.Ecas … These resource bundles are stored as java properties files in the directory src/messages.

Page 80: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 80 of 127

[/web]/WEB-INF/controllers/notes.xml (Web.xml: Controllers contextConfigLocation) <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> … <bean name="listNotesController" class="eu.cec.sampleapp.controller.notes.ListNotesController"> <property name="notesServices"><ref bean="notesServices"/></property> <property name="itemsName"><value>notes</value></property> <property name="view"><value>notesListView</value></property> </bean> … </beans>

Configuration File 24 Note Controllers

[/web]/WEB-INF/web.xml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd"> <web-app> …

Page 81: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 81 of 127

<context-param> <param-name>contextConfigLocation</param-name> <param-value> … /WEB-INF/controllers/ecas.xml /WEB-INF/controllers/errors.xml /WEB-INF/controllers/welcome.xml /WEB-INF/controllers/tabs.xml /WEB-INF/controllers/notes.xml /WEB-INF/controllers/noteRemarks.xml /WEB-INF/controllers/widgets.xml </param-value> </context-param> … </web-app>

Configuration File 25 Web.xml: Controllers contextConfigLocation

[/web]/WEB-INF/sampleapp-servlet.xml <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean id="viewResolver" class="org.springframework.web.servlet.view.ResourceBundleViewResolver"> <property name="basenames"> <list> <value>views.Ecas</value> <value>views.Errors</value> <value>views.Template</value> <value>views.Welcome</value> <value>views.Notes</value> <value>views.Tabs</value> <value>views.Widgets</value> </list> </property> </bean>

Page 82: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 82 of 127

<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> <property name="interceptors"> <list> <ref bean="localeChangeInterceptor"/> </list> </property> <property name="mappings"> <props> … <prop key="/examples/notes/list.do">listNotesController</prop> <prop key="/examples/notes/add.do">addNoteController</prop> <prop key="/examples/notes/edit.do">editNoteController</prop> <prop key="/examples/notes/delete.do">deleteNoteController</prop> … </props> </property> </bean> </beans>

Configuration File 26 Sampleapp-servlet.xml: viewResolver & urlMapping

[/src]/views/Notes.properties (Sampleapp-servlet.xml: viewResolver & urlMapping) notesListView.parent=templateView notesListView.attributesMap[contentUrl]=/WEB-INF/jsp/examples/notes/list.jsp … redirectingNotesListView.parent=abstractRedirectView redirectingNotesListView.url=/examples/notes/list.do …

Configuration File 27 Notes.properties: Views

Page 83: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 83 of 127

[/src]/views/Template.properties (Sampleapp-servlet.xml: viewResolver & urlMapping) templateView.class=org.springframework.web.servlet.view.JstlView templateView.url=/WEB-INF/jsp/template/template.jsp abstractRedirectView.class=org.springframework.web.servlet.view.RedirectView abstractRedirectView.contextRelative=true …

Configuration File 28 Template.properties

[/web]/WEB-INF/applicationContext.xml (Web.xml: Context Loader) <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean id="localeResolver" class="org.springframework.web.servlet.i18n.CookieLocaleResolver"/> <bean id="localeChangeInterceptor" class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"/> … <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource"> <property name="basenames"> <list> <value>messages.Menu</value> <value>messages.Welcome</value> <value>messages.Header</value> <value>messages.Ecas</value> <value>messages.Errors</value> <value>messages.Notes</value> <value>messages.NoteRemarks</value> <value>messages.Tabs</value> <value>messages.Widgets</value> </list> </property> </bean> </beans>

Configuration File 29 Application Context: messageSource

Page 84: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 84 of 127

[/src]/messages/Notes.properties (Application Context: messageSource) required.note.title = The note requires a title. required.note.message = A note without a message is rather useless. Please fill it in. malformed.note.reference = The reference must match the pattern aaa-9999-99. notes.list.title=List of Notes notes.master.detail.list=List master-detail notes.form.title=Notes form notes.form.new.title.default=<New title here> notes.with.remarks.list.title=List with remarks notes.remarks.form.title=Remark for note form notes.showHide=show/hide notes.reference=Reference notes.reference.help=The reference is a unique code that will be used to refer to this note. notes.message=Message notes.title=Title notes.noNotes=There are no notes. notes.createNewNote=Create a new note notes.alt.edit=Edit note notes.alt.delete=Delete note notes.delete.confirmation=Are you sure you want to delete the note [{0}]? notes.list=The list of notes notes.search=Search …

Configuration File 30 Notes.properties: Messages

Page 85: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 85 of 127

5.2.3.5. Error Handling Configuration:

Error handling can be configured by putting error-page elements in the web.xml file. This element specifies a mapping between an error code or exception type to the path of a resource in the Web Application. It is the responsibility of the application server to forward the request to the specified location when an error occurs.

[/web]/WEB-INF/web.xml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd"> <web-app> … <context-param> <param-name>contextConfigLocation</param-name> <param-value> … /WEB-INF/controllers/errors.xml … </param-value> </context-param> … <error-page> <error-code>404</error-code> <location>/error404.do</location> </error-page> … </web-app>

Configuration File 31 Web.xml: Error Page

[/web]/WEB-INF/sampleapp-servlet.xml <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean id="viewResolver" class="org.springframework.web.servlet.view.ResourceBundleViewResolver"> <property name="basenames"> <list> <value>views.Errors</value> … </list> </property> </bean> <!-- URL mappings to controllers --> <bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> … <property name="mappings"> <props> <prop key="/error404.do">error404Controller</prop> … </props> </property> </bean> </beans>

[/web]/WEB-INF/controllers/errors.xml

Page 86: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 86 of 127

<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean name="error404Controller" class="eu.cec.sampleapp.controller.errors.Error404Controller"> <property name="view"><value>error404View</value></property> </bean> </beans>

/src/eu/cec/sampleapp/controller/errors/Error404Controller.java public class Error404Controller extends ViewController { public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { Map model = new HashMap(); model.put("pageTitleKey", "error404.title"); model.put("badUrl", request.getAttribute( "javax.servlet.error.request_uri")); return new ModelAndView(getView(), model); } }

[/src]/views/Errors.properties error404View.parent=templateView error404View.attributesMap[contentUrl]=/WEB-INF/jsp/errors/404.jsp

[/web]/WEB-INF/jsp/errors/404.jsp <%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %> <%@ taglib prefix="fmt" uri="http://java.sun.com/jstl/fmt" %> <table> <tr> <td><img border="0" src="<c:url value="/images/error/404.gif" />"/></td> <td> URL: <b><c:out value="${badUrl}" /></b><br/> <fmt:message key="error404.error" /> </td> </tr> </table>

5.2.3.6. Context information Sometimes we want some context information to be available along the call stack without having to explicitly pass this information as method parameters. E.g.: user name, session id, client language … This can be achieved using the Threadlocal pattern. The Threadlocal pattern basically creates a singleton context object per thread so that each thread has its own, independently initialized instance of the variable.

When the application server gets a request it will first execute the filter chain. One of the configured filters in the chain is the context filter. This filter gets a threadlocal instance of the threadcontext and puts the username in it. After processing the filters, the request is handled by executing the corresponding controller. As usual the controller uses a service to handle the necessary business logic. At this point the user information is nog longer part of any of the parameters. If the service needs the

Page 87: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 87 of 127

username it simple gets the threadcontext instance linked with the current thread and gets the username.

Sequence Diagram:

Figure 19 Thread Context Sequence Diagram

Flow Description:

1. The client sends an http request.

1.1. The application server executes the filter chain.

1.1.1. The threadContextFilter gets a ThreadContext instance for this thread.

1.1.2. The threadContextFilter gets the user information from the request.

1.1.3. The threadContextFilter puts the user information in the ThreadContext.

1.2. The application server calls invokes the handleRequest on the controller (via DispatcherServlet)

1.2.1. The controller calls the service.

1.2.1.1. The service gets the ThreadContext instance of this thread.

1.2.1.2. The service gets the user information from the ThreadContext object.

Source: public class ThreadContextFilter implements Filter { public void init(FilterConfig filterConfig) throws ServletException {

Page 88: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 88 of 127

// Do nothing } public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest httpServletRequest; ThreadContext threadContext; if (servletRequest instanceof HttpServletRequest) { httpServletRequest = (HttpServletRequest) servletRequest; threadContext = ThreadContext.getInstance(); threadContext.setUserID(httpServletRequest.getRemoteUser()); } if (filterChain != null) { filterChain.doFilter(servletRequest, servletResponse); } } public void destroy() { // Do nothing } }

public class ThreadContext { private static ThreadLocal threadLocal = new ThreadLocal(); public static ThreadContext getInstance() { ThreadContext result; result = (ThreadContext) threadLocal.get(); if (result == null) { result = new ThreadContext(); threadLocal.set(result); } return result; } private String userID; private ThreadContext() { } public String getUserID() { return userID; } public void setUserID(String userID) { this.userID = userID; } }

Configuration:

The sample application configures 2 filters that manage context information: one from the springext library and one with its own implementation.

Page 89: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 89 of 127

[/web]/WEB-INF/web.xml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd"> <web-app> … <filter> <filter-name>Request url filter</filter-name> <filter-class>springext.web.filter.RequestFilter</filter-class> </filter> <filter> <filter-name>Thread context filter</filter-name> <filter-class> eu.cec.sampleapp.support.context.ThreadContextFilter </filter-class> </filter> … <filter-mapping> <filter-name>Thread context filter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <filter-mapping> <filter-name>Request url filter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> … </web-app>

Configuration File 32 Web.xml: Context Information

5.2.3.7. Taglibs The following tag libraries are used by the reference application (samples).

• JSTL

• Ergonomics

• Displaytag

Configuration:

Tag library jar files need to be put in the /lib directory.

Page 90: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 90 of 127

During the build process the webapp-libs.xml ant script will copy the necessary jar files to the /WEB-INF/lib directory. Jar files in the /WEB-INF/lib directory will automatically be included in the classpath of the web application by the application server. If you add new taglib jar files to your project you need to add an include element to the ant script.

/conf/webapp-libs.xml <?xml version="1.0"?> <!-- In this file, you will specify which .jar files in the /lib folder will be included in the .war file. --> <project name="webapp-libs" basedir="." default="webapp-libs"> <target name="webapp-libs" description="Includes the given .jar files in the web application."> <copy todir="${build.webapp.webinf.lib.dir}" preservelastmodified="yes"> <fileset dir="${lib.dir}"> … <include name="displaytag-1.0-modified.jar"/> <include name="ergonomics-taglib-0.4.jar"/> <include name="jstl.jar"/> <include name="spring-1.1.5.jar"/> <include name="standard.jar"/> </fileset> </copy> </target> </project>

Configuration File 33 Web Application Libraries: Taglibs

If you want to use the tags from a tag library in your jsp pages you also need to copy the tag library descriptor files (.tld) in the [/web]/WEB-INF/tld directory and declare them in the [/web]/WEB-INF/web.xml file.

Page 91: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 91 of 127

[/web] /WEB-INF/web.xml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd"> <web-app> … <taglib> <taglib-uri>http://java.sun.com/jstl/core_rt</taglib-uri> <taglib-location>/WEB-INF/tld/c-rt.tld</taglib-location> </taglib> … <taglib> <taglib-uri>http://cec.eu/ergonomics</taglib-uri> <taglib-location>/WEB-INF/tld/ergonomics.tld</taglib-location> </taglib> <taglib> <taglib-uri>http://www.displaytag.org</taglib-uri> <taglib-location> /WEB-INF/tld/displaytag-el-12-modified.tld </taglib-location> </taglib> … </web-app>

Configuration File 34 Web.xml: Taglibs

Usage:

If you use a tag library in a jsp page you have to declare it by using the taglib directive on top of the page. The uri attribute should match the uri specified in the web.xml file.

Example:

[/web]/WEB-INF/jsp/welcome/welcome.jsp <%@ taglib prefix="fmt" uri="http://java.sun.com/jstl/fmt" %> <h1><fmt:message key="welcome.title"/></h1><br/> <fmt:message key="welcome.hint"/>

5.2.3.8. Security: Ecas authentication The reference application implements authentication by using Ecas. ECAS is the Common Authentication Service that will enable Web applications to authenticate centrally with a common strong password, offering more security than the current LDAP password. It offers also single sign-on between applications using it.

The url-pattern “/*” in the security-constraint and the Ecas filter-mapping section of the web.xml file marks all resources of the web application as protected. If no valid credentials are available when a resource is requested the control is forwarded to the form-login-page “/ecas/login.do”. The Ecas filter notices that there is no valid user or ticket yet and redirects the response to the login page on the Ecas server over a secure connection (https://www.cc.cec/cas/login). After logging in on the ecas server the client will get an ecas ticket and will be redirected back to the application. The Ecas filter will validate the ticket and link an authenticated principal to the session. The EcasLoginController will redirect to the welcome page.

Page 92: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 92 of 127

For more information on the init-parameters of the Ecas filter please read the Ecas documentation on CITnet.

Sequence Diagram:

Figure 20 Ecas Authentication Sequence Diagram

Page 93: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 93 of 127

Flow Description:

1. The client sends the request to the application server

1.1. The application server creates a response

1.2. The application server checks security. There is no authorised principle yet so the control is forwarded to /ecas/login.do

1.2.1. Before the controller associated with the /ecas/login.do URL is executed, the ecas filter is triggered

1.2.1.1. There is no ecas ticket available. The response is redirected to Ecas.

1.3. The response is closed and destroyed.

2. The client is redirected to the URL on the Ecas server, logs in and is redirected back to the application server with an Ecas ticket.

3. The client is redirected to the application server.

3.1. The application server creates a response

3.2. The application server checks security. There is still no authorised principle so the control is forwarded to /ecas/login.do

3.2.1. Before the controller associated with the /ecas/login.do URL is executed, the ecas filter is triggered

3.2.1.1. There is an ecas ticket available. The EcasAuthenticator authenticates the ticket and returns a subject.

3.2.1.2. The EcasAuthenticator impersonates the subject.

3.2.2. After executing the filters the EcasLoginController associated with the /ecas/login.do URL is executed.

3.2.2.1. The EcasLoginController redirects the response to the welcome page.

3.3. The response is closed and destroyed.

4. The client is redirected to the welcome page of the application.

4.1. The application server checks security. There is an authorised principle.

4.2. After executing the filters the WelcomeController is executed.

Page 94: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 94 of 127

Source Code: public class EcasLoginController implements Controller { private static final String AUTHENTICATION_PROPERTY = "eu.cec.digit.ecas.authenticated"; public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { if (request.getSession().getAttribute(AUTHENTICATION_PROPERTY) == null) { request.getSession().setAttribute(AUTHENTICATION_PROPERTY, Boolean.TRUE); String targetURL = EcasServletAuthenticationFactory.getInstance().getServletAuthentication() .getAbsoluteTargetURLForFormAuthentication(request); if (targetURL != null) { response.sendRedirect(targetURL); return null; } else { return new ModelAndView("redirectingWelcomeView"); } } else { return new ModelAndView("redirectingEcasErrorView"); } } }

Configuration:

[/web]/WEB-INF/web.xml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd"> <web-app> <context-param> <param-name>edu.yale.its.tp.cas.client.filter.proxyUrl</param-name> <param-value>https://www.cc.cec/cas/proxy</param-value> </context-param>

Page 95: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 95 of 127

<filter> <filter-name>ECAS filter</filter-name> <filter-class>eu.cec.digit.ecas.client.filter.EcasFilter</filter-class> <!-- The following URLS point to the ECAS server. Change it when you want to use an ECAS mockup server. --> <init-param> <param-name>edu.yale.its.tp.cas.client.filter.loginUrl</param-name> <param-value>https://www.cc.cec/cas/login</param-value> </init-param> <init-param> <param-name>edu.yale.its.tp.cas.client.filter.validateUrl</param-name> <param-value>https://www.cc.cec/cas/proxyValidate</param-value> </init-param> <init-param> <param-name>edu.yale.its.tp.cas.client.filter.serverName</param-name> <param-value>@appserver.name@:@appserver.port@</param-value> </init-param> <init-param> <param-name>eu.cec.digit.ecas.client.filter.applicationServer</param-name> <param-value>weblogic</param-value> <description>Application Server Type (default value = "weblogic")</description> </init-param> <init-param> <param-name>eu.cec.digit.ecas.client.filter.groups</param-name> <param-value>internet, europol, dante, livenews, mailmas*</param-value> <description> Groups required by the application (omit this parameter if you don't want to receive any group) </description> </init-param> <init-param> <param-name>eu.cec.digit.ecas.client.filter.acceptStrength</param-name> <param-value>STRONG</param-value> <description>Accepted Strength Levels (ordered by priority)</description> </init-param> <!-- Preferably enable and use SSL! When it is done; use the commented https URLs below. --> <init-param> <param-name>eu.cec.digit.ecas.client.filter.proxyCallbackUrl</param-name> <param-value>http://@appserver.name@:@appserver.port@/sampleapp/ecasProxy</param-value> </init-param> <init-param> <param-name>eu.cec.digit.ecas.client.filter.authorizedProxies</param-name> <param-value>http://@appserver.name@:@appserver.port@/sampleapp/ecasProxy</param-value> </init-param> </filter> <filter-mapping> <filter-name>ECAS filter</filter-name> <url-pattern>/*</url-pattern>

Page 96: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 96 of 127

</filter-mapping> <!-- ProxyTicketReceptor Servlet --> <servlet> <servlet-name>ProxyTicketReceptor</servlet-name> <servlet-class>eu.cec.digit.ecas.client.proxy.EcasProxyTicketReceptor</servlet-class> <load-on-startup>3</load-on-startup> </servlet> <servlet-mapping> <servlet-name>ProxyTicketReceptor</servlet-name> <url-pattern>/ecasProxy</url-pattern> </servlet-mapping> <!-- ECAS security --> <security-constraint> <web-resource-collection> <web-resource-name>sampleapp</web-resource-name> <description>Require users to authenticate</description> <url-pattern>/*</url-pattern> </web-resource-collection> <auth-constraint> <description>allow users with role 'sampleapp'</description> <role-name>sampleapp</role-name> </auth-constraint> <user-data-constraint> <description>Encryption is not required for the application in general.</description> <transport-guarantee>NONE</transport-guarantee> </user-data-constraint> </security-constraint> <login-config> <auth-method>FORM</auth-method> <realm-name>myrealm</realm-name> <form-login-config> <form-login-page>/ecas/login.do</form-login-page> <form-error-page>/ecas/error.do</form-error-page> </form-login-config> </login-config> <security-role> <description>Role to allow authentication</description> <role-name>sampleapp</role-name> </security-role>

Page 97: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 97 of 127

</web-app>

Configuration File 35 Web.xml: Ecas Security

Page 98: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 98 of 127

5.2.3.9. Internationalization (i18n) Internationalization has many aspects. Among them are character encoding, language selection and multilingual messages.

5.2.3.9.1. Request Character Encoding

The incoming request should always be UTF-8 encoded. This encoding is forced by using the CharacterEncodingFilter. The Filter simply sets the character encoding of the servletRequest to UTF-8.

[/web]/WEB-INF/web.xml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd"> <web-app> … <filter> <filter-name>Character encoding filter</filter-name> <filter-class> eu.cec.sampleapp.support.i18n.CharacterEncodingFilter </filter-class> </filter> … <filter-mapping> <filter-name>Character encoding filter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> … </web-app>

Configuration File 36 Web.xml: Request Character Encoding

Source Code: /src/eu/cec/sampleapp/support/i18n/CharacterEncodingFilter.java public class CharacterEncodingFilter implements Filter { public void init(FilterConfig filterConfig) throws ServletException { // do nothing } public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { servletRequest.setCharacterEncoding("UTF-8"); if (filterChain != null) { filterChain.doFilter(servletRequest, servletResponse); } } public void destroy() { // do nothing } }

5.2.3.9.2. File encoding

- properties

Page 99: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 99 of 127

- jsp

5.2.3.9.3. Language Selection

The user of the web application should be able to change the language of the application.

Participants and responsibilities:

RequestLocaleFilter

This filter has the responisibility to determine the locale of the request and to pass it to all of the used frameworks (spring, struts, jstl …).

InternationalizationUtils

This utility class has to determine the locale for the current request. The locale can be specified on the request as a parameter or as a cookie. If not specified it will use the server locale.

LocaleResolver

Interface for web-based locale resolution strategies that allows for both locale resolution via the request and locale modification via request and response.

LocaleChangeInterceptor

Interceptor that allows for changing the current locale on every request, via a configurable request parameter.

When the application server receives a request the RequestLocaleFilter asks the InternationalizationUtils to determine the locale. This can be a new one specified as a parameter on the request. It can be a locale selected in one of the previous requests, stored in a cookie. In any other case the locale of the server is used. Once the RequestLocaleFilter has the locale, it stores it as an attribute on the request for easy access for tags, scriptlets … It stores it in struts and jstl session attributes so that all tag libraries will use the same locale. Finally the the locale of the response is set.

The RequestLocaleFilter generates a set of hidden input tags and stores them in a request attribute: one tag per request query parameter except for the locale parameter. These input tags can be used when generating a language selection form on the jsp page.

[/web]/WEB-INF/jsp/template/header.jsp … <form method="GET"> <c:out value="${requestLocaleParametersHiddenFields}" escapeXml="false"/> <ergonomics:listBox name="locale" onChange="this.form.submit();"> <ergonomics:listBoxItem value="en" selected="${requestLocale eq 'en'}"> <ergonomics:labelKey>language.english</ergonomics:labelKey> </ergonomics:listBoxItem> <ergonomics:listBoxItem value="fr" selected="${requestLocale eq 'fr'}"> <ergonomics:labelKey>language.french</ergonomics:labelKey> </ergonomics:listBoxItem> <ergonomics:listBoxItem value="nl" selected="${requestLocale eq 'nl'}"> <ergonomics:labelKey>language.dutch</ergonomics:labelKey> </ergonomics:listBoxItem> </ergonomics:listBox> </form>

Page 100: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 100 of 127

After handling all filters in the filter chain the application server passes the control to the Dispatcher servlet. The DispatcherServlet first calls the preHandle method on the LocaleChangeInterceptor. This interceptor is configured in the urlMapping bean in the sampleapp-servlet.xml file. The LocaleChangeInterceptor checks in the same way as the RequestLocaleFilter if the user has requested a new locale and if that is the case, asks to the LocaleResolver to store the locale. The localeResolver we use is a CookieLocaleResolver so it stores the locale in a cookie.

Page 101: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 101 of 127

Sequence Diagram:

Figure 21 Locale Processing Sequence Diagram

Page 102: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 102 of 127

Flow Description:

1. The client sends an HTTP request to the application server

1.1. The application server calls the RequestLocaleFilter.

1.1.1. The RequestLocaleFilter gets the locale from the InternationalizationUtils.

1.1.1.1. The InternationalizationUtils looks for a locale parameter on the request.

1.1.1.2. If no locale parameter is on the request it gets the cookies from the request.

1.1.1.3. The InternationalizationUtils looks through the cookies for the locale cookie

1.1.1.4. The locale is returned to the RequestLocaleFilter

1.1.2. The RequestLocaleFilter sets a request attribute with the locale.

1.1.3. The RequestLocaleFilter sets the struts session attributes with the locale.

1.1.4. The RequestLocaleFilter sets the jstl session attributes with the locale.

1.1.5. The RequestLocaleFilter sets the locale of the response.

1.1.6. The RequestLocaleFilter creates a set of hidden input fields based on the request query parameters except for the locale parameter.

1.1.7. The hidden input fields are stored in a request attribute.

1.2. The application server calls the DispatcherServlet

1.2.1. The DispatcherServlet first calls the interceptors

1.2.1.1. The localeChangeInterceptor checks if there is a locale parameter on the request.

1.2.1.2. If there is a locale parameter on the request, the localeChangeInterceptor calls the setLocale of the localeResolver

1.2.2. The DispatcherServlet calls the handleRequest of the Controller that matches the request URL.

Configuration:

Just like any other filter the RequestLocaleFilter is configured in the web.xml file. It requires no additional information.

[/web]/WEB-INF/web.xml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd"> <web-app> … <filter> <filter-name>Request locale filter</filter-name> <filter-class>eu.cec.ergonomics.filter.RequestLocaleFilter</filter-class> </filter> … <filter-mapping> <filter-name>Request locale filter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> … </web-app>

Configuration File 37 Web.xml: Request Locale Filter

Page 103: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 103 of 127

The LocaleChangeInterceptor and LocaleResolver beans are defined in the applicationContext.xml file.

[/web]/WEB-INF/applicationContext.xml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean id="localeResolver" class="org.springframework.web.servlet.i18n.CookieLocaleResolver"/> <bean id="localeChangeInterceptor" class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"/> … </beans>

Configuration File 38 Application Context: Locale Resolver & Change Interceptor

The LocaleChangeInterceptor is attached to the handlermapping of the DispatcherServlet in the sampleapp-servlet.xml file.

[/web]/WEB-INF/sampleapp-servlet.xml <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> … <bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> <property name="interceptors"> <list> <ref bean="localeChangeInterceptor"/> </list> </property> <property name="mappings"> <props> <prop key="/defaultMenu.do">defaultMenuController</prop> <prop key="/error404.do">error404Controller</prop> <prop key="/welcome.do">welcomeController</prop> … </props> </property> </bean> </beans>

Configuration File 39 Servlet Context: Locale Change Interceptor

5.2.3.9.4. DatabaseMessageSource

Multilingual messages using a messagesource based on properties files are already described in the previous chapters. An alternative is to put the messages in a database and use a databaseMessageSource.

Configuration and dependencies:

The database message source library depends on Hibernate and the ODMG (Object Data Management Group) library. These libraries are put in the lib directory during the generation of a new project.

Page 104: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 104 of 127

[/web]/WEB-INF/web.xml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd"> <web-app> … <context-param> <param-name>contextConfigLocation</param-name> <param-value> … /WEB-INF/dataAccessContext.xml /WEB-INF/applicationContext.xml /WEB-INF/dao/databaseMessageSource.xml </param-value> </context-param> … </web-app>

Configuration File 40 Web.xml: DatabaseMessageSource

[/web]/WEB-INF/applicationContext.xml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> … <bean id="messageSource" class="eu.cec.databaseMessageSource.support.DatabaseMessageSource"> <property name="dao"> <ref bean="databaseMessageSourceDao"/> </property> <property name="defaultLanguage"> <value>en</value> </property> <property name="useCache"> <value>false</value> </property> </bean> </beans>

Configuration File 41 Application Context: Database messageSource

[/web]/WEB-INF/dao/databaseMessageSource.xml (Web.xml: DatabaseMessageSource) <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean id="databaseMessageSourceDao" class="eu.cec.databaseMessageSource.dao.hibernate .DatabaseMessageSourceDaoImplementation"> <property name="sessionFactory"> <ref bean="hibernateSessionFactory"/> </property> </bean> </beans>

Configuration File 42 DatabaseMessageSource.xml

Page 105: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 105 of 127

[/web]/WEB-INF/dataAccessContext.xml (Web.xml: DatabaseMessageSource) <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> … <!-- Transaction manager for Hibernate SessionFactory (alternative to JTA) --> <bean id="hibernateTransactionManager" class="org.springframework.orm.hibernate.HibernateTransactionManager"> <property name="sessionFactory"> <ref local="hibernateSessionFactory" /> </property> </bean> <!-- Hibernate SessionFactory --> <bean id="hibernateSessionFactory" class="org.springframework.orm.hibernate.LocalSessionFactoryBean"> <property name="dataSource"> <ref bean="dataSource" /> </property> <property name="mappingResources"> <list> <value>hibernate/I18N.hbm.xml</value> </list> </property> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect"> ${hibernate.dialect} </prop> </props> </property> </bean> </beans>

Configuration File 43 Data Access Context: Database messageSource

[/src]/hibernate/I18N.hbm.xml (Data Access Context: Database messageSource) <?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN" "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd"> <hibernate-mapping> <class name="eu.cec.databaseMessageSource.domain.Code" table="T_I18N_CODES"> <id column="CODEID" type="long" name="id"> <generator class="uuid.hex"/> </id> <property column="CODECD" length="50" name="code" not-null="true" type="string"/> <map name="translations" table="T_I18N_CODES_TRANS" lazy="false" cascade="save-update" > <key column="CODEID" foreign-key="CODEID"/> <index column="CODELANG" type="string" length="2" /> <one-to-many class="eu.cec.databaseMessageSource.domain.Translation"/> </map> </class>

Page 106: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 106 of 127

<class name="eu.cec.databaseMessageSource.domain.Translation" table="T_I18N_CODES_TRANS"> <id column="TRANSID" name="id" type="long"> <generator class="uuid.hex"/> </id> <property column="CODEID" name="codeId" type="long" not-null="true"/> <property column="CODELANG" name="language" type="string" length="2"/> <property column="CODETRANS" length="1024" name="translation" not-null="true" type="string"/> </class> <class name="eu.cec.databaseMessageSource.domain.List" table="T_I18N_LISTS"> <id column="LISTID" type="long" name="id"> <generator class="uuid.hex"/> </id> <property column="LISTCD" length="50" name="code" not-null="true" type="string"/> <property column="LISTDESC" length="200" name="description" not-null="true" type="string"/> <list name="codes" table="T_I18N_LISTS_CODES" lazy="false"> <key column="LISTID"/> <index column="LISTORDER"/> <many-to-many class="eu.cec.databaseMessageSource.domain.Code" column="CODEID"/> </list> </class> </hibernate-mapping>

Configuration File 44 Database messageSource Hibernate Mapping

Page 107: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 107 of 127

/db/oracle/create-databaseMessageSource.sql CREATE TABLE t_i18n_codes ( CODEID NUMBER(10) PRIMARY KEY, CODECD VARCHAR2(50 BYTE) NOT NULL, CODEDTEFFET DATE DEFAULT '01-JAN-2004' NOT NULL ); CREATE TABLE t_i18n_codes_trans ( TRANSID NUMBER(10) PRIMARY KEY, CODEID NUMBER(10), CODELANG VARCHAR2(2 BYTE) DEFAULT 'EN' NOT NULL, CODETRANS VARCHAR2(1024 BYTE), CODEDTEFFET DATE DEFAULT '01-JAN-2004' NOT NULL ); CREATE TABLE t_i18n_lists ( LISTID NUMBER(10) PRIMARY KEY, LISTCD VARCHAR2(50 BYTE), LISTDESC VARCHAR2(200 BYTE) ); CREATE TABLE t_i18n_lists_codes ( LISTID NUMBER(10), CODEID NUMBER(10), LISTORDER NUMBER(6) ); CREATE SEQUENCE SEQ_I18N_CODES; CREATE SEQUENCE SEQ_I18N_CODES_TRANS; CREATE SEQUENCE SEQ_I18N_LISTS; INSERT INTO t_i18n_codes VALUES (SEQ_I18N_CODES.NEXTVAL, 'welcome.title', (SELECT SYSDATE FROM DUAL)); INSERT INTO t_i18n_codes VALUES (SEQ_I18N_CODES.NEXTVAL, 'welcome.user', (SELECT SYSDATE FROM DUAL)); … INSERT INTO t_i18n_codes_trans VALUES (SEQ_I18N_CODES_TRANS.NEXTVAL, (SELECT codeid FROM t_i18n_codes WHERE codecd = 'welcome.user' AND rownum = 1 ), 'en', 'User:' , (SELECT SYSDATE FROM DUAL)); INSERT INTO t_i18n_codes_trans VALUES (SEQ_I18N_CODES_TRANS.NEXTVAL, (SELECT codeid FROM t_i18n_codes WHERE codecd = 'welcome.title' AND rownum = 1 ), 'en', 'Welcome to the application' , (SELECT SYSDATE FROM DUAL)); INSERT INTO t_i18n_codes_trans VALUES (SEQ_I18N_CODES_TRANS.NEXTVAL, (SELECT codeid FROM t_i18n_codes WHERE codecd = 'welcome.user' AND rownum = 1 ), 'fr', 'Utilisateur:' , (SELECT SYSDATE FROM DUAL)); INSERT INTO t_i18n_codes_trans VALUES (SEQ_I18N_CODES_TRANS.NEXTVAL, (SELECT codeid FROM t_i18n_codes WHERE codecd = 'welcome.title' AND rownum = 1 ), 'fr', 'Bienvenue à l''application!' , (SELECT SYSDATE FROM DUAL)); … COMMIT;

Configuration File 45 Create Database messageSource SQL

Page 108: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 108 of 127

5.2.3.10. Struts MVC As an alternative to the spring MVC framework explained in “5.2.3 User Interface Layer” you can also use the Struts framework. Set use.springMVC to false and use.struts to true in the preferences properties file.

The core of the Struts framework is a flexible control layer based on standard technologies like Java Servlets, JavaBeans, ResourceBundles, and XML, as well as various Jakarta Commons packages. Struts encourages application architectures based on the Model 2 approach, a variation of the classic Model-View-Controller (MVC) design paradigm.

Struts provides its own Controller component and integrates with other technologies to provide the Model and the View. For the Model, Struts can interact with standard data access technologies, like JDBC and EJB, as well as most any third-party packages, like Hibernate, iBATIS, or Object Relational Bridge. For the View, Struts works well with JavaServer Pages, including JSTL and JSF, as well as Velocity Templates, XSLT, and other presentation systems.

Struts uses a configuration file to initialize its own resources. These resources include ActionForms to collect input from users, ActionMappings to direct input to server-side Actions, and ActionForwards to select output pages.

Action package:

The actions package contains the struts action controllers. Subpackages are used for organizing them according functionality. E.g.: notes, welcome, errors …

The actions take the input data from a form bean, call the right business logic service and forward to the next action or the view to display. (= Update Controllers)

Page 109: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 109 of 127

Controller package:

The controller package contains the tiles controllers. These controllers only prepare data for the view. They do not receive input or control the page flow. (= Display Controllers)

Page 110: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 110 of 127

Class Diagram:

Figure 22 Struts Class Diagram

Based on the configuration file struts will first determine which action is mapped to the requested URL. Next it will create the associated form bean, populate it with the data from the request and validate the form bean. If there are no validation errors then the action is executed and the form is passed as parameter. The action should call the appropriate business logic using the data from the form bean.

Page 111: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 111 of 127

Sequence Diagram:

Figure 23 Struts Sequence Diagram

Page 112: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 112 of 127

Flow Description:

1. The client sends a request to the application server

1.1. The RequestDispatcher tries to match the request URL with the servlet URL patterns. The incoming request matches the URL pattern of the ActionServlet: “*.do” so the RequestDispatcher orders the ActionServlet to process the request.

1.1.1. The ActionServlet asks the ModuleConfig (struts-config.xml) for the ActionMapping that corresponds with the given request (path).

1.1.2. The ActionServlet gets the form name associated with the ActionMapping.

1.1.3. The ActionServlet asks the ModuleConfig for the form definition of the given formname.

1.1.4. The ActionServlet creates the form.

1.1.5. The ActionServlet populates the form.

1.1.5.1. Data is retrieved from the request.

1.1.5.2. Data is stored in the form.

1.1.6. The validate method of the form is invoked. (If validation fails the request is forwarded to the URL specified in the input attribute of the action mapping)

1.1.7. The ActionServlet gets the action class associated with the ActionMapping

1.1.8. The ActionServlet creates an instance of the action class.

1.1.9. The action is executed. The ActionMapping and the form containing the data from the request are passed as parameters.

1.1.9.1. The Action makes some preparations and calls the necessary business logic.

1.1.9.2. Depending on the result (success, failure …) the Action finds the right forward in the ActionMapping and returns the forward to the ActionServlet.

1.1.10 The ActionServlet orders the RequestDispatcher to forward the request. The forward can lead to another action, servlet, html page or jsp page.

Page 113: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 113 of 127

Participants and collaborations:

RequestDispatcher (web container)

The requestdispatcher is an object that receives requests from the client and sends them to any resource (such as a servlet, HTML file, or JSP file) on the server.

ActionServlet

The ActionServlet provides the "controller" in the Model-View-Controller (MVC) design pattern for web applications. Based on the request URL it selects an Action and executes it.

ModuleConfig

The ModuleConfig is a collection of static configuration information that describes a Struts-based module. The configuration is read from the struts-config.xml file at startup.

ActionMapping

An ActionMapping represents the information that the controller, RequestProcessor, knows about the mapping of a particular request to an instance of a particular Action class. This includes the classname of the action, classname of the linked form and local forward definitions.

ActionForm

An ActionForm is a JavaBean optionally associated with one or more ActionMappings. Such a bean will have had its properties initialized from the corresponding request parameters before the corresponding Action.execute method is called.

When the properties of this bean have been populated, but before the execute method of the Action is called, this bean's validate method will be called, which gives the bean a chance to verify that the properties submitted by the user are correct and valid.

Action

An Action is an adapter between the contents of an incoming HTTP request and the corresponding business logic that should be executed to process this request. The ActionServlet will select an appropriate Action for each request, create an instance (if necessary), and call the execute method.

Service

Service provided by the business logic tier.

Page 114: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 114 of 127

Example: addNote

Sequence Diagram:

Figure 24 Struts - addNote Sequence Diagram

Flow Description:

1. The AddNoteAction is executed. The ActionMapping object and a NoteForm are passed as parameters.

1.1. The AddNoteAction creates a Note domain object with the data from the NoteForm.

1.1.1. A Note domain object is created.

1.1.2. The action gets the data from the form (converts it if necessary)

1.1.3.. The data is put in the note domain object.

1.2. A NotesDelegate object is created.

1.2.1. The notesDelegate gets an instance of the Service Locator

Page 115: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 115 of 127

1.2.2. The notesDelegate asks the service locator for a notesService and stores it in an attribute.

1.3. The addNote method is invoked on the notesDelegate.

1.3.1. The method is delegated to the notesService retrieved from the servicelocator

1.4. The addNote asks the actionMapping for the forward with name “success” and returns it to the caller. In this case the result will be “/examples/notes/list.do”.

Source Code: public class AddNoteAction extends Action { private Note createNote(NoteForm noteForm) { Note result = new Note(); // 1.1.1 result.setTitle(noteForm.getTitle()); // 1.1.2&3 result.setMessage(noteForm.getMessage()); result.setReference(noteForm.getReference()); return result; } public ActionForward execute(ActionMapping mapping, ActionForm form, // 1 HttpServletRequest request, HttpServletResponse response) throws Exception { NoteForm noteForm = (NoteForm) form; Note note = createNote(noteForm); // 1.1 NotesDelegate notesDelegate = new NotesDelegate(); // 1.2 notesDelegate.addNote(note); // 1.3 return mapping.findForward("success"); // 1.4 } } public class NoteForm extends ValidatorForm { private String title; private String message; private String reference; public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } public String getReference() { return reference; } public void setReference(String reference) { this.reference = reference; } }

Page 116: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 116 of 127

Dependencies and Configuration:

Three parts in the web.xml file need to be configured for using the struts framework. First you need to add the struts action servlet. The config parameter refers to the struts configuration file. (Dependency between web.xml and struts-config.xml)

Second you need to add a servlet mapping that matches a URL pattern to the struts action servlet. Usually the pattern is “*.do”.

Finally you need to add the struts taglibs.

[/web]/WEB-INF/web.xml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd"> <web-app> … <!-- Struts Action servlet --> <servlet> <servlet-name>sampleapp</servlet-name> <servlet-class>org.apache.struts.action.ActionServlet</servlet-class> <init-param> <param-name>config</param-name> <param-value>/WEB-INF/struts-config.xml</param-value> </init-param> <init-param> <param-name>debug</param-name> <param-value>3</param-value> </init-param> <init-param> <param-name>detail</param-name> <param-value>3</param-value> </init-param> <load-on-startup>0</load-on-startup> </servlet> … <!-- Struts Action servlet mapping --> <servlet-mapping> <servlet-name>sampleapp</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping> … <!-- Struts Tag Library Descriptors --> <taglib> <taglib-uri>/tags/struts-bean</taglib-uri> <taglib-location>/WEB-INF/tld/struts-bean-el.tld</taglib-location> </taglib> <taglib> <taglib-uri>/tags/struts-html</taglib-uri> <taglib-location>/WEB-INF/tld/struts-html-el.tld</taglib-location> </taglib> <taglib> <taglib-uri>/tags/struts-logic</taglib-uri> <taglib-location>/WEB-INF/tld/struts-logic-el.tld</taglib-location> </taglib> <taglib> <taglib-uri>/tags/struts-nested</taglib-uri> <taglib-location>/WEB-INF/tld/struts-nested-el.tld</taglib-location> </taglib> <taglib> <taglib-uri>/tags/struts-tiles</taglib-uri> <taglib-location>/WEB-INF/tld/struts-tiles-el.tld</taglib-location> </taglib> …

Page 117: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 117 of 127

</web-app>

Configuration File 46 Web.xml: Struts

The struts configuration file contains information about the form beans, exceptions, forwards, action mappings, message resource bundle and plugins.

Form beans are defined by their name and class.

Global Forwards are defined by their name and path.

Actions are defined by their path, form name and action class (or forward URL). Forwards defined inside the action element are local forwards. The optional input attribute specifies the forward URL to use when validation of the form fails.

The message-resources element specifies the resource bundle to be used by struts for i18n support. (Dependency between struts-config.xml and ApplicationResources.properties)

Struts PlugIns are configured using the <plug-in> element. Tiles and the validator plugin are configured by the reference application. More information about Tiles or the validator plugin can be found in the next sections of the document. (Dependencies between struts-config.xml and tiles-defs.xml, validation.xml & validator-rules.xml)

[/web]/WEB-INF/struts-config.xml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.2//EN" "http://struts.apache.org/dtds/struts-config_1_2.dtd"> <struts-config> <form-beans> <form-bean name="noteForm" type="eu.cec.sampleapp.forms.noteForm" /> … </form-beans> <global-exceptions /> <global-forwards /> <action-mappings> <action path="/error404" forward="error404view" /> <action path="/defaultMenu" forward="defaultMenuView" /> <action path="/welcome" forward="welcomeView" /> <action path="/examples/notes/list" forward="notesListView" /> <action path="/examples/notes/add" name="noteForm" validate="false" type="eu.cec.sampleapp.actions.notes.InitAddNoteAction"> <forward name="success" path="/examples/notes/inputNew.do" redirect="true" /> </action> <action path="/examples/notes/viewAdd" forward="addNoteView" /> <action path="/examples/notes/inputNew" name="noteForm" validate="false" type="eu.cec.sampleapp.support.actions.FormDispatcherAction"> <forward name="view" path="/examples/notes/viewAdd.do" /> <forward name="process" path="/examples/notes/processNew.do" /> <forward name="cancel" path="/examples/notes/list.do" redirect="true" /> </action> <action path="/examples/notes/processNew" name="noteForm" validate="true" input="/examples/notes/viewAdd.do" type="eu.cec.sampleapp.actions.notes.AddNoteAction"> <forward name="success" path="/examples/notes/list.do" redirect="true"/> </action>

Page 118: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 118 of 127

… </action-mappings> <message-resources parameter="ApplicationResources" /> <plug-in className="org.apache.struts.tiles.TilesPlugin" > <set-property property="definitions-config" value="/WEB-INF/tiles-defs.xml" /> <set-property property="definitions-parser-validate" value="false" /> <set-property property="moduleAware" value="false" /> </plug-in> <plug-in className="org.apache.struts.validator.ValidatorPlugIn"> <set-property property="pathnames" value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml"/> </plug-in> </struts-config>

Configuration File 47 Struts-config.mxl

Page 119: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 119 of 127

5.2.3.10.1. Tiles

Tiles builds on the "include" feature provided by the JavaServer Pages specification to provide a full-featured, robust framework for assembling presentation pages from component parts. Each part ("Tile") can be reused as often as needed throughout your application. This reduces the amount of markup that needs to be maintained and makes it easier to change the look and feel of a website.

Configuration:

First of all you have to enable the tiles plugin in your struts configuration file.

The tiles are defined in an xml configuration file (usually “tiles-defs.xml”). A tile definition is identified by a name.

The simplest form of a tile is a tile defined only by a jsp page. E.g.: menuDef.

More complex tile definitions have attributes definied in “put” child elements. If you compare building pages with tiles to procedural programming a tile is the equivalent of a procedure and the attributes are the parameters.

An even more powerful feature of tiles is the possibility to extend definitions. When you extend a definition you inherit the page and all the attributes. You can add new attributes or you can override existing ones.

Last but not least you can assign a controller to a tile definition. A tiles controller is basically a mini-Action. It prepares data for viewing much like a Struts Action does but they are not designed for controlling page flow or receiving input! That's what Actions do. Each tile in an application can have it's own separate controllers that prepare data just for them.

[/web]/WEB-INF/tiles-defs.xml (Struts-config.mxl) <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE tiles-definitions PUBLIC "-//Apache Software Foundation//DTD Tiles Configuration//EN" "http://jakarta.apache.org/struts/dtds/tiles-config.dtd"> <tiles-definitions> <definition name="menuDef" page="/WEB-INF/jsp/template/menu.jsp" /> <definition name="headerDef" page="/WEB-INF/jsp/template/header.jsp"> <put name="pageTitleKey" value="CHANGE-ME"/> <put name="menu" value="menuDef"/> </definition> <definition name="contentDef" page="/WEB-INF/jsp/template/empty.jsp"/> <definition name="masterDef" page="/WEB-INF/jsp/template/empty.jsp"/> <definition name="detailDef" page="/WEB-INF/jsp/template/empty.jsp"/> <definition name="footerDef" page="/WEB-INF/jsp/template/footer.jsp"/> <definition name="template" page="/WEB-INF/jsp/template/template.jsp"> <put name="pageTitleKey" value="CHANGE-ME"/> <put name="header" value="headerDef"/> <put name="content" value="contentDef"/> <put name="footer" value="footerDef"/> </definition> <definition name="masterdetail" extends="template"> <put name="content" value="masterdetailContent"/> </definition> <definition name="masterdetailContent" page="/WEB-INF/jsp/template/master_detail.jsp"> <put name="master" value="masterDef"/> <put name="detail" value="detailDef"/> </definition>

Page 120: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 120 of 127

… <definition name="welcomeView" extends="template"> <put name="pageTitleKey" value="welcome.page.title"/> <put name="content" value="welcomeContent"/> </definition> <definition name="welcomeContent" page="/WEB-INF/jsp/welcome/welcome.jsp"/> <definition name="notesListView" extends="template"> <put name="pageTitleKey" value="notes.list.title"/> <put name="content" value="notesListContent"/> </definition> <definition name="notesListContent" page="/WEB-INF/jsp/examples/notes/list.jsp" controllerClass="eu.cec.sampleapp.controller.notes.ListNotesController"/> … <definition name="addNoteView" extends="template"> <put name="pageTitleKey" value="notes.form.title"/> <put name="content" value="addNoteContent"/> </definition> <definition name="addNoteContent" page="/WEB-INF/jsp/examples/notes/form.jsp"> <put name="action" value="add"/> </definition> … </tiles-definitions>

Configuration File 48 Tiles-defs.xml

Usage:

Tiles can be used by struts. When controlling the flow a forward can point to a tile definition instead of an action, html or jsp page. <action path="/examples/notes/list" forward="notesListView" />

Tiles can also be used by jsp. Use the tiles insert tag to insert a tile into your page <%@ page language="java" %> <%@ taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>My first tile</title> </head> <body> This page uses tiles <br> <tiles:insert definition="helloView"> <tiles:put name="name">Geert</tiles:put> </tiles:insert> </body> </html>

Page 121: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 121 of 127

5.2.3.10.2. Validator

Once you have configured the Validator Plug-In, so that it can load your Validator Resources, you just have to extend ValidatorForm (or ValidatorActionForm) instead of ActionForm. Then when the validate method is called, the action's name (or path) attribute from the Struts Configuration is used to load the validations for the current form. The form element's name (or path) attribute in the Validator configuration should match the action element's name attribute.

Configuration:

[/web]/WEB-INF/validation.xml (Struts-config.mxl) <form-validation> <global/> <formset> <form name="/examples/notes/processNew"> <field property="message" depends="required"> <msg name="required" key="required.note.message"/> </field> <field property="reference" depends="mask"> <msg name="mask" key="malformed.note.reference"/> <var> <var-name>mask</var-name> <var-value>[a-zA-Z][a-zA-Z][a-zA-Z]-\d\d\d\d-\d\d</var-value> </var> </field> <field property="title" depends="required"> <msg name="required" key="required.note.title"/> </field> </form> </formset> … </form-validation>

Configuration File 49 Validation.xml

[/web]/WEB-INF/validator-rules.xml (Struts-config.mxl) <!DOCTYPE form-validation PUBLIC "-//Apache Software Foundation //DTD Commons Validator Rules Configuration 1.1.3//EN" "http://jakarta.apache.org/commons/dtds/validator_1_1_3.dtd"> <form-validation> <global> <validator name="required" classname="org.apache.struts.validator.FieldChecks" method="validateRequired" methodParams="java.lang.Object, org.apache.commons.validator.ValidatorAction, org.apache.commons.validator.Field, org.apache.struts.action.ActionMessages, javax.servlet.http.HttpServletRequest" msg="errors.required"/> <validator name="mask" classname="org.apache.struts.validator.FieldChecks" method="validateMask" methodParams="java.lang.Object, org.apache.commons.validator.ValidatorAction, org.apache.commons.validator.Field,

Page 122: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 122 of 127

org.apache.struts.action.ActionMessages, javax.servlet.http.HttpServletRequest" depends="" msg="errors.invalid"/> <validator name="date" classname="org.apache.struts.validator.FieldChecks" method="validateDate" methodParams="java.lang.Object, org.apache.commons.validator.ValidatorAction, org.apache.commons.validator.Field, org.apache.struts.action.ActionMessages, javax.servlet.http.HttpServletRequest" depends="" msg="errors.date" jsFunctionName="DateValidations"/> … <validator name="includeJavaScriptUtilities" classname="" method="" methodParams="" depends="" msg="" jsFunction="org.apache.commons.validator.javascript.validateUtilities"/> </global> </form-validation>

Configuration File 50 Validator-rules.xml

Page 123: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 123 of 127

6. APPENDIX A - NAMING CONVENTIONS

General conventions:

• Don’t use abbreviations unless they are commonly accepted e.g.: HTTP, URL …

• Try to keep names simple and descriptive

Packages:

• The prefix of a unique package name is always written in all-lowercase ASCII letters and should be of the top-level domain name: “eu.cec”

• Subsequent components of the package name should contain the application, layer and/or component name e.g. “eu.cec.sampleapp.dao.notes”

Class names:

• Class names should be nouns, in mixed case with the first letter of each internal word capitalized. Try to keep your class names simple and descriptive.

Interfaces:

• Interface names should be capitalized like class names.

Methods:

• Methods should be verbs, in mixed case with the first letter lowercase, with the first letter of each internal word capitalized. (Camel Case)

Variables:

• Variables are in mixed case with a lowercase first letter. Internal words start with capital letters. Variable names should not start with underscore _ or dollar sign $ characters, even though both are allowed.

• Variable names should be short yet meaningful. The choice of a variable name should be mnemonic- that is, designed to indicate to the casual observer the intent of its use. One-character variable names should be avoided except for temporary "throwaway" variables. Common names for temporary variables are i, j, k, m, and n for integers; c, d, and e for characters

Constants:

• The names of variables declared class constants should be all uppercase with words separated by underscores ("_").

Filenames:

• Java source files should follow the naming convention of the class name.

• Extensions should be lower case.

Beans:

• Bean names should be capitalized like variable names.

Page 124: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 124 of 127

7. INDEX

7.1. Figures

Deployment Diagram .............................................................................................................................. 9 Component Diagram ............................................................................................................................. 10 Data Access Layer Component Diagram .............................................................................................. 11 Domain Class Diagram.......................................................................................................................... 12 Notes DAO Class Diagram ................................................................................................................... 14 Notes DAO - getNotes Sequence Diagram ........................................................................................... 16 EJB 2.0 CMP Component Diagram ...................................................................................................... 33 EJB 2.0 CMP Class Diagram ................................................................................................................ 34 Services Component Diagram............................................................................................................... 49 Services Class Diagram......................................................................................................................... 50 Services - getNotes Sequence Diagram................................................................................................. 51 Transaction Class Diagram.................................................................................................................... 55 Transaction Sequence Diagram............................................................................................................. 57 Logging Sequence Diagram .................................................................................................................. 63 EJB Services Class Diagram ................................................................................................................. 69 User Interface Component Diagram...................................................................................................... 73 Controller Class Diagram...................................................................................................................... 74 User Interface - getNotes Sequence Diagram........................................................................................ 76 Thread Context Sequence Diagram....................................................................................................... 87 Ecas Authentication Sequence Diagram ............................................................................................... 92 Locale Processing Sequence Diagram................................................................................................. 101 Struts Class Diagram........................................................................................................................... 110 Struts Sequence Diagram .................................................................................................................... 111 Struts - addNote Sequence Diagram.................................................................................................... 114

Page 125: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 125 of 127

7.2. Configuration Files

Notes DAO spring-beans....................................................................................................................... 20 Data Access Context spring-beans: DataSource properties .................................................................. 21 JDBC properties .................................................................................................................................... 21 Application Context spring-beans: propertyConfigurer........................................................................ 22 Web.xml: Context Loader ..................................................................................................................... 23 Data Access Context: dataSource option .............................................................................................. 25 jdbc.properties: basic vs jndi ................................................................................................................. 26 Data Access Context: Hibernate............................................................................................................ 29 DataAccess Context: EJB 2.0 CMP ...................................................................................................... 39 notes.xml: EJB 2.0 CMP ....................................................................................................................... 39 serviceContext.xml: EJB 2.0 CMP........................................................................................................ 40 ejb-jar.xml: EJB 2.0 CMP ..................................................................................................................... 42 weblogic-cmp-rdbms-jar.xml ................................................................................................................ 43 weblogic-ejb-jar.xml ............................................................................................................................. 44 application.xml: EJB 2.0 CMP.............................................................................................................. 45 Web.xml: Log4J .................................................................................................................................... 47 log4j.properties...................................................................................................................................... 48 Services Context spring beans............................................................................................................... 55 Services Context: Transaction............................................................................................................... 60 DataAccess Context: Transaction.......................................................................................................... 61 Sampleapp Servlet: Logging ................................................................................................................. 65 EJB Services: Services Context Implementation .................................................................................. 71 EJB Services: Services Context Proxy .................................................................................................. 72 Note Controllers .................................................................................................................................... 80 Web.xml: Controllers contextConfigLocation ...................................................................................... 81 Sampleapp-servlet.xml: viewResolver & urlMapping .......................................................................... 82 Notes.properties: Views ........................................................................................................................ 82 Template.properties ............................................................................................................................... 83 Application Context: messageSource.................................................................................................... 83 Notes.properties: Messages ................................................................................................................... 84 Web.xml: Error Page............................................................................................................................. 85 Web.xml: Context Information ............................................................................................................. 89 Web Application Libraries: Taglibs ...................................................................................................... 90 Web.xml: Taglibs .................................................................................................................................. 91 Web.xml: Ecas Security ........................................................................................................................ 97 Web.xml: Request Character Encoding ................................................................................................ 98

Page 126: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 126 of 127

Web.xml: Request Locale Filter.......................................................................................................... 102 Application Context: Locale Resolver & Change Interceptor............................................................. 103 Servlet Context: Locale Change Interceptor ....................................................................................... 103 Web.xml: DatabaseMessageSource .................................................................................................... 104 Application Context: Database messageSource .................................................................................. 104 DatabaseMessageSource.xml .............................................................................................................. 104 Data Access Context: Database messageSource ................................................................................. 105 Database messageSource Hibernate Mapping..................................................................................... 106 Create Database messageSource SQL................................................................................................. 107 Web.xml: Struts................................................................................................................................... 117 Struts-config.mxl................................................................................................................................. 118 Tiles-defs.xml...................................................................................................................................... 120 Validation.xml..................................................................................................................................... 121 Validator-rules.xml.............................................................................................................................. 122

Page 127: Reference Application Architectureec.europa.eu/regional_policy/archive/tender/pdf/200736/annex1_regional_expenditure.pdfuse.documentation = true use.ecas = true use.ejb = false

DIGIT A4 27/06/2007 Page 127 of 127

8. REFERENCES

8.1. Books

“Core J2EE Patterns”, Prentice Hall, Deepak Alur – John Crupi – Dan Malks

“Better, Faster, Lighter Java”, O’Reilly, Bruce A. Tate & Justin Gehtland

8.2. Links

Reference Application &

Ergonomics taglib

http://www.cc.cec/CITnet/modules/xfmod/project/?refapp

Ant http://ant.apache.org/

Log4J http://logging.apache.org/log4j/

Commons Logging http://jakarta.apache.org/commons/logging/

Commons Database Connection Pool http://jakarta.apache.org/commons/dbcp/

Commons Attributes http://jakarta.apache.org/commons/attributes/

Commons Validator http://jakarta.apache.org/commons/validator/

Displaytag http://displaytag.sourceforge.net/

J2EE http://java.sun.com/j2ee/

EJB http://java.sun.com/ejb/

JDBC http://java.sun.com/products/jdbc/

JNDI http://java.sun.com/products/jndi/

JSTL http://java.sun.com/products/jsp/jstl/

JSTL Reference Implementation http://jakarta.apache.org/taglibs/

ODMG http://www.odmg.org/

Hibernate http://www.hibernate.org/

Spring http://www.springframework.org/

Struts http://struts.apache.org/

Tiles http://www.lifl.fr/~dumoulin/tiles/

Inversion of Control Containers and the Dependency Injection pattern

http://www.martinfowler.com/articles/injection.html

ECAS http://www.cc.cec/CITnet/modules/xfmod/project/?ecas