langkuik

35
Langkuik: An experiment in declarative web application framework By: Azrul MADISA May 2016

Upload: azrul-madisa

Post on 17-Jan-2017

126 views

Category:

Internet


0 download

TRANSCRIPT

Page 1: Langkuik

Langkuik: An experiment in declarative web application framework

By: Azrul MADISAMay 2016

Page 2: Langkuik

About me…• VP - Data Enterprise Architecture @

Maybank

– In charge of big and fast data across the Maybank Group

• Love to read

• Black belt in aikido

• Hack stuff once in a while

Page 3: Langkuik

Langkuik: What is it?

• Experiment started back in 2011

• I noticed that I’ve been coding the same web app over and over again

– With different data models, different clients, different flows but the same features

Page 4: Langkuik

Langkuik: What is it?

• Experiment started back in 2011

• I noticed that I’ve been coding the same web app over and over again

– With different data models, different clients, different flows but the same features

– Is there a way to code these features once and declaratively change the data model, look and feel and workflow?

• Scaffolding => too basic (hence the name)

• CRUD => mostly quick and dirty (emphasis on dirty)

• MDM => no flow

– So I code my own => Langkuik

Page 5: Langkuik

Not another web framework!!

Page 6: Langkuik

Not another web framework!!

2002 just call, they want their hype back

Page 7: Langkuik

Why?

• You should write your own web framework even if no one uses it, not even you

– You WILL learn A LOT

• Additionally…

– We reuse declarative underlying framework

• Hibernate annotations

• Spring Security XML

Page 8: Langkuik

Langkuik: Under the hood

Hibernate Search + Lucene

[Search]

Spring Security [Access control]

Hibernate [Persistence]

Vaadin

[Web GUI]

• Minimise re-inventing the wheel

• Make these underlying engine accessible

Page 9: Langkuik

Root and Aggregate

• Design pattern from DDD book

• Helps manage complexity

• The gist:

– Group classes into aggregate

– Aggregate has one root

– Root serves as entry/exit point for all other classes in the aggregate

– Each aggregate has its own lifecycle

Page 10: Langkuik

Root and Aggregate

– Root serves as entry/exit point for all other classes in the aggregate

• Non root -> Root

• Root -> Another root

• Root -> Non root in its own aggregate

• Non root -> another non root

Page 11: Langkuik

Root and Aggregate: Example

Item

Line Item

Customer

Shipping address

Page 12: Langkuik

Root and Aggregate: Example

<<Root>>Item

Line Item

<<Root>>Customer

Shipping address

Page 13: Langkuik

Entity

@Entity

@Indexed

@Table(schema = "BANK1")

@WebEntity(name="collateral", isRoot=true)

public class Collateral implements Serializable {

}

Page 14: Langkuik

Create

Page 15: Langkuik

View

Page 16: Langkuik

Relationship

@Entity

@Table(schema = "BANK1")

@Indexed

@WebEntity(name = "application", isRoot = true)

public class Application implements Serializable {

@OneToMany(fetch = FetchType.LAZY)

@JoinColumn()

@WebField(name = "applicants", rank = 6)

private Collection<Applicant> applicantsCollection;

}

@Entity

@Table(schema = "BANK1")

@Indexed

@WebEntity(name="applicant")

public class Applicant implements Serializable {

}

<<Root>>Application

Applicant*

Page 17: Langkuik

Create

Page 18: Langkuik

View

Page 19: Langkuik

Object graph as workflow

Application

Applicant*

Collateral

Address

*

1

*

Page 20: Langkuik

Object graph as workflow

Application

Applicant*

Collateral

Address

*

1

*

Page 21: Langkuik

Object graph as workflow

Application

Applicant*

Collateral

Address

*

1

*

Page 22: Langkuik

Data type to web component

String =>

Date =>

Page 23: Langkuik

Data type to web component

Collection<Attachment> => =>

Page 24: Langkuik

Choices

@WebField(name="marital status", group="Personal

information", rank=6, choices={

@Choice(display="Single",textValue="S"),

@Choice(display="Married",textValue="M"),

@Choice(display="Divorced",textValue="D"),

@Choice(display="Unknown",textValue="U")

})

@Column(name = "MARITAL_STATUS")

private String maritalStatus;

Page 25: Langkuik

Active Choices

Page 26: Langkuik

Active Choices

@ActiveChoiceHierarchy({"Country","State","Town"})

public enum CountryState implements

ActiveChoiceEnum<CountryState>{

Malaysia(null),

Perak(Malaysia),

Ipoh(Perak),

Taiping(Perak),

Selangor(Malaysia),

ShahAlam(Selangor),

Cyberjaya(Selangor),

Bangi(Selangor),

Johor(Malaysia),

Kedah(Malaysia),

Penang(Malaysia),

US(null),

Alabama(US),

Alaska(US),

Massachusetts(US),;

}

@WebField(name="country“,

activeChoice=

@ActiveChoice(

enumTree=CountryState.class,

hierarchy="Country")

)

@Column(name = "COUNTRY")

private String country;

@WebField(name="state", rank=4, displayInTable=true,

activeChoice=

@ActiveChoice(

enumTree=CountryState.class,

hierarchy="State")

)

@Column(name = "STATE")

private String state;

Page 27: Langkuik

Search

@Indexed

public class Address implements Serializable {

}

Page 28: Langkuik

Audit trail

Page 29: Langkuik

Audit trail

public class Application implements Serializable {

@Id

@Audited

private Long applicationId;

@Audited

private Date acceptedDate;

@Audited

private String accountNumber;

}

Page 30: Langkuik

Entity access right

@WebEntity(name="address",

userMap = {

@EntityUserMap(

role = "ROLE_LOAN_OFFICER",

right = EntityOperation.CREATE_UPDATE

),

@EntityUserMap(

role = "ROLE_UNDERWRITER",

right = EntityOperation.VIEW

)

}

)

public class Address implements Serializable {

}

User role

What the role can do to this object

User role

What the role can do to this object

Page 31: Langkuik

Field access right

@WebEntity(name=“application” …)

public class Application implements Serializable {

@WebField(

name = "account number",

userMap = {

@FieldUserMap(

role = "ROLE_UNDERWRITER",

right = FieldOperation.VIEW)

})

private String accountNumber;

}

User role

What the role can do this field

Page 32: Langkuik

Required

@WebEntity(name=“application” …)

public class Application implements Serializable {

@WebField(

name = "account number",

required=true)

private String accountNumber;

}

Page 33: Langkuik

What’s next

• Automated test framework

• Work queue

• Proper workflow

• Asynchronous actions

• Search in between dates

• Hide some of the annotations with sane defaults

Page 34: Langkuik

Other related projects

• OpenXava [http://www.openxava.org/web/guest]

• Krank [https://code.google.com/archive/p/krank/]

Page 35: Langkuik

Getting started

• Langkuik Github site

– Maven based

– https://github.com/azrulhasni/Langkuik

• Start with a ‘hello world’ project

– Todo List application

– Maven based

– Basic features

– https://github.com/azrulhasni/MyTodoList