44
1 ADF Development Live from the trenches Aino Andriessen AMIS

ADF Development Live from the trenches

  • 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

Page 1: ADF Development  Live from the trenches

1

ADF Development Live from the trenches

Aino Andriessen

AMIS

Page 2: ADF Development  Live from the trenches

2

Aim

Share our experience with ADF development

Better ADF development Prevent problems Better maintainance Better applications

Page 3: ADF Development  Live from the trenches

3

JDeveloper 10.1.3.3

ADF 10.1.3.41.57

JHS 10.1.23.2.51

Page 4: ADF Development  Live from the trenches

4

Software studio Project Organization Development

Page 5: ADF Development  Live from the trenches

5

Software studio

SCM Continuous integration Incident management OTAP Quality measurement Testing Reporting Artifact repository

Page 6: ADF Development  Live from the trenches

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

Page 7: ADF Development  Live from the trenches

7

Page 8: ADF Development  Live from the trenches

8

Continuous Integration

build test deploy

Scripted maven / ant

Automated Continuum

Dedicated environment

Page 9: ADF Development  Live from the trenches

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

Page 10: ADF Development  Live from the trenches

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);}

Page 11: ADF Development  Live from the trenches

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 ...

Page 12: ADF Development  Live from the trenches

12

demo

Page 13: ADF Development  Live from the trenches

13

Software studio Project Organization Development

Page 14: ADF Development  Live from the trenches

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

Page 15: ADF Development  Live from the trenches

15

Test projects

Page 16: ADF Development  Live from the trenches

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

Page 17: ADF Development  Live from the trenches

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

Page 18: ADF Development  Live from the trenches

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

Page 19: ADF Development  Live from the trenches

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.

Page 20: ADF Development  Live from the trenches

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

Page 21: ADF Development  Live from the trenches

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

Page 22: ADF Development  Live from the trenches

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

Page 23: ADF Development  Live from the trenches

23

Software studio Project Organization Development

Page 24: ADF Development  Live from the trenches

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

Page 25: ADF Development  Live from the trenches

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

Page 26: ADF Development  Live from the trenches

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);

Page 27: ADF Development  Live from the trenches

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/

Page 28: ADF Development  Live from the trenches

28

Debugging

Page 29: ADF Development  Live from the trenches

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) { // ...}

Page 30: ADF Development  Live from the trenches

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

Page 31: ADF Development  Live from the trenches

31

Entity Validation

! No value change : no attribute validation but entity validation is performed

Page 32: ADF Development  Live from the trenches

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);}

Page 33: ADF Development  Live from the trenches

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

Page 34: ADF Development  Live from the trenches

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());}

Page 35: ADF Development  Live from the trenches

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

Page 36: ADF Development  Live from the trenches

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}"/>

Page 37: ADF Development  Live from the trenches

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>

Page 38: ADF Development  Live from the trenches

38

JHeadstart

ADF Faces generation Different types of pages I18N Authorization Search Lov FlexItems ... velocity based templating to customize

generation

Page 39: ADF Development  Live from the trenches

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.

Page 40: ADF Development  Live from the trenches

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

Page 41: ADF Development  Live from the trenches

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

Page 42: ADF Development  Live from the trenches

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")} -->

Page 43: ADF Development  Live from the trenches

43

The key to success

Organization Knowledge Communication Fun

Page 44: ADF Development  Live from the trenches

44

[email protected]

http://www.amis.nl

http://technology.amis.nl/blog