Upload
jered
View
34
Download
0
Embed Size (px)
DESCRIPTION
ADF Development Live from the trenches. Aino Andriessen AMIS. Aim. Share our experience with ADF development Better ADF development Prevent problems Better maintainance Better applications. JDeveloper 10.1.3.3 ADF 10.1.3.41.57 JHS 10.1.23.2.51. Software studio Project Organization - PowerPoint PPT Presentation
Citation preview
1
ADF Development Live from the trenches
Aino Andriessen
AMIS
2
Aim
Share our experience with ADF development
Better ADF development Prevent problems Better maintainance Better applications
3
JDeveloper 10.1.3.3
ADF 10.1.3.41.57
JHS 10.1.23.2.51
4
Software studio Project Organization Development
5
Software studio
SCM Continuous integration Incident management OTAP Quality measurement Testing Reporting Artifact repository
6
SCM
e.g. Subversion JDev 10.1.3.3 : 1.4.x; before it's 1.3
JDeveloper extension(s) Only 1 scm per JDev installation Limited functionality, but mostly enough Necessary for correct refactoring of BC's ! beware of delete and (re)create in 1 'update-commit cycle' When updating outside JDev, close JDev or make sure that
all changes have been saved
Built-in JDev history very helpful for re-applying post-generation 'activate' manually the scm connection to include scm
history
7
8
Continuous Integration
build test deploy
Scripted maven / ant
Automated Continuum
Dedicated environment
9
Unit-testing
↑ code control
↑ code quality
↓ development time
TDD improves the testibility of your code Unit-testing increases your ADF skills Easy debugging of BC's Automated execution at continuous
integration
10
BC testing
BC tester JDeveloper JUnit extensions URL based application module configuration 'unit-test framework'
application module configuration authentication generic functions
import oracle.jbo.client.Configuration;...public void setUp() { _am = Configuration.createRootApplicationModule ("nl.amis.demo.odtug.model.services.HRService" ,"HRServiceLocalURL");}public void tearDown () { Configuration.releaseRootApplicationModule(_am, true);}
11
What to test
Synchronicity of BC with database Basic test for all VO's get<AM>().get<VO>().executeQuery()
VO instance in AM Data Custom interface methods Entity validators Custom methods on ADF objects Non-ADF java classes ...
12
demo
13
Software studio Project Organization Development
14
Application organization
common General code, Baseclasses
database Database code
ear Build and deployment
functional-tests JMeter and other tests
model ADF BC's
model2 ADF BC's
viewcontroller UI
lib 'External' libraries
15
Test projects
16
Project naming
Use comprehensive names for your project. The name will normally also be used for the
deliverables:• model.jar or viewcontroller.jar is not very informative
but it is good practice to include them in the name
17
Project merge
It's quite easy to merge BC projects Copy / paste BC's Add configurations to bc4j.xcfg Modify bc4j.xcfg - jbo.project option recompile
18
Project organization
Organize your BC's in directories Separate the usage of ViewObjects
(VO) in separate Application Modules (AM)
Bundle read-only reference VO's in a nested AM
Use Custom baseclasses Extend AM baseclass from Jhs
baseclass
19
Naming conventions
Good names make the project much more comprehensible and maintainable
Stick to your conventions Apply them asap
or you must perform refactoring later on
Do not use the default sequencenumber suffix that JDeveloper often generates. e.g. EmployeesVw1 This will make your life miserable in no time.
20
Examples
Entities singular e.g. Employee
Viewobjects plural suffix e.g. EmployeesVw read-only reference (dropdown, lov)
• e.g. EmployeesListVw indicate the usage
• EmployeesByNameVw Accessors of associations and viewlinks
use plural for list and singular for 1 object Attributes
Start with capital Lkp prefix for reference entity and Lkp<entity> for referenced attributes Trnsnt prefix or suffix for non-database bound attributes
VO instance names NO number suffix comprehensible names, especially within hierarchies
• e.g. EmployeesByDepartmentVw or JobsListVw
21
Refactoring
Don't be afraid of refactoring try to be strongly typed use unittests for verification spend some time getting familiar
Refactor with scm enabled JDeveloper does a rather good job... but misses a
few spots rename VO does not update the <am>.get<VO>() method
• compile error, manual correction of method in Impl rename an entity may not correctly update the association
• manual correction in entity XML file Rename VO
The 'api' (AM instance) is not refactored. Iterator bindings remain valid Attribute bindings in adf faces pages are not updated
22
JHeadstart refactoring
BC refactoring (AM instance, attribute) only requires a 'refresh' (and regenerate).
Custom code (EL expressions, binding) must be done manually Rename a group :
Obsolete files :• <oldGroupName>.jspx • <oldGroupName>Table.jspx (in case your group has layout style
‘table-form’.) • <oldGroupName>.pageDef.xml • <oldGroupName>-beans.xml
Obsolete entries :• DataBindings.cpx• web.xml (param-name javax.faces.CONFIG_FILES) • db resourcebundles
Generate and wait with saving to identify the old, not modified, files.
Note that custom templates may contain hard-coded references to the old entries
23
Software studio Project Organization Development
24
Development skills
Diverse set of skills Standard Java and Enterprise Java Database ADF
• JSF pagelifecycle HTML / Javascript / css JHeadstart Application Server Administration SOA Architecture / design Security Object Orientation ...
Know your tool / framework! When using JHeadstart, make sure you know how to
make an ADF application
25
General
Use a 'reference Emp project' for research and trials JHeadstart solutions Download SRDemo project RTFM Oracle forums http://radio.weblogs.com/0118231/stories/
2004/09/23/notYetDocumentedAdfSampleApplications.html
Do scm project branching to test changes with major impact
http://www.oracle.com/technology/products/jdev/htdocs/partners/addins/exchange/jsf/doc/tagdoc/core/imageIndex.html
26
Logging
Log4J and Apache Commons
Logging log4j is included with jhs
runtime Do NOT include in deliverable
log4j.properties file on classpath source path
private static Log sLog = LogFactory.getLog(HRServiceImpl.class);
27
Debugging
Project properties -> custom run configuration -Djbo.debugoutput=console (file) -Djbo.logging.show.function=true
http://www.oracle.com/technology/products/jdev/tips/muench/debugger/index.html
http://www.oracle.com/webapps/online-help/jdeveloper/10.1.3/state/content/navId.4/navSetId._/vtAnchor.editing/vtTopicFile.adfdevguide%7Cweb_testdebug~htm/
28
Debugging
29
Application Module / Service
Create impl class direct access to VO's
Custom interface methods parameters must be serializable return type must be serializable throw JboException
Exceptions are caught in the binding framework and cannot be catched in managed bean.
try { sendEmailBinding.execute();} catch (JboException e) { // never ever catched}
if (ADFJSFUtils.hasErrors(bindings) { // ...}
30
AM Configuration
Datasource for production URL for testing
public static void main(String[] args) { launchTester("nl.amis.demo.odtug.model.services","HRServiceLocalURL");}
Use exactly the same DB connection
Configure the datasource manually Do not use the generated
ones Normally do not include
them with deployment
31
Entity Validation
! No value change : no attribute validation but entity validation is performed
32
Entity validation
Testing can be quite easy with unit-tests
/** * Test that the salary must be lower than 10000 */public void testSalaryRule () { HRServiceImpl service = getHRService(); EmployeeImpl emp = (EmployeeImpl) createEntity ("nl.amis.demo.odtug.model.entities.Employee"); try { emp.setSalary(new oracle.jbo.domain.Number (11111)); fail(); } catch (Exception e) { assertTrue(true); } emp.setSalary(new oracle.jbo.domain.Number (9999)); emp.setSalary(new oracle.jbo.domain.Number (-1)); emp.setSalary(null);}
33
Views with Instead-of triggers
public boolean isUseReturningClause() { return false;}
OracleSQLBuilderImpl.doEntityDML(401) BEGIN UPDATE EMPLOYEES Employee SET SALARY=? WHERE EMPLOYEE_ID=?;SELECT PHONE_NUMBER INTO ? FROM EMPLOYEES WHERE EMPLOYEE_ID=?; END;
OracleSQLBuilderImpl.doEntityDML(401)BEGIN UPDATE EMPLOYEES Employee SET SALARY=? WHERE EMPLOYEE_ID=? RETURNING PHONE_NUMBER INTO ?; END;
Note, that you cannot use this to refresh the DB generated primary key.
Refresh after insert / update DB does not allow returning clause
34
Sequence based PK
Sequence based Override entity create(AttributeList) method :
DbSequence negative temp id that is NOT submitted to the database Initially easier to use, but the consequences might be more
complex negative temp id, that is not always updated on details :
• override entity postChanges() refactoring to sequence based requires absence of
<VO>Impl• scm issues may arise when delete and create in one
updatecycle
protected void create(AttributeList attributeList) { super.create(attributeList); SequenceImpl seq = new SequenceImpl("EMP_SEQ", getDBTransaction()); setEmployeeId(seq.getSequenceNumber());}
35
Constants and literals
Minimize the use of literals in EL-expressions Use contants
as managed bean property with 'getter'
IsXXX transient attribute on VO
36
SetActionListener
The setActionListener tag is a declarative way to allow an action source to set a value before navigation
From and to must be both EL-expressions even constants, e.g. : from="#{'HelloWorld'}" oracle.jbo.domain.Number cannot be set as constant
Note execution sequence : actionListener attribute setActionListener action
Can also used to set methodbindings
<af:setActionListener
from="#{bindings.EmployeesVwEmail.inputValue}"
to="#{emailBean.emailTo}"/>
37
Manipulating the model using binding
OperationBinding commitBinding = ADFUtils.getBindingContainer().getOperationBinding("Commit");
commitBinding.execute();
FacesContext ctx = FacesContext.getCurrentInstance();
Application app = ctx.getApplication();
ValueBinding bind = app.createValueBinding("#{bindings}");
BindingContainer bindingContainer = (BindingContainer) bind.getValue(ctx);
OperationBinding sendEmailBinding = bindingContainer.getOperationBinding("sendEmail");
sendEmailBinding.execute();
OperationBinding sendEmailBinding = bindings.getOperationBinding("sendEmail");
sendEmailBinding.execute();
<managed-property>
<property-name>bindings</property-name>
<value>#{bindings}</value>
</managed-property>
38
JHeadstart
ADF Faces generation Different types of pages I18N Authorization Search Lov FlexItems ... velocity based templating to customize
generation
39
General
Organize pagedefs, resourcebundles, beans, regions
Utils : oracle.jheadstart.controller.jsf.util.JsfUtils
Jhs PhaseListeners in JhsCommon-beans.xml When using multiple faces-config
!! An extra ADFPhaseListener appears in faces-config.xml after adding custom bindings. Multiple PhaseListeners may lead to unpredictable behaviour.
40
Postgeneration
Velocity templates Pagedef generation is not templated
but uses JDev mechanism Documention of pagedef postgen in a
<pafegdef>.postgen.txt file Disable 'clear pagedef before generation' Note, disable 'Override' does not add new bindings
41
Templates
Use scm tag / copy to create a copy template to keep the link with the original template in case of updates
Include custom templates : #parse("cxs/misc/include/cxsNlsEntries.vm")
If necessary, use your own .jtp
# Custom template
QUICK_SEARCH_TEXT_INPUT=odtug/item/find/googleSearchTextInput.vm
# no dropdown needed
QUICK_SEARCH_DROP_DOWN_REGION=default/common/empty.vm
# removed other entries
42
Templates and nls
create nls entries : (http://technology.amis.nl/blog/?p=1405 )
Include custom nls-entries in comment
${JHS.nls("<some text (only used in combination with standard jhs text)>" , "<nls_key>" , "<nls_text>" )}
<!-- NLS Entries ${JHS.nls("Global Help button label", "GLOBAL_HELP_LABEL", "Help")} -->
43
The key to success
Organization Knowledge Communication Fun