Transcript Slide 1
NAAM
ADF Development
More tales from the trenches
Aino Andriessen
AMIS Services
•
•
•
•
•
•
Systems integrator
Co-sourcing
Maintenance
Oracle, Java, Open Source, ADF, DBA, SOA
AMIS technology school
Pagoni
• http://www.amis.nl
• http://technology.amis.nl/blog/
Aino Andriessen
•
•
•
•
•
•
•
Technical Consultant
Technical Architect
Java, ADF, PL/SQL, XML, ...
SOA , Integration
Software engineering
Quality management
Agile development
• [email protected]
• http://www.fttech.net
Stakeholders
customer
developer
maintenance
project
lead
better according to... Customer
better according to... Project lead
better according to... Developer
better according to... Maintenance
better according to... Girlfriend
• How can we make better ADF applications?
5 essentials
•
•
•
•
•
Communication
Responsibility
Knowledge
Organization
Fun
• Let's start coding...
• Sorry, not yet...
Organization...
•
•
•
•
•
•
•
•
•
Project
Development process
Skills
Project structure (file structure)
Code
Design and Architecture
Documentation
Communication
Infrastructure
Source
control
Tests
Developer
Developer
2
Developer
2
Developer
2
Inspection
Documentation
site
Reports
Documentation
Custom
Corporate
Library
Build
automation
Issue reports
Delivery environments
Library
Public
Library
Production
Acceptance
Test
Issue
management
Integration
Development
• Can we now start coding?
• Almost...
Development principles
• OK, wake up and let's get to business...
• Build an ADF - JHeadstart application
• Address common and not so common issues
• ADF 10g
– Some 11g
Demo
• Regatta Management System
• Application to support sailing regatta's.
– maintain regatta's
– registration
– enter racing data
– results
Development Goal
• Match implementation against stakeholders'
concerns :
– Functional
– Maintainable
– Stable
– Budget
– Organized
– Fun
–...
Business Logic implementation
• Business Logic can be implemented at many locations
– ADF Faces components
•
•
•
•
Managed beans
Backing beans
EL-expressions
Attributes
– Service methods
– VO's
• Attributes : transient, calculated
• Methods
– Entities
• Attributes
• Validators
– Database
• Constraints
• Views
• Stored procedures
– ...
The (ADF) challenge
• Consistent and comprehensible
implementation of business logic.
FD
•
Requirements
–
–
Maintain regatta information
Allow sailors / boats to enter a regatta.
•
–
–
–
–
–
–
•
Register skipper and captain (owner) with some personal details
Schedule racings
Easy registration of race details, only by certain people
Publish results
Nice look and feel
Easy to use
Handle handicap system
Business rules
–
–
–
–
–
–
Participant, skipper, must be older than 18
Same boat may enter only once
Finishtime after starttime
Participant can have only one result
It should be able to reset the finish of a participants, in case of error
Register if the boat didn't start or finish, using the common codes like DNF, DNS, DSQ etc.
•
–
Extra information about this situation must be entered
Races cannot be scheduled at the same time
Functions / Use cases
•
•
•
•
•
Maintain regatta's
Register for a regatta
Enter racing data
Publish results
Supportive functions
ADF 'architecture'
• ADF applications tend to evolve instead of being
designed.
– Viewobjects are created when needed
– Managed beans are created as needed
– Application Modules function merely as a service-hatch
• ADF doesn't force you into an organized application,
except maybe the model and viewController.
• ADF offers multiple solutions for the same problem and
in the end all of them will eventually appear in the
application.
ADF architecture
ADF Faces
ADF model (binding)
ADF BC
Database
ADF architecture
ADF Faces
Managed beans
ADF model (binding)
ADF BC
Objects
Application Modules
ViewObjects
Entities
Database Stored Procedures
Tables
Views
Application Integration
ADF Application
Webser
vices
Files
Database
Notifica
tion
Messa
ging
Function / Use Case approach
• The application module, the service, is the
core of the application
• Each function / use case is implemented as a
service.
• Services can be nested
ADF
architecture
ADF Faces
Webser
vices
ADF model (binding)
Service
ADF BC
Webser
vices
Service
Service
Files
Database
Service
Notifica
tion
Service
Messa
ging
RMS Services
Datamodel
Datamodel 2
• Views
– 1 : 1 on tables : vpd,
– complex queries
• Stored procedures
• app_owner and app_user
Development
Development environment
•
•
•
•
•
•
JDeveloper 10g 10.1.3.4
JHeadstart 10g 10.1.3.3
Oracle 11g R1
OC4J 10.1.3.4
Maven 2.1
Subversion 1.5
JDeveloper Setup
• External tools
• Encoding UTF-8
– Preferences -> Environment
• Upgrade JDev svn client to 1.5
– http://technology.amis.nl/blog/5253/upgrade-jdeveloper10g-subversion-client
JDeveloper
• Organize imports
• Define .vm as text file
– preferences -> filetypes
• Default editors : source
– preferences -> filetypes
Project setup
Projects
common
General code, Baseclasses
Reusable's
database
deployment
Database code, scripts
(automated) Deploy to iAS
ear
model
viewController
Build deliverable, ear
ADF BC's
UI
ADF Faces
'External' libraries
lib
Maven conventions - code
Maven conventions - unittests
General
•
•
•
•
SRDemo
JHeadstart framework
Weblogs
Documentation
– Developer’s Guide For Forms/4GL Developers
• Simple Emp reference project
BC Creation
Default - create BC's from table
Default - create BC's from table
BC creation
1.
2.
3.
4.
5.
6.
Services
Entities
Associations
Viewobjects
Viewlinks
VO usages
• Apply naming conventions
– Refactor if needed
• Organize, organize, organize
Create Entities
• Create Business components
from table
– Refactor associations
• Base on table, change later to
database view
Edit entities
• Set Id from sequence
– DBSequence is a nightmare to refactor
• Control Hints
– Enter once, use often
Associations
• Association properties
– apply correct plural and singular
• Define Composition
Association
– Developer’s Guide For
Forms/4GL Developers - Chapter
6.3.3
Business rules
BR
Implementation
Participant, skipper, must be older than 18
Entity validation
Same boat may enter only once
Unique key
Finishtime after starttime
FE or DB or 'complex' entity
Participant can have only one result
Unique key
It should be able to reset the finish of a participants,
in case of error
FE function
Register if the boat didn't start or finish, using the
common codes like DNF, DNS, DSQ etc.
Datamodel, domain
Extra information about this situation must be
entered
FE, mandatory dependency
Races cannot be scheduled at the same time
Unique key?
A boat either has a finishtime or a special situation
Row validation
Entity Business Rules
• Mandatory, PK, UK
• Validation
– Declarative
– Method
– Rules
• Declare in project properties
– Very Reusable
• [Entity constraint]
– NO validation
– Only present for creating table from entity
Validators / Rules
• Create Registered Rule in project properties
– Or reuse an existing one
• Implement code in validateValue method
Validators
• Select the Rule as attribute validation
• Test
Entity Validation - remarks
• The setter immediate triggers the validation
– actually the setAttributeInternal(...)
• Validations are executed top to bottom
• Row validation is performed 'independent' of attribute validation.
• Declarative Date validators are limited
– Use Validators
• Using a select statement for validation is very limited (if it works at
all)
– Avoid it.
• Consider Validator when the same validation is entered multiple
times.
• Validator exception msg not published to the front-end (as we'll see
later)
(J)Unittesting Entities
• Create Application Module :
import oracle.jbo.client.Configuration;
RegistrationServiceImpl
_am;
public void setUp() {
_am = Configuration.createRootApplicationModule
("nl.amis.demo.rms.model.services.RegistrationService"
,"RegistrationServiceLocalURL");
}
public void tearDown () {
Configuration.releaseRootApplicationModule(_am, true);
}
• Create entity :
EntityDefImpl empdef =
(EntityDefImpl)EntityDefImpl.findDefObject
("nl.amis.demo.rms.model.entities.CrewMember");
crewMember = (CrewMemberImpl)empdef.createInstance2
(_am.getDBTransaction(), null);
• Execute test :
Date testDate = (Date)Date.getCurrentDate();
try {
crewMember.setBirthdate(testDate);
fail();
}
catch (Exception e) {
e.printStackTrace();
}
testDate = (Date)testDate.addMonths(-12*20);
try {
crewMember.setBirthdate(testDate);
}
catch (Exception e) {
fail();
e.printStackTrace();
}
Unit-testing
↑ code control
↑ code quality
↓ development time
•
•
•
•
•
'Automatic' regression test
TDD improves the testability of your code
Unit-testing increases your ADF skills
Easy debugging of BC's
Automated execution at continuous integration
Unittest framework
• TestBase per application module
– provide ServiceImpl
• Utility methods
– Create entity
• Standardization
– Authorization
– Context
I don't write
unittests
because it takes
too much time
I'll start the
application, login,
navigate to the right
screen and then
perform the correct
actions?
Then, how do you
test your code?
Gee, How long
does that take?
VO Remarks
• Often screen, Use Case driven
• Organize
– the number may increase rapidly
– Separate list-only VO's
• Apply naming conventions
–
–
–
–
plural
Lkp
Trnsnt
...By...
• Don't use 'automatic BC creation from database'
– Unless you like refactoring...
VO remarks
• Calculated attributes are not updated
automatically, but need a requery
– This may often result in complex code
Domain driven logic
• NoFinishCode
– DSQ, DNF, DNS
• define constants
or enum
• IsXXX attributes
VO client interface methods
• Implement VO related functions
– startRace()
– disqualifyParticipant()
– ..
• Maybe also published as Service interface
method
• Beware with nested applicationmodules to bind
the correct method
– or else the getCurrentRow does not work
– NB, bindings work ok
Bindings and Nested AM
Viewobject validation
• Override validate() method
• setter method
• throw JboException
– define your own
View object usages
• Naming conventions
• Organize them in services
Unittesting VO's (Usages)
• Basic test
– executeQuery
• Business Logic
• Beware of detail VO's
– they are direct available on the AM, but relate to
their parent
Programmatic viewobjects
• e.g. for Webservice clients
• See Developer’s Guide For Forms/4GL Developers Chapter 9
• JhsProgrammaticViewObject
– getJhsProgrammaticResultSet
• ! Executed many times
– Override executeQuery() to actually retrieve data
– Store result in JhsProgrammaticResultSet class variable
– Convert using
JhsProgrammaticHelper.convertBean
• Match attributes with ws return object
Re-use
•
•
•
•
•
Bases classes
Validators
Unittest utilities
Date handling
ADF Binding (model) methods
– SRDemo : JSFUtils and ADFUtils
•
•
•
•
•
•
•
JHeadstart templates
Business Components
Task flows
Beans
Converters
Filters
...
Organize Re-use
• Separate projects, libraries, and owners
• Review / audit criteria
Reuse BC's
•
•
•
•
Separate project
Create deliverable
Add jar to project
Import jar
• Beware, sharing database connection from
root application module
Refactoring BC's
• http://technology.amis.nl/blog/2859/fear-forrenaming-refactoring-adf-bc-objects-injdeveloper-is-not-unfounded
• Renaming and moving BC's is handled quite well.
• Bindings are not automatically adjusted
• JHeadstart is not automatically updated
– Generation errors
– Just reselect the attribute / group
• Try to be strongly typed
Refactoring remarks
• Matching subversion clients
• Refactoring DBSequence attributes is a pain...
• ADF does not always allow you to refactor, in
case of dependencies.
• Validator
– Re-registration of the Rule
• Beware of static 'dependencies' in the
JHeadstart templates
JHeadstart
• One application definition vs. multiple
– Can merge and split quite easily
– 11g support for multiple improved
• JHeadstart supports nested application modules
• Apply standards and naming conventions
• Configuration
– tools -> preferences
• e.g. item prompt
– AppDef root node
• AM superclass
Custom Templates
• Application hierarchy matches the default
• Documentation of templates
• Try to avoid hard-coded bindings
– difficult to refactor
– custom properties
• Buttons can be generated
– however, the binding is not
Common recommendations
• Understand the framework
• Avoid 'bindings', use a managed bean and
dependencies
• Custom bindings : Disable 'Clear Page
Definition'
• Close pagedefs before generation
Date and time
• Using Java Date and Calendar and oracle.jbo.domain.Date
and Timestamp can be tricky
– new oracle.jbo.domain.Date() ?
– new oracle.jbo.domain.Timestamp() ?
– Date.getCurrentDate() ?
– ((Date)Date.getCurrentDate()).timestampValue
• actually java.sql.Timestamp
• Current time?
Date and time - Calendar
Calendar c = Calendar.getInstance();
oracle.jbo.domain.Timestamp ts =
new Timestamp(c.getTime());
Timestamp ts =
new Timestamp(c. getTimeInMillis());
c.set(Calendar.HOUR_OF_DAY,5)
Date Time - JodaTime
DateTime dt = new DateTime();
Timestamp ts = new Timestamp(dt.getMillis());
DateTime dt=new Da
dt.getHourOfDay();
dt.plusMinutes(10);
dt.minusWeeks(5);
dt.isAfter(dt2);
dt.isBefore(dt2);
dt.isBeforeNow();teTime(2009,6,14,13,0,0,0)
Search Programmatic viewobject
• Standard JHeadstart Search
– Allows searching using the VO attributes
– Creates 'SQL formatted' ViewCriteria
• oracle.jheadstart.model.QueryCondition
• unusable for Programmatic viewobject
1. Somehow retrieve actual data from viewcriteria
1. Strip the formatting
2. Provide the actual value
1. e.g. via the oracle.jheadstart.model.QueryCondition
2. Override JhsApplicationModuleImpl.advancedSearch()
Store search criteria
• On login requery the latest search
• Extend JhsSearchBean
• Override advancedSearch()
– Serialize the criteria to file
– Use the userId as name for the file
• Constructor
– Retrieve the criteria from file
• http://groups.google.com/group/adfmethodology