Anda di halaman 1dari 346

christian@dalager.com :: simon@jorsal.net :: eske@allsorts.

dk
Abstract

This report aims at providing software developers with an understanding of the as-
pect oriented paradigm as used in the JBoss 4 application server.

The aspect oriented framework in JBoss is presented in two stages: The first is how
to use the framework, the second how it has been implemented. A case study is
used to show how to design applications and aspect oriented services. A thorough
presentation of the implementation details of the framework is given and reflections
on the design choices are made.

We conclude that the complexity and flexibility is the strength and the weakness of
the framework. The cost of the flexibility is a major cognitive burden on the developer.
We further reflect on the communication of our findings.
Creative Commons Deed

Creative Commons

Attribution-ShareAlike 1.0

You are free:

to copy, distribute, display, and perform the work


to make derivative works
to make commercial use of the work

Under the following conditions:

Attribution. You must give the original author credit.

Share Alike. If you alter, transform, or build upon this work, you may
distribute the resulting work only under a license identical to this one.

For any reuse or distribution, you must make clear to others the license
terms of this work.
Any of these conditions can be waived if you get permission from the
author.

Your fair use and other rights are in no way affected by the above.

This is a human-readable summary of the Legal Code (the full license).

Disclaimer

http://creativecommons.org/licenses/by-sa/1.0/ (1 of 2) [01-03-2004 23:01:42]


Contents

1 Introduction 1

1.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1

1.2 What are the Goals of this Report? . . . . . . . . . . . . . . . . . . . . . . 2

1.3 Method and Approach . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2

1.3.1 Understanding the AOP Framework . . . . . . . . . . . . . . . . . 2

1.3.2 Communicating the AOP Framework . . . . . . . . . . . . . . . . 3

1.4 Who is This Report For? . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4

1.4.1 Prerequisites . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4

1.5 Short Thesis Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5

I A First Look at JBoss, Aspect Oriented Programming and our


Case Study 7

2 JBoss 9

2.1 The JBoss Server . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9

2.2 MBeans and the JBoss Web-console . . . . . . . . . . . . . . . . . . . . . 10

3 Aspect Oriented Programming 11

3.1 Crosscutting Concerns . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

3.2 Traditional Handling of Crosscutting Concerns . . . . . . . . . . . . . . . 12

3.2.1 Handling Crosscutting Concerns with Aspect Oriented Program-


ming . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

3.3 What is Aspect Oriented Programming . . . . . . . . . . . . . . . . . . . 14

I
CONTENTS II

3.4 AOP Implementations for Java a Short Overview . . . . . . . . . . . . 15

3.5 From Aspect Components to AOP-services . . . . . . . . . . . . . . . . . . 16

3.6 Some Perspectives . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17

4 Inventory Management Case Introduction 19

4.1 What Application did we Create and Why? . . . . . . . . . . . . . . . . . 19

4.2 The Core Application a Technical Walkthrough . . . . . . . . . . . . . . 20

4.2.1 The jboss.thesis.inventory.model Package . . . . . . . . . . . . 21

4.2.2 The jboss.thesis.inventory.controller Package . . . . . . . . . 22

4.3 Client Application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24

4.4 Inventory Management System Setup . . . . . . . . . . . . . . . . . . . . 26

II Creating Your Own AOP-Applications and AOP-Services 27

5 Using the JBoss AOP Framework 29

5.1 The Pointcut Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29

5.1.1 Pointcuts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30

5.1.2 Interceptors and Interceptor Chains . . . . . . . . . . . . . . . . . 32

5.1.3 Dynamic Interceptors . . . . . . . . . . . . . . . . . . . . . . . . . . 34

5.1.4 Metadata . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36

5.1.5 Introductions and Mixin Classes . . . . . . . . . . . . . . . . . . . 37

5.2 Writing an AOP-service . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39

5.3 Deploying Applications and AOP-services . . . . . . . . . . . . . . . . . . 40

5.3.1 Accessing AOP-applications and AOP-services . . . . . . . . . . . 41

5.3.2 Deployment Units . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42

5.4 Built-in services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43

6 Inventory Management Case AOP-Services 45

6.1 Handling of Minimum Stock Levels . . . . . . . . . . . . . . . . . . . . . . 46

6.2 Watch on a Product . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49


CONTENTS III

6.3 Logging of New Orders and Reservations . . . . . . . . . . . . . . . . . . 51

6.4 Accessing the AOP-Services . . . . . . . . . . . . . . . . . . . . . . . . . . 52

III JBoss AOP Framework Internals 53

7 Basic JBoss Functionality 55

7.1 Main Deployment Sequence . . . . . . . . . . . . . . . . . . . . . . . . . . 55

7.2 Scanning for Services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57

7.3 Bytecode Manipulation and Javassist . . . . . . . . . . . . . . . . . . . . 57

7.4 Classloading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58

8 An Example AOP-service 59

8.1 A model of Interaction Between Calling and Called Class . . . . . . . . . 59

8.2 The Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60

8.2.1 ProductImpl . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60

8.2.2 ClassUsingProduct . . . . . . . . . . . . . . . . . . . . . . . . . . . 61

8.2.3 LoggingInterceptor . . . . . . . . . . . . . . . . . . . . . . . . . . . 62

8.2.4 AOP Deployment Descriptor . . . . . . . . . . . . . . . . . . . . . . 62

8.3 From Deployment to Instance Creation at a Glance . . . . . . . . . . . . 63

9 Deployment of AOP-applications 65

9.1 Presentation of the Deployment Process . . . . . . . . . . . . . . . . . . . 65

9.2 Handling .aop Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65

9.3 Tables in the AspectManager . . . . . . . . . . . . . . . . . . . . . . . . . . 66

9.4 Deployment of the Example . . . . . . . . . . . . . . . . . . . . . . . . . . 68

10 Instrumentation of Classes 69

10.1 An Overview of the Instrumentation Process . . . . . . . . . . . . . . . . 69

10.2 Creating Advisors in ProductImpl . . . . . . . . . . . . . . . . . . . . . . . 70

10.2.1 The ClassAdvisor . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71


CONTENTS IV

10.2.2 The ClassInstanceAdvisor . . . . . . . . . . . . . . . . . . . . . . . 71

10.2.3 Initializing the ClassAdvisor . . . . . . . . . . . . . . . . . . . . . 71

10.3 Moving Information from the AspectManager to the Advisor . . . . . . . . 72

10.4 Adding Generic Delegation Methods . . . . . . . . . . . . . . . . . . . . . 73

10.5 Making Changes to Accomodate Delegation to the Advisor . . . . . . . . 76

10.5.1 Method Changes . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76

10.5.2 Field Changes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77

10.5.3 Constructor Changes . . . . . . . . . . . . . . . . . . . . . . . . . . 77

10.6 Making Changes to Handle Mixin Classes . . . . . . . . . . . . . . . . . . 78

10.6.1 Handling Introduced Interfaces With an Interceptor . . . . . . . . 79

10.7 Making Changes to ClassUsingProduct . . . . . . . . . . . . . . . . . . . . 79

10.7.1 Changes made to Handle Field Access . . . . . . . . . . . . . . . . 80

10.7.2 Changes made to Handle Constructor Calls . . . . . . . . . . . . . 80

10.7.3 Changes Made to Handle Caller-pointcuts . . . . . . . . . . . . . . 81

10.8 Non-instrumentable Classes . . . . . . . . . . . . . . . . . . . . . . . . . . 82

10.9 Finishing the Instrumentation Process . . . . . . . . . . . . . . . . . . . . 83

11 Initializing an Instrumented Class 85

11.1 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85

11.2 Method Interceptors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86

11.3 Field Interceptors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86

11.4 Constructor Interceptors . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87

11.5 Caller Interceptors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87

12 Using Instrumented Classes 89

12.1 Instantiating an Instrumented Class . . . . . . . . . . . . . . . . . . . . . 89

12.2 Accessing Fields in an Instrumented Class . . . . . . . . . . . . . . . . . 91

12.3 Intercepting Methods with a Method-pointcut . . . . . . . . . . . . . . . 91

12.4 Intercepting Methods with a Caller-pointcut . . . . . . . . . . . . . . . . 93


CONTENTS V

IV Critique, Conclusions and Evaluation 95

13 Reflections and Conclusion on JBoss 4 97

13.1 Separating AOP-services from AOP-applications . . . . . . . . . . . . . . 98

13.2 Using the Supplied AOP Remoting Service . . . . . . . . . . . . . . . . . 99

13.2.1 AOP Framework Error . . . . . . . . . . . . . . . . . . . . . . . . . 99

13.2.2 Difficult to Use Remoting . . . . . . . . . . . . . . . . . . . . . . . 99

13.2.3 Default Constructors are a Must . . . . . . . . . . . . . . . . . . . 100

13.2.4 Equal Methods in Remote Objects . . . . . . . . . . . . . . . . . . 100

13.3 Usability Issues The Cognitive Burden . . . . . . . . . . . . . . . . . . 101

13.3.1 Too Many Combinations . . . . . . . . . . . . . . . . . . . . . . . . 101

13.3.2 Semantic Inconsistencies . . . . . . . . . . . . . . . . . . . . . . . . 102

13.3.3 An Abundance of Features . . . . . . . . . . . . . . . . . . . . . . . 103

13.4 Performance of JBoss AOP . . . . . . . . . . . . . . . . . . . . . . . . . . . 103

13.4.1 Test Results . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104

13.4.2 Filters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106

13.5 Improvement Suggestions . . . . . . . . . . . . . . . . . . . . . . . . . . . 107

13.5.1 Support for Multiple Mixin Classes . . . . . . . . . . . . . . . . . . 107

13.5.2 Pointcuts on Inherited Methods . . . . . . . . . . . . . . . . . . . . 107

13.5.3 Dumping Modified Classes . . . . . . . . . . . . . . . . . . . . . . . 108

13.6 Conclusions on JBoss 4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109

14 Evaluation of the Process 111

14.1 Communicating the AOP Framework . . . . . . . . . . . . . . . . . . . . 111

14.1.1 Example Programs in the Report . . . . . . . . . . . . . . . . . . . 111

14.2 The Process Working on the Thesis . . . . . . . . . . . . . . . . . . . . . 112

14.2.1 Too Much Time Spent on AOP Remoting . . . . . . . . . . . . . . 112

14.2.2 Graphical Client not Really Needed . . . . . . . . . . . . . . . . . 113

14.2.3 Understanding JBoss Source Code . . . . . . . . . . . . . . . . . . 113


CONTENTS VI

14.2.4 If We had All the Time in the World . . . . . . . . . . . . . . . . . 113

Bibliography 114
Appendix Contents

I Short Introductions to Technologies Mentioned in the Report 1

A Short Intro to Technologies 2

A.1 What is J2EE and EJBs? . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2

A.2 What is JMX? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

A.3 What are MBeans? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

A.4 JBoss as an MBean Server . . . . . . . . . . . . . . . . . . . . . . . . . . . 4

II Overview of Classes Used in JBoss AOP 5

B Support Classes for Instrumented Classes 6

B.1 Advisor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6

B.2 ClassAdvisor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6

B.3 InstanceAdvisor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6

B.4 ClassInstanceAdvisor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7

B.5 InstanceAdvised . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7

B.6 Advised . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7

C Classes for Deployment and Instrumentation 8

C.1 AspectManager . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

C.2 AspectXmlLoader . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

C.3 DeploymentInfo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9

C.4 Instrumentor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9

I
CONTENTS II

D Pointcut Classes 10

D.1 Advisable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10

D.2 InterceptorPointcut . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10

D.3 ConstructorPointcut . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10

D.4 FieldPointcut . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

D.5 MethodPointcut . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

D.6 CallerPointcut . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

D.7 IntroductionPointcut . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

E Interceptor Classes 12

E.1 Interceptor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12

E.2 InterceptorFactory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12

E.3 ConstructorTailInterceptor . . . . . . . . . . . . . . . . . . . . . . . . . . 13

E.4 FieldTailInterceptor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

E.5 MethodTailInterceptor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

E.6 CallerTailInterceptor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

F Invocation Classes 14

F.1 Invocation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14

F.2 ConstructorInvocation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14

F.3 FieldInvocation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14

F.4 FieldReadInvocation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15

F.5 FieldWriteInvocation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15

F.6 MethodInvocation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15

F.7 CallerInvocation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15

F.8 InvocationType . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15

G Javassist Classes 16

G.1 ClassPool . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

G.2 CtClass . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
CONTENTS III

G.3 CtConstructor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

G.4 CtField . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17

G.5 CtMethod . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17

III Diagrams 19

H Deployment Diagrams 20

H.1 MBean Deployment Diagrams . . . . . . . . . . . . . . . . . . . . . . . . . 21

H.2 Scanning for Services and Applications . . . . . . . . . . . . . . . . . . . 23

H.3 AOP Deployment Process . . . . . . . . . . . . . . . . . . . . . . . . . . . 24

I Instrumentation Process Diagrams 26

I.1 Instrumentation Sequence Diagrams . . . . . . . . . . . . . . . . . . . . . 26

I.2 Instrumentation Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34

J Diagrams of Instrumented Class Use 35

J.1 Instance Creation, Field Access and Method Invocation Sequence Dia-
grams . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35

J.2 Class Use Class Diagrams . . . . . . . . . . . . . . . . . . . . . . . . . . . 39

IV Simplified Inventory Management Example 41

K Classes used in Part III 42

K.1 Original ProductImpl.java . . . . . . . . . . . . . . . . . . . . . . . . . . 42

K.2 Instrumented ProductImpl.java . . . . . . . . . . . . . . . . . . . . . . . . 43

K.3 Original ClassUsingProduct.java . . . . . . . . . . . . . . . . . . . . . . 46

K.4 Instrumented ClassUsingProduct.java . . . . . . . . . . . . . . . . . . . . 47

K.5 AOP Deployment Descriptor . . . . . . . . . . . . . . . . . . . . . . . . . . 48


CONTENTS IV

V Source Code 49

L Deployment Descriptors 50

L.1 AOP Deployment Descripter . . . . . . . . . . . . . . . . . . . . . . . . . . 50

L.2 JBoss Service Deployment Descriptor . . . . . . . . . . . . . . . . . . . . 53

M Inventory Managment AOP-application 54

M.1 Customer.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54

M.2 IdUtil.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56

M.3 Order.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58

M.4 OrderList.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62

M.5 Product.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64

M.6 ProductImpl.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66

M.7 ProductComposite.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69

M.8 Reservation.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72

M.9 Type.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74

N Inventory Management Application Controller 76

N.1 CreationException.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76

N.2 InventoryController.java . . . . . . . . . . . . . . . . . . . . . . . . . . . 77

N.3 InventoryFactory.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81

N.4 NoSuchOrderException.java . . . . . . . . . . . . . . . . . . . . . . . . . . 85

N.5 RemoteUtil.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86

O Inventory Management AOP-services 88

O.1 DecrementReservationInterceptor.java . . . . . . . . . . . . . . . . . . . 88

O.2 IncrementReservationInterceptor.java . . . . . . . . . . . . . . . . . . . 90

O.3 MinimumStock.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92

O.4 MinimumStockInterceptor.java . . . . . . . . . . . . . . . . . . . . . . . . 93

O.5 ProductCompositeMixin.java . . . . . . . . . . . . . . . . . . . . . . . . . . 95
CONTENTS V

O.6 ProductConstructionInterceptor.java . . . . . . . . . . . . . . . . . . . . 98

O.7 ProductMixin.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101

O.8 ReservationCounter.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103

O.9 WatchListInterceptor.java . . . . . . . . . . . . . . . . . . . . . . . . . . 104

O.10 ModelConstructorLoggingInterceptor.java . . . . . . . . . . . . . . . . . 106

P Inventory Management MBeans 108

P.1 AOPService.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108

P.2 AOPServiceMBean.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112

P.3 InventoryService.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113

P.4 InventoryServiceMBean.java . . . . . . . . . . . . . . . . . . . . . . . . . . 120

Q The Graphical Client 121

Q.1 AddReservationButton.java . . . . . . . . . . . . . . . . . . . . . . . . . . 121

Q.2 ButtonCellRenderer.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122

Q.3 ColumnData.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123

Q.4 InventoryProxyClient.java . . . . . . . . . . . . . . . . . . . . . . . . . . 124

Q.5 JTableButtonListener.java . . . . . . . . . . . . . . . . . . . . . . . . . . 128

Q.6 MainWindow.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130

Q.7 OrderDetailButton.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134

Q.8 OrderFrame.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135

Q.9 OrderTableData.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141

Q.10 ProductTableData.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144

Q.11 ReservationButtonCellRenderer.java . . . . . . . . . . . . . . . . . . . . 147

Q.12 ReservationTableData.java . . . . . . . . . . . . . . . . . . . . . . . . . . 148

R AOP Performance Test 150

R.1 PerformanceTest.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150

R.2 PerformanceTestMBean.java . . . . . . . . . . . . . . . . . . . . . . . . . . 157

R.3 ConstructorTest.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158


CONTENTS VI

R.4 ConstructorTestUnadvised.java . . . . . . . . . . . . . . . . . . . . . . . . 159

R.5 PerformanceInterceptor.java . . . . . . . . . . . . . . . . . . . . . . . . . 160

R.6 SimplePerformanceClassA.java . . . . . . . . . . . . . . . . . . . . . . . . 161

R.7 SimplePerformanceClassB.java . . . . . . . . . . . . . . . . . . . . . . . . 163

R.8 SimpleUnadvisedPerformanceClassA.java . . . . . . . . . . . . . . . . . . 164

R.9 SimpleUnadvisedPerformanceClassB.java . . . . . . . . . . . . . . . . . . 165

R.10 Timer.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166

VI Source of Instrumented Classes 167

S Instrumented Decompiled Classes 168

S.1 Order.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168

S.2 ProductComposite.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 178

S.3 ProductImpl.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 189

S.4 Reservation.java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199

T Building and Deploying with Ant 204

T.1 Ant Properties File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 204

T.2 Ant Build File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 207


Chapter 1

Introduction

1.1 Introduction

The main concerns of our thesis are the inclusion and usage of an aspect oriented
programming (AOP) framework in the JBoss 4.0 Java 2 Enterprise Edition (J2EE)
application server.

J2EE is the largest middleware platform for Java. Despite its wide usage, the devel-
opment of J2EE applications is complex with a multitude of rules to bear in mind.
The JBoss Group has recognized the need for easier development of complex mid-
dleware systems that offer the same functionality as J2EE. By extending the JBoss
application server with an aspect oriented framework the company aims at providing
an alternative or at least a supplement to J2EE.

In the last few years there has been a lot of interest in aspect oriented programming
and its applications. AOP is about separating crosscutting concerns.

By using the JBoss AOP framework to create applications, the development cycle can
be split up thus making development easier.

Basically the usage of AOP in JBoss allows developers to create applications with-
out implementing transactions, security, persistence and other services needed on a
distributed platform such as J2EE. Furthermore the AOP framework offers devel-
opers a way of creating an entire application without having to think complicated
functionality that spans many objects into the application.

More complicated functionality can be dealt with and added at a later time through
the use of AOP techniques.

In this report we take a close look at the JBoss AOP framework, how it is used, what
problems it solves and how it is designed.

1
CHAPTER 1. INTRODUCTION 2

1.2 What are the Goals of this Report?

Our first goal is to fully understand the AOP framework in JBoss 4, how it has
been constructed, why it has been constructed this way, and what the benefits
and drawbacks of the framework are.

Our second goal is to provide documentation for the AOP framework so that
other developers can use it to get a deeper understanding of the framework and
learn how to use it.

1.3 Method and Approach

This master thesis is a communicative project that will provide a presentation and
critique of the JBoss AOP framework. This section describes what is needed in or-
der to reach the goals presented above. As the goals imply we approach the task of
communicating the framework on two levels:

1. How we as writers of this report can gain the required knowledge to communi-
cate the framework.

2. What is needed to communicate the framework to the readers of this report.

1.3.1 Understanding the AOP Framework

JBoss 4 and the AOP framework are still under development and at present suffer
from lack of documentation. In order to understand the framework in detail we have
done the following:

Conducted extensive analysis of the source code of the AOP framework.

Conducted experiments to learn and document the features provided by the


AOP framework.

Constructed a large example application in order to use the features in a more


realistic development situation.

The above has not only given us a comprehensive knowledge of the framework, it has
also provided us with an insight into how the framework should be communicated
based on our own experiences. Our experiences have taught us that examples are
the best way to understand complex systems such as the JBoss AOP framework.
CHAPTER 1. INTRODUCTION 3

1.3.2 Communicating the AOP Framework

We have broken the communication of the AOP framework into four parts. From
part one through part three we will lower the level of abstraction progressively as we
delve deeper into the details of the framework. In part four we again raise the level
of abstraction, as we offer critique and conclusions on the framework.

Part 1

This thesis does not presuppose extensive knowledge of JBoss or any knowledge of
aspect oriented programming. The first part will focus on providing an introduction
to the JBoss server as well as basic knowledge of the theoretical concepts of aspect
oriented programming.

Throughout the report we will use an inventory management system case study as
an example application. AOP will be applied to the application. We find a concrete
example the best way to communicate details of the AOP framework. In a worst
case scenario a concrete example is the only thing that connects the reader with the
subject communicated. The first part will also be dedicated to a presentation of our
example application.

Part 2

In the second part we will lower the level of abstraction by presenting the features of
the JBoss AOP framework and how these features are used.

The presentation of features will also serve as a basis for understanding the AOP
that we apply on top of our example application. In the second part we describe and
illustrate the AOP extensions of our case.

Part 3

To fully understand the consequences of using the different features of the framework
it is necessary to have insight into the framework implementation.

In part three we go into the lowest level of abstraction when we offer a detailed
description of the implementation of the JBoss AOP framework. A low-level walk-
through will help the reader understand the more subtle consequences in choices
made while developing applications. Furthermore it will provide the reader with the
foundation required to fully comprehend the critique we offer in part four.
CHAPTER 1. INTRODUCTION 4

Part 4

Firstly part four will offer critique and conclusions on the JBoss AOP framework and
our experiences with it. Secondly it will offer conclusions on our communication of
the framework.

1.4 Who is This Report For?

This report is for anyone interested in the JBoss AOP framework from a development
point of view.

Parts 1 and 2 should be sufficient for anyone interested in getting a head start to
using the JBoss 4 AOP framework. Part 3 is is for those who furthermore wants to
know about and learn from the design and implementation in detail.

Developers should benefit from this report by getting a thorough knowledge of using
the framework effectively. It should also be a supplementary help for decision makers
about to choose between different aspect oriented frameworks.

1.4.1 Prerequisites

To limit the scope and length of this report there are a number of prerequisites that
we expect readers to have knowledge about. These are:

Object oriented programming and design techniques in Java.

Design patterns.

Distributed systems, particularly knowledge on remote method invocation tech-


niques.

Basics knowledge of the Java Reflection API.

Basic knowledge of XML.

Basic knowledge of Java 2 Enterprise Edition (J2EE) and Enterprise Java Beans
(EJB). (A very short introduction to these is provided in appendix A.1)

Java Management Extensions (JMX). (A short introduction is provided in ap-


pendix A.2)
CHAPTER 1. INTRODUCTION 5

1.5 Short Thesis Overview

As explained in section 1.3 this report is divided into four parts each covering a num-
ber of subjects. Here we give a short ouline of the parts and the chapters they contain:
Part I Part II Part III Part IV
A First Look at JBoss, Aspect Creating Your Own AOP-
Critique, Conclusions and
Oriented Programming and our Applications and AOP- JBoss AOP Framework Internals
Evaluation
Case Study services

Aspect Inventory Inventory Basic An Instru- Initializing Using


Using theWhat is Deployment Reflections and
Oriented Management Management Jboss Example menta- an instru- instru- Critiqu Evaluation of
JBoss JBoss AOPAOP of AOP- Conclusions on
Program- Case Case Function- AOP- tion of mented mented e the Process
Framework applications JBoss AOP
ming Introduction AOP-Services ality Service classes class Classes

Part 1: A First Look at JBoss, Aspect Oriented Programming and our Case
Study.
A short introduction to the JBoss application server.
An introduction to aspect oriented programming.
The example application is introduced.

Part 2: Creating Your Own AOP-Applications and AOP-Services.


Firstly we show how AOP has been realized in the JBoss AOP framework, what
the different concepts and building blocks are, and how they are used for mak-
ing AOP-applications.
Secondly, by presenting how we have extended our case application with AOP-
services, we exemplify the above.

Part 3: JBoss AOP Framework Internals.


Looking underneath the surface of JBoss and the JBoss AOP framework, we
describe in detail how the framework is put together and what these implemen-
tation details mean to applications written for the framework.

Part 4: Critique, Conclusions and Evaluation.


The critique is an evaluation of the JBoss AOP framework. We look at perfor-
mance, possible improvements and how the framework has been to work with
overall.
Conclusive remarks presenting our findings in short form.
Part I

A First Look at JBoss, Aspect


Oriented Programming and our
Case Study

7
Part Overview

The chapters in this part will lay the foundation for understanding the rest of the
report.

The part consists of the following chapters:

Chapter 2 JBoss. A very short introduction to the JBoss server.

Chapter 3 Aspect Oriented Programming. A theoretical overview of what as-


pect oriented programming is. Aspect oriented terms and concepts are also
introduced in this chapter.

Chapter 4 Inventory Management Case Introduction. The example applica-


tion used throughout the report is introduced in this chapter. It is a technical
view of the basic part of the example application.

8
Chapter 2

JBoss

This short chapter will provide a short introduction to the JBoss application server
and the features for managing the server and its deployed applications.

2.1 The JBoss Server

The JBoss application server (currently version 3.x) is widely regarded as a J2EE
application server, even though it has not been certified as such. With the next re-
lease of the server JBoss 4 the server will be certified by Sun Microsystems as
a J2EE 1.4 application server. JBoss is open source and licensed under the GNU
Lesser General Public License (LGPL).

With JBoss 4 the JBoss Group (the organisation behind the JBoss server) has decided
to extend the functionality of the JBoss server, so it no longer is only a J2EE server.
With the emergence of aspect oriented programming techniques the JBoss group has
seen a way to ease the development cycle of applications that need services like those
provided by J2EE. Instead of developing cumbersome Enterprise Java Beans (EJBs)
it should be possible to develop ordinary Java classes free of restrictions such as
those of EJB and offer the same services that EJBs benefit from to these ordinary
classes. The services are added to the classes with aspect oriented techniques.

The server version we have used throughout this report is a checkout from the JBoss
CVS head branch from 16th of December 2003: JBoss 4.0.0DR3(200312161202), Ver-
sion Name: Zion

9
CHAPTER 2. JBOSS 10

2.2 MBeans and the JBoss Web-console

We briefly describe Management Beans (MBeans) and the JBoss web-console here.
We will refer to both MBeans and the web-console from time to time in the rest of
the report. This section is not meant to be exhaustive for a longer explanation and
references to more information see appendix A.2, A.3 and A.4.

MBeans are a part of the Java Management Extensions (JMX) specification and can
be used to manage a manageable component. An MBean is a Java Bean with a few
more restrictions. MBeans are deployed in an MBean server in this case JBoss is
the MBean server and they have a management application that can be used to
configure and access them. In JBoss the web-console is the management application.

In the web-console the MBeans are listed and their methods can be invoked through
the web interface. When a method is invoked on an MBean, the MBean invokes an
appropriate method on the component it manages. The manageable component can
be a part of an application deployed on the JBoss server.

The web-console is a Servlet-based management interface for JBoss and it can be


used to get information on and access to applications running in the server. A man-
agement component is called an Mbean (Management Bean) and it works as an in-
terface to the application.
Chapter 3

Aspect Oriented Programming

This chapter is a presentation of aspect oriented programming in general and will


introduce the core concepts in the field, starting with crosscutting concerns.

3.1 Crosscutting Concerns

Generally in software development the design process is about breaking down the
system into units of behaviour or function. This is often referred to as functional
decomposition [10]. A reduction of the complexity in a system is achieved by splitting
a vast subject-domain into smaller intelligible units. Dijkstra talks about separation
of concerns in 1976:

To my taste the main characteristic of intelligent thinking is that one


is willing and able to study in depth an aspect of ones subject matter in
isolation, for the sake of its own consistency, all the time knowing that
one is occupying oneself with only one of the aspects. The other aspects
have to wait their turn, because our heads are so small that we cannot
deal with them simultaneously without getting confused. [...] I usually
refer to it as a separation of concerns, because one tries dealing with the
difficulties, the obligations, the desires, and the constraints one by one.[...]
The purpose of thinking is to reduce the detailed reasoning needed to a
doable amount, and a separation of concerns is the way in which we hope
to achieve this reduction. [7], p.220

The object oriented paradigm has brought into the picture a way to modularize con-
cerns by building hierarchies of classes through classification and specialization.

11
CHAPTER 3. ASPECT ORIENTED PROGRAMMING 12

But across these hierarchies concerns may exist that are not possible to generalize
through inheritance or polymorphism. Having decomposed the system into a class
hierarchy, some general issues cannot be dealt with in a modularized way. These
concerns are called crosscutting concerns.

The presence of crosscutting concerns basically shows in two ways: (1)By leaving
the actual functionality scattered across multiple classes as redundant code. This
condition is called scattering [15]. (2) When two or more collocated concerns overlap
each other the code is said to be tangled. With Kiczaless words,

the tangled code is extremely difficult to maintain, since small changes


to the functionality require mentally untangling and then re-tangling it.
[10]p.226.

It is possible to view object orientation as a vertical organization of classes with a


horizontal distribution of crosscutting concerns.

An example of a crosscutting concern could be a logging feature that tracked cer-


tain method calls in different classes and wrote down the method name, the passed
parameters and timestamps in a file.

Implementing the logging concern will result in logging statements scattered across
a wide range of classes and the symptoms will include:

Redundant code

Unclear structure

Maintainability problems to change something you would have to find all oc-
currences of a certain piece of logic, change it everywhere and be sure not to
introduce new errors

Code in a class that is irrelevant to the concern of the class (eg a logging mech-
anism)

3.2 Traditional Handling of Crosscutting Concerns

Crosscutting concerns are often identified at early stages in the design process, but
there are no silver bullet solutions to the problems mentioned above. Object oriented
solutions to deal with crosscutting concerns can be found in the use of design pat-
terns. Design patterns are general solutions to common design problems and some
of them are used for separating crosscutting concerns [9]. Here are a couple of exam-
ples:
CHAPTER 3. ASPECT ORIENTED PROGRAMMING 13

The Visitor design pattern makes it possible to extend the functionality of classes
across the class hierarchy, but even if there is a separation of concerns in this
pattern, the coupling between the visited object and the visiting object is rather
tight.
The visited objects cannot be oblivious to the visiting object, and the visiting
object cannot treat the visited objects in a general way, but will have to know
the exact nature of each member of the visited family of objects. A complex vis-
itor implementation can be hard to maintain, as adding of visitor functionality
requires that new code is added to the visitor hierarchy and maybe also to the
methods in the visited object tree.

In the Observer pattern a number of Observer objects registers with a Subject. The
subject notifies the observers of changes to its state. The primary concern for
the subject is not necessarily the notification of observers and a subject can be
part of several observer patterns with different purposes. The observer pattern
separates the state of an object and the presentation of that state on changes,
The subject only has to implement the simple notification of attached observers
on updates.

Many design patterns are a good and very common solution to minimizing the tan-
gling of code, but as we shall see there are other ways to do it.

3.2.1 Handling Crosscutting Concerns with Aspect Oriented Program-


ming

As we have tried to explain, it is not a trivial thing to separate concerns that inter-
twine. In aspect oriented programming the idea is that the existing way of modular-
izing traditional OOP concerns organized by classification and specialization should
be kept.

Concerns that are crosscutting should be modularized themselves and isolated from
the existing code. These isolated concerns are the aspects of aspect oriented program-
ming. In the logging example above the logging functionality can be identified as an
aspect that should be implemented by itself.

A common way of presenting aspect oriented programming is the notion of vertical


and horizontal decomposition. The vertical is the object oriented hierarchy as a result
of the functional decomposition what we could call a decomposition of the first order.
The aspects are a result of what could be called a decomposition of the second order,
and they can be visualized horizontally as sis done in figure 3.1
CHAPTER 3. ASPECT ORIENTED PROGRAMMING 14

Figure 3.1: Concerns as horizontal decomposition

Class 1 Class2

+a() +uniqueMethod()

Class3 Class4 Class5 Class 6

Logging Concern +a() +doSomethingImportant() +uniqueMethod() +powerMethod()

Log.print("doSomethingImportant();"); Log.print("powerMethod()");

Log.print("a()"); Log.print("uniqueMethod()");

3.3 What is Aspect Oriented Programming

AOP can be classified as a new layer on top of object oriented programming. It sup-
plies a new level of abstraction, both as a way of thinking software design and a way
of actually implementing it

In his introductory paper, Kiczales defined what the basic properties of an aspect
oriented implementation should consist of:

(a) a component language with which to program the components, (b) one
or more aspect languages with which to program the aspects, (c) an aspect
weaver for the combined languages, (d) a component program, that imple-
ments the components using the component language, and (e) one or more
aspect programs that implement the aspects using the aspect languages.
[10] p. 235

Here components corresponds to classes and packages from the vertical decomposi-
tion.

The aspect programs must be weaved into the components by the weaver. Looking
at figure 3.1 the points at which this weaving should be made is easily identified as
the places where there are logging statements. The places where the vertical and
horizontal structures intersect are called joinpoints or pointcuts and this is where
the component code and the aspect code is weaved together.

An implementation of aspect oriented programming must provide a way to mark


CHAPTER 3. ASPECT ORIENTED PROGRAMMING 15

these pointcuts so the aspect weaver can merge the code. A pointcut will typically be
a field, a constructor or a method in a specified range of classes. The aspect code that
should be executed at that point will have access to the context of the pointcut that
is the arguments passed and local variables in the target class.

The implementations of AOP currently available on the market use quite different
approaches in that they vary in pointcut model, aspect language and aspect weaving.

3.4 AOP Implementations for Java a Short Overview

The following is a short presentation of the AOP implementations that AOSD.net


(Home of the Aspect-Oriented Software Development conference) has categorized as
"Tools for practitioners". Many other projects exist, but the following implementa-
tions are the ones with the broadest support.

AspectJ

AspectJ [3] is the oldest implementation and has been developed by Gregor Kicza-
les [10]. The aspect language in AspectJ is Java with some syntactical extensions.
Aspects are modularized into separate units not unlike classes. The weaver is a pre-
compiler that produces valid Java source code. AspectJ does not yet support runtime
bytecode weaving.

AspectWerkz

AspectWerkz [4] is an open source project. It can weave by preprocessing at compile


time or use runtime bytecode manipulation. The aspect language is plain Java and
the project aims to integrate with other projects both open source and commercial.

JAC

JAC [12] is a French AOP framework oriented towards middleware. It is an applica-


tion server (or container), but not J2EE compliant. JAC uses runtime weaving and
unweaving and supplies a range of aspect components for applications running in the
container.
CHAPTER 3. ASPECT ORIENTED PROGRAMMING 16

JBoss AOP

JBoss-AOP [14] is the Java AOP architecture used for the JBoss application server.
It uses runtime weaving, and Java and XML as the aspect languages. It comes with
a range of aspect components.

Nanning

Nanning [16] is another open source AOP project. It uses dynamic proxies for runtime
weaving. Dynamic proxies is part of Java 1.4.

3.5 From Aspect Components to AOP-services

If the result of the functional decomposition constitutes the core functionality of the
application, then the identified aspects can be seen as a service (or add-on) for the
core application. This is the case for the logging example in figure 3.1. The aspect
component can be called an aspect oriented service or AOP-service in short, which is
the naming convention we use in this report.

An AOP-service is meant to run on top of something that is already there. In other


words the AOP-layer has a certain secondary quality compared to the application
that it will cross cut. The relation to the core application can be anywhere between
very general and very specific.

General services are loosely coupled to the underlying application and can be used,
ideally, on top of any application. A general service could be for logging, persistence,
remoting, security or something similar.

Specific or custom services are tightly coupled to the underlying application. Such a
service is not meant to be widely ported but is written to supply a specific functional-
ity to a specific target.

Integration of the aspect components in the design from the start is a third way to
approach AOP development. This might be one of the most interesting things about
AOP seeing it as a new paradigm in software development, not on top of program-
ming.

Choosing any of the three approaches to aspect oriented programming has conse-
quences:

A general service is portable across multiple domains but it is coarse grained.


CHAPTER 3. ASPECT ORIENTED PROGRAMMING 17

A custom service is fine grained but hard or impossible to transfer to another


domain.

An integrated service can hardly be seen as a service as it is merged into the


application design. Thus it cannot be ported. And the application cannot run
without the aspect components.

In the rest of this report we will refer to both general and custom services with the
term AOP-service.

3.6 Some Perspectives

As aspect oriented programming is gaining wider support, new software development


methodologies are needed. The paradigm is being applied at different levels, and we
will provide a few examples here:

Early aspects is a research initiative that focuses on managing crosscutting prop-


erties at the early development stages of requirements engineering and archi-
tecture design [8]. Early aspects are initially not code oriented and the idea is
to include the design process as a whole in the aspect oriented line of thought.

Aspect mining is the process of analyzing existing code with the purpose of identify-
ing crosscutting concerns that could be extracted and re-implemented as aspect
components [2]. Several tools such as the Aspect Mining Tool [11] have been
designed for facilitating this analysis process.

Aspect Modelling is another challenge for aspect oriented software development


and it receives a lot of attention from the AOSD research community [17]. UML
has not been made with AOP in mind, and later in this report we will provide a
suggestion for a notation of aspects and crosscutting concerns.

Abstraction is generalizing more things into one, throwing away details, forgetting
differences and reducing volume. Aspect oriented programming is not necessarily
an abstraction put on top of object oriented programming, as the untangling merely
relocates the scattered code. Modularizing aspects is of course an abstraction, but
it is an abstraction at the well known object oriented level. The braintwisting thing
about aspect oriented programming is not abstraction, it is dimension. Developers
will have to grasp two dimensions at the same time, switching between a vertical
and a horizontal perspective and this puts a cognitive burden on the developer. With
the words of Karl Lieberherr:
CHAPTER 3. ASPECT ORIENTED PROGRAMMING 18

If advice can be added to a joinpoint by any aspect, we must discover and


understand all aspects globally in order to comprehend a methodss local
behaviour. [15] p.543

This burden should not be on developers but on the tools and methodologies. As an
example AspectJ has provided a plugin for Eclipse that supports the construction and
the visual representation of crosscutting aspects.

After this theoretical section on AOP we will proceed to the presentation of the case
application developed for this project. This application will be extended with an AOP
layer in chapter 6.
Chapter 4

Inventory Management Case


Introduction

This chapter will present the core application developed for this project. This will be
the empirical foundation for the practical work on AOP-services in chapter 6 and the
examples in the presentation of the JBoss AOP internals in part III.

4.1 What Application did we Create and Why?

To demonstrate the usage the AOP framework in JBoss 4 we have created an appli-
cation that uses a large part of its features. We wanted the application to be more
than just a simple example, and large enough to use several features of the AOP
framework in a natural context.

To meet our own requirements we decided to create an application for a domain that
would give us plenty of potential features and room for expansion. We also wanted
to make sure that a great deal of the features of the application would inherently
be crosscutting, since these would be prime candidates for separation into aspect
components, that can be plugged in and out of the main application.

We have not made a fully functional application since this is beyond the scope of our
thesis. However we have implemented a small core, which is sufficient to accommo-
date a range of AOP-services.

An inventory management system has potential for many features and expansions.
It is already a field with many well-established requirements [5].

The core contains only what is absolutely necessary to implement a simple inventory
management system:

19
CHAPTER 4. INVENTORY MANAGEMENT CASE INTRODUCTION 20

A database representation of items in the inventory.

Adding and removing items.

Creation of reservations of items, contained in orders.

Creating an invoice is the realization of an order, and it removes reserved items


from inventory.

Our application is simply called "Inventory Management". Its overall goal is to han-
dle stocks of goods. Once all the goods have been collected from stock an invoice can
be created.

Creating an invoice concludes the transaction and the stock level of goods is decre-
mented with the amount shipped out.

In this chapter we will not go into details about the AOP-services mounted on top of
the core application, but rather defer this to chapter 5, where a description of how to
create an AOP-service is provided.

4.2 The Core Application a Technical Walkthrough

Figure 4.1 gives an overview of all the classes and their packages in the core applica-
tion.

Figure 4.1: All core-classes and their packages


CHAPTER 4. INVENTORY MANAGEMENT CASE INTRODUCTION 21

4.2.1 The jboss.thesis.inventory.model Package

This package contains the data objects of the application. If the application had been
persistent (a feature we have left out) almost all of these objects would have had their
state saved in some way.

We here provide an overview of the classes in the jboss.thesis.inventory.model


package as well as their overall use. (See the actual code in appendix M).

In diagram 4.2, the relations are modelled as static UML.

Customer : A particular customer who can order Products (appendix M.1).

IdUtil: A utility class for generating unique IDs for several of the classes in this
package. This utility is needed due to AOP remoting1 which requires that
Objects be registered with unique IDs. If the core application had been persis-
tent, something similar to this class would have been needed to create primary
keys for the objects (appendix M.2).

OrderList: A list that contains all Orders made in the system regardless of who or-
dered them. This OrderList only exists because the application is not persistent.
It can be compared to a table in a database. We use the list for keeping track of
the orders and to enable us to search for specific Orders. It is implemented as a
Singleton (design pattern, see [9]) (appendix M.4).

Order : An order placed by a Customer. An Order has a reference to a Customer as


well as to one or more Reservations. It is through an Order that an invoice is
created (appendix M.3).

Product: A product in the inventory management system such as specific CPUs,


chains for bicycles or screws in a tool shop. A Product instance does not repre-
sent a physical object in the real world. Instead a Product contains a number
that states how many physical objects it represents. This is done for perfor-
mance reasons. If the system was to map Product instances with real-world
objects it would be flooded with object instances if the system was managing,
say, nuts and bolts. The Product class is an interface for the ProductImpl and
ProductComposite classes (appendix M.5).

ProductImpl: A concrete implementation of the Product interface (appendix M.6).

ProductComposite : A product that consists of several Products. A ProductCompo-


site is for instance an entire computer that consists of several ProductImpl ob-
jects such as RAM, HDD, motherboard etc. The ProductComposite class follows
1 Remoting is the JBoss way of doing remote method calls equivalent to Java RMI. AOP remoting is
remoting implemented via the JBoss AOP framework.
CHAPTER 4. INVENTORY MANAGEMENT CASE INTRODUCTION 22

the design conventions of the Composite design pattern [9] with the addition
that a ProductComposite does not allow cyclic references (appendix M.7).

Reservation: A reservation of a Product in a given Order in the system. A Reserva-


tion has a reference to the Product reserved, and contains an int representing
how many of the particular Product has been reserved (appendix M.8).

Type: A generic type of product. This could for instance be CPU or HDD. The
difference between a CPU Product and a CPU Type is that a Product is a
specific kind of CPU such as Athlon 1,2Ghz and the Type is just CPU. In
other words the Type is meant to classify a Product. A Product has methods
that returns its name (eg. Athlon 500+ Mhz) as well as its Type (eg. CPU)
((appendix M.9).

4.2.2 The jboss.thesis.inventory.controller Package

The classes in this package define functionality of the Inventory Management system
that links together some of the classes in the jboss.thesis.inventory.model package.
There are also classes that exist solely to make the functionality of the application
possible via JBoss AOP remoting.

CreationException: The exception thrown if a Product, Order or Reservation could


not be created. It is mainly used for remoting reasons in which objects that need
to be remote are created via a FactoryMethod [9].

InventoryController : The central business logic of the application implement-


ed as a singleton. In some ways it acts as a link between the core application,
AOP-services and the client application. Since the core application is not per-
sistent the InventoryController acts as a database for Products and Orders
created in the application.

InventoryFactory : Used to create instances of the classes in the jboss.thesis.-


inventory.model package. It is only needed because our client application uses
JBoss AOP remoting. It creates objects of the types specified and also produce
a proxy of that instance. The proxy is serialized to the client and the real
object is kept on the server side. The InventoryFactory also provides a series of
methods that can return the real object instead of the proxy. This functionality
is needed on the server side in the AOP-services.

NoSuchOrderException: This exception is thrown whenever a part of the applica-


tion looks up an Order that does not exist (ie. the Order ID looked up does not
exist).
CHAPTER 4. INVENTORY MANAGEMENT CASE INTRODUCTION 23

Figure 4.2: Core classes in the jboss.thesis.inventory.model package

IdUtil OrderList
-orders : ArrayList
Order 0..*
1 -quantity : int

Reservation 0..* Customer


-quantity : int 1

1 interface 1 Type
Product

0..*

ProductComposite ProductImpl

RemoteUtil: Provides convenience methods for obtaining remote references to the


InventoryController, InventoryFactory and the OrderList. This is used from
the client.

In figure 4.3 we show how most of the classes in the packages jboss.thesis.inven-
tory.model and jboss.thesis.inventory.controller fit together on a class level.
CHAPTER 4. INVENTORY MANAGEMENT CASE INTRODUCTION 24

Figure 4.3: A view of some of the jboss.thesis.inventory.model and jboss.the-


sis.inventory.controller classes

IdUtil OrderList 1
-orders
Order 0..*
1 -quantity : int
InventoryController

Reservation 0..* Customer 1


1 +getOrder() : Order
-quantity : int
1 +addOrder()
+removeOrder()
+getProduct() : Product
+addProduct()
1 interface 1 Type +removeProduct()
Product +getOrders() : OrderList

0..* 0..*

ProductComposite ProductImpl InventoryFactory


throws CreationException
+createCustomer() : Customer
+createOrder() : Order
+createProductComposite() : Product
+createProductImpl() : Product
+createReservation() : Reservation
+createType() : Type
+getLocalProduct() : Product
+getLocalProductComposite() : ProductComposite
+getLocalProductImpl() : ProductImpl

4.3 Client Application

We have made a graphical client application that we use with the inventory manage-
ment application. The client program is a simple Swing application that has suffi-
cient functionality to exercise all the features of the core application.

The client application can be used to:

Create new orders.

See information about orders.

Reserve products for a particular order.

Finish orders by creating invoices. (No invoice is actually created. Instead the
core application is told that an order is completed and that the stock levels of
the products in the order should be decremented).

Delete non-finished orders.


CHAPTER 4. INVENTORY MANAGEMENT CASE INTRODUCTION 25

Figure 4.4: The Client Application Main Window

Figure 4.5: Creating or editing an order

In figure 4.4 the main window lists all orders in the system. One order has already
been created, but not yet processed by creating an invoice.

By creating a new order through the InventoryFactory an Order object is created


on the JBoss server, and a proxy for communication with the server side object is
serialized to the client.

In figure 4.5 the window for creating or editing existing orders is shown. Products
can be added to the order. An order can be saved for later use or deleted. Once all the
products have been added to the order an invoice can be created. When an invoice
is created the number of Products in the Order is subtracted from the stock in the
management system on the server.
CHAPTER 4. INVENTORY MANAGEMENT CASE INTRODUCTION 26

The graphical client application can be run standalone or as a Java Web Start ap-
plication. In the latter case it needs to be deployed on the JBoss server as a web
application (.war file).

4.4 Inventory Management System Setup

When the inventory management system starts up the InventoryController is popu-


lated with Products. The computer hardware retailer has been chosen as domain to
illustrate the use of the inventory management system. It is also necessary to create
instances of the classes needed for servicing the application and client (most of the
classes in the jboss.thesis.inventory.controller package).

We have created an MBean (jboss.thesis.inventory.model.jmx.InventoryService)


that takes care of setting up the management system when the application is de-
ployed on the server. The startup actions of the MBean are as follows:

1. Create an instance of the jboss.thesis.inventory.controller.InventoryFac-


tory class. Create a proxy for the InventoryFactory class and bind the proxy in
JNDI. The proxy is used by the client application to access the InventoryFactory
remotely.

2. Repeat step 1 for the classes jboss.thesis.inventory.controller.Inventory-


Controller and jboss.thesis.inventory.model.OrderList.

3. Create a range of different products by creating instances of Product using the


InventoryFactory (thus creating proxies as well as normal instances of the Pro-
ducts). Fill out the Products with relevant information (such as CPU, Ahtlon
1200+ etc.) and add them to the InventoryController.

Now the client application can talk to the management system remotely, and use the
Products to create Orders.

This was the the core case application the inventory management system.

Turning back to JBoss the next part will be about the use of the JBoss AOP frame-
work. Firstly an introduction to using it, and secondly a presentation of the AOP-
services put on top of the core application.
Part II

Creating Your Own


AOP-Applications and
AOP-Services

27
Part Overview

The chapters in this part explain how to use the JBoss AOP framework.

The part consists of the following chapters:

Chapter 5 Using the JBoss AOP Framework. This chapter explains the differ-
ent parts of the JBoss AOP framework and how to use them when creating
AOP-applications and AOP-services.

Chapter 6 Inventory Management Case AOP-Services. In this chapter the knowl-


edge acquired in the previous chapter is used to create AOP-services for the
Inventory Management AOP-application. It is a technical view of the AOP-
services created.

28
Chapter 5

Using the JBoss AOP


Framework

This chapter is an overview of the AOP framework in JBoss 4. It will be a quick run-
down off the basic concepts in the framework. Chapter 3 on aspect oriented program-
ming have provided the theoretical background and the examples given are taken
from the preceding chapter 4 on the inventory management system.

An overview of some of the main classes of the AOP framework can be found in the
appendices in part II.

5.1 The Pointcut Model

In JBoss AOP a pointcut is a specific point in the thread of execution of the applica-
tion, where the new functionality is added in the form of interceptors. One could say
that the pointcut is the where and when of aspect oriented programming. The inter-
ceptor is the what that is, what logic to execute at the time a pointcut is reached.

The aspect weaving in JBoss is done by modifying the bytecode of the existing com-
piled classes. This process is called the instrumentation process or you could say
that the classes are being instrumented with aspects. It is necessary to tell JBoss
which classes should be available for AOP instrumentation. This is done in the AOP
deployment descriptor, jboss-aop.xml:

Listing 5.1: Which Classes can be Aspectized


1 <aop >
2 < advisable class =" jboss . thesis . inventory . model .*" / >
3 < advisable class =" jboss . thesis . inventory . controller . InventoryController " / >
4 </aop >

29
CHAPTER 5. USING THE JBOSS AOP FRAMEWORK 30

In this example jboss.thesis.inventory.controller.InventoryController and all


classes in jboss.thesis.inventory.model and its subpackages will be instrumented.

5.1.1 Pointcuts

There is a range of different types of pointcuts:

Class-pointcut which matches every access to an objects constructors, methods and


fields. This is the pointcut with the coarsest granularity. Awkwardly the class
corresponding to the class-pointcut is named InterceptorPointcut. This incon-
sistency is being fixed as we write this.

Method-pointcut; Matches method calls.

Constructor-pointcut: matches the initialization of objects.

Field-pointcut: Matches direct field access both from the within the class and
from other objects.

Caller-pointcut: Matches method calls from within a specified method in a given


class A on objects of type B. The caller-pointcut can be seen as method-pointcut
with a finer granularity, matching not only the target but also the origin of the
method invocation.

Introduction-pointcuts: Used for introductions a feature to enable runtime im-


plementation of interfaces. Calling this a pointcut is somewhat misleading as
it is a completely different concept than that of the other poincuts. See section
5.1.5 on introductions.

Pointcuts are defined in the AOP deployment descriptor, jboss-aop.xml:

Listing 5.2: Three pointcuts: field, method and caller


1 <field - pointcut class =" jboss . thesis . inventory . model .*" fieldName =" name ">
2 < interceptors >
3 < interceptor - ref name =" MyInterceptor "/ >
4 </ interceptors >
5 </ field - pointcut >
6

7 < method - pointcut class =" jboss . thesis . inventory . model .*" methodName =" setName ">
8 < interceptors >
9 < interceptor - ref name =" MyInterceptor "/ >
CHAPTER 5. USING THE JBOSS AOP FRAMEWORK 31

10 </ interceptors >


11 </ method - pointcut >
12

13 < caller - pointcut class =" jboss . thesis . inventory . model . Order "
14 withinMethodName =" createInvoice "
15 calledClass =" jboss . thesis . inventory . model . Product "
16 calledMethod =" decreaseStockBy ">
17 < interceptors >
18 < interceptor - ref name =" MyInterceptor "/ >
19 </ interceptors >
20 </ caller - pointcut >
21

22 < method - pointcut class =" jboss . thesis . inventory . model .*" methodName =".*" >
23 < interceptors >
24 < interceptor - ref name =" MyInterceptor "/ >
25 </ interceptors >
26 </ method - pointcut >

The three pointcuts in Listing 5.2 represent three different granularities. They all
match field access.

The field-pointcut (line 1-5) will match any access to the denoted field from any class.

The method-pointcut (line 7-11) is a more narrow match here the direct field-access
is not matched, only the set-method on the field, which provides a more economic way
of monitoring field access.

The caller-pointcut (line 13-20) is the most fine grained pointcut, letting us match
very special cases of method invocations. What the XML in the caller-pointcut states
is that:

1. The method that will be monitored for invocations is the decreaseStockBy()


method

2. In the class jboss.thesis.inventory.model.Product.

3. The class from which the decreaseStockBy method must be called before any
interception can occur is the jboss.thesis.inventory.model.Order class.

4. Furthermore the decreaseStockBy method must be called from within the method
createInvoice() in the Order class.

The last method-pointcut (line 22-26) demonstrates how regular expressions are used
for the matching. This can be applied to fields, classes and methods.
CHAPTER 5. USING THE JBOSS AOP FRAMEWORK 32

5.1.2 Interceptors and Interceptor Chains

For intercepting the various types of access to class, constructor, method or field JBoss
uses an Interceptor. An interceptor contains the code that will be executed when a
given pointcut is reached. The interceptor is a Java class that must implement the
Interceptor interface:

Listing 5.3: org.jboss.aop.Interceptor


1 public interface Interceptor {
2 public Object invoke ( Invocation invocation );
3 public String getName ();
4 }

The framework calls invoke() on the interceptor and this method performs what
needs to be done at the particular pointcut. The interceptor has access to the context
data in the Invocation object.

Figure 5.1: A generalized interceptor chain

When there are more than one interceptor associated with a pointcut, the intercep-
tors are said to be in an interceptor stack or chain. Every intercepted invocation runs
through all the interceptors in the appointed chain, calling them subsequently by
calling invokeNext() on the invocation (Figure 5.1).

In the actual implementation of the Interceptor, an Invocation-object and a response-


Object, represent the way into and out of the pointcut (see listing 5.4).
CHAPTER 5. USING THE JBOSS AOP FRAMEWORK 33

Listing 5.4: SimpleInterceptor


1 public class SimpleInterceptor implements Interceptor {
2 public Object invoke ( Invocation inv ){
3 // do something before entering the method
4 Object returnval = inv . invokeNext ();
5 // do something after returning from the method
6 return returnval ;
7 }
8 public String getName (){
9 return " SimpleInterceptor ";
10 }
11 }

Interceptors are not forced to call invokeNext() it is perfectly legal to break the in-
terceptor chain by returning a new Object(). But in doing so caution is called for. Not
only is it possible to change behaviour in classes by adding new code in interceptors,
but by breaking the interceptor chain it is also possible to change behaviour for other
interceptors that have been added to a pointcut.

Interceptors can be used to add code both on the way in and on the way out of the
intercepted method call, constructor call or field access, and it is possible to modify
the arguments on the way in and the return values on the way out. The return
value from invoke() is returned to another interceptor or to the calling object. An
example of an aspect where the return value of a method would be changed could be
an aspect for translating the return values of getMessage() invocations into German
an approach that could be useful for localization of error handling.

As a general rule, an interceptor should always call invokeNext().

Although it is possible to call invokeNext() more than once, only the first time will
result in a valid value as the Invocation object manages the interceptor chain.

Below is another simple interceptor, which logs method invocations:

Listing 5.5: DecreaseLoggingInterceptor


1 public class DecreaseLoggingInterceptor implements Interceptor {
2 public Object invoke ( Invocation inv ){
3 MethodInvocation invocation = ( MethodInvocation ) inv ; // ( A)
4 MyObject o = ( MyObject ) invocation . targetObject ; // ( B)
5 System . out . println (" Now decreasing : " + o. getName ()); // ( C)
6 Integer arg = ( Integer ) invocation . arguments [0];
7 System . out . println (" by "+ arg +" items "); // ( D)
8 return inv . invokeNext (); // ( E)
9 }
10 public String getName (){
CHAPTER 5. USING THE JBOSS AOP FRAMEWORK 34

11 return " DecreaseLoggingInterceptor ";


12 }
13 }

At (A) we get hold of the MethodInvocation object, then at (B) we take the object on
which the method was called and at (C) print out a log entry with the results of the
getName() method of the target object along with (D) the supplied argument to the
method. Finally (E) we pass on the request to the next interceptor in the chain. Note
that in the above example the logging is done before entering the method.

The interceptors are also specified in the AOP deployment descriptor. An interceptor
can either be a specific class like the DecreaseLoggingInterceptor or it can be created
by an interceptor factory class and configured with custom elements in the XML file.

Listing 5.6: Specifying interceptors in XML


1 < interceptor name =" MyInterceptor " class =" DecreaseLoggingInterceptor "/ >
2

3 < interceptor name =" AnotherInterceptor " factory =" MyInterceptorFactory ">
4 < myCustomParameter value ="42"/ >
5 </ interceptor >
6

7 < stack name =" InterceptorStack ">


8 < interceptors >
9 < interceptor class =" DecreaseLoggingInterceptor "/ >
10 < interceptor class =" AnotherInterceptor "/ >
11 </ interceptors >
12 </ stack >
13

14 < method - pointcut class =" jboss . thesis . inventory . model .*" methodName =".*" >
15 < interceptors >
16 < interceptor - ref name =" MyInterceptor "/ >
17 < stack - ref name =" InterceptorStack "/ >
18 </ interceptors >
19 </ method - pointcut >

The result of this configuration: Any call to any method in any class in the package
jboss.thesis.inventory.model will be intercepted in this order:
MyInterceptor SimpleLoggingInterceptor AnotherInterceptor.

5.1.3 Dynamic Interceptors

The examples so far have shown how adding pointcuts and interceptors is done dur-
ing development in the AOP deployment descriptor. This means that pointcuts and
interceptors are deployed when the application loads.
CHAPTER 5. USING THE JBOSS AOP FRAMEWORK 35

But interceptors can also be applied runtime so long as the target class is marked as
advisable in the AOP deployment descriptor.

Listing 5.7: How to use a dynamic interceptor


1 AspectManager am = AspectManager . instance ();
2

3 am . addInterceptorFactory (" DynInterceptorFactory " , new InterceptorFactory (){


4 public Interceptor create ( Advisor advisor ) {
5 return new DynamicInterceptor ();
6 }
7 });
8

9 InterceptorPointcut ip = new MethodPointcut (


10 " DynMethodPointcut " , // name of the pointcut
11 " jboss . thesis . inventory . model. Product " , // the regexp for the class
12 null , // metadata group , there is no metadata attached to the pointcut
13 "" , // method attributes to match . E.g . " public static "
14 " setName " , // name of method to intercept
15 new String [] { " DynInterceptorFactory " } , // InterceptorFactory names
16 InterceptorFilter . NONE ); // method filter
17

18 am . addInterceptorPointcut ( ip );

The code from listing 5.7 would go into a class used for controlling aspect behaviour.
This class could be a controller or support class for the application containing AOP-
services.

The AspectManager is a singleton class that manages all pointcuts and metadata in
the JVM. By adding an InterceptorFactory that creates a DynamicInterceptor (an
arbitrary example interceptor), an InterceptorPointcut "DynMethodPointcut" (line
9) is made, matching the setName() method on Product.

Finally the pointcut is added to the AspectManager (line 18), and now all instances of
Product in the JVM have been instrumented with a new pointcut and an interceptor.
This happens instantly across the JVM and the code contained in the interceptor can
potentially be thread-unsafe.

Adding global interceptors runtime is not recommended unless you know exactly
what classes are matched by your pointcut and how your interceptors affect these
classes.

Another way to use interceptors dynamically is by adding them per instance. Each
instance of an advised class has an associated ClassInstanceAdvisor:
CHAPTER 5. USING THE JBOSS AOP FRAMEWORK 36

Listing 5.8: Applying interceptors per instance


1 Advisable adv = ( Advisable ) myObj ; // casting to the Advisable interface
2 ClassInstanceAdvisor cia = ( ClassInstanceAdvisor ) adv . _getInstanceAdvisor ();
3 cia . appendInterceptor ( new DynamicInterceptor ());

The code block in listing 5.8 would also go into a class used for controlling aspect
behaviour.

Note that in this case a pointcut is not used to mark the place of interception. Adding
interceptors directly like this corresponds to using a class-pointcut. The matching
granularity is very coarse as the interceptor is invoked for every constructor, method
or field access. If you want to intercept a certain method call you must first filter out
field and constructor access and then filter out the irrelevant methods.

5.1.4 Metadata

Metadata is a feature that allows developers of AOP-services to attach meta infor-


mation to classes. This is a feature that has already been implemented in a language
such as C# and it will also be part of the next Java release 1.5 [6].

In JBoss AOP the attachment of metadata to classes is specified in the AOP deploy-
ment descriptor. It can be attached to a whole class, a method or to a field.

Listing 5.9: Metadata example


1 <class - metadata group =" logging " class =" jboss . thesis . inventory . model .*" >
2 <default >
3 < logging - attribute > Disabled </ logging - attribute >
4 </ default >
5

6 < method name =" decreaseStockBy ">


7 < logging - attribute > Enabled </ logging - attribute >
8 </ method >
9

10 < field name =" stock ">


11 < logging - attribute > Enabled </ logging - attribute >
12 </ field >
13 </ class - metadata >

The attached metadata will be accessible from interceptors that handle the object,
like this:
CHAPTER 5. USING THE JBOSS AOP FRAMEWORK 37

Listing 5.10: Accessing metadata


1 public Object invoke ( Invocation invocation ){
2 String loggingProp = ( String ) invocation . getMetaData (" logging ",
3 " logging - attribute ");
4 ... // do logging if it is " enabled "
5 return invocation . invokeNext ();
6 }

The metadata facility in JBoss AOP attaches attributes to classes, making the in-
formation available to a deployed AOP service as in our logging example. As shown
above, the metadata is not attached directly to the class but is placed centrally in the
AOP deployment descriptor file. A code generation tool like XDoclet [21] can be used
to generate the deployment descriptor if special JBoss AOP JavaDoc-tags have been
written in the Java source file. This approach makes it somewhat easier to keep the
source file and the deployment descriptor constantly synchronized with each other.
We will not cover the use of XDoclet with JBoss AOP in this report.

Besides using JBoss metadata to do static tagging of classes it is also possible to dy-
namically attach metadata to various scopes: per invocation, per thread, per instance
and as the default: per class. This provides the developer with a very flexible way of
controlling services and applications. The different scopes will result in different be-
haviour and although it is flexible the application may become more complex, putting
a cognitive burden on the developers.

Metadata can be seen as a way to add dynamic fields to the class with different scopes
from invocation to cluster, but without any kind of encapsulation metadata can be
overwritten by anyone who gets hold of the appropriate context. It is impossible to
place restriction on the access to metadata-attributes on advised classes.

Dynamic metadata can be quite useful it is possible to do a highly fine-grained ser-


vice configuration of your application, saying something to the effect of: "this service
should run on all objects from the package jboss.thesis.inventory.model in this par-
ticular thread". Which would be a very nice and simple way to implement debugging
and logging features in big complex applications.

5.1.5 Introductions and Mixin Classes

Having identified a crosscutting concern for a wide range of classes, it has previously
been shown how to extend the functionality of the classes by intercepting various
kinds of access to chosen objects through pointcuts and interceptors.

Introductions is a means of letting classes implement one or more new interfaces at


CHAPTER 5. USING THE JBOSS AOP FRAMEWORK 38

Figure 5.2: Mixin class

interface
ReservationCounter
+getNumberOfReservations()
+incrementReservations()
+decrementReservations()

Product ProductMixin

1 1

load time. This allows typecasting the objects that have crosscutting concerns to the
same reference type, because they now implement a common interface.

The implemented methods can either be implemented in an interceptor or in a sep-


arate class called a mixin class. When an interface method is called on the instru-
mented classes, the method call is delegated to the specified interceptor or mixin
class. In the mixin class the methods of the interface must be implemented other-
wise a runtime exception is thrown. If an interceptor is used, the invoke(..) method
in the interceptor must provide the intended functionality of the introduced method.
The invoke(..) method must return an object corresponding to the return value of
the introduced method it should not call invokeNext() on the invocation object. This
design is unfortunate as it breaks the chaining of interceptors.

When using an interceptor to handle introduced methods, method-pointcuts must


be added for each introduced method. These method-pointcuts must reference the
interceptor that contains the implementations of the method functionality.

Figure 5.2 shows the result of introducing the interface ReservationCounter to Pro-
duct using the mixin class ProductMixin. A class CallerClass that calls the intro-
duced methods cannot do so directly on a Product reference or by casting the Product
reference to a ReservationCounter. This would result in a compile error when compil-
ing CallerClass, as the Product the compiler knows is not instrumented. There are
two ways to call introduced methods:

Either: Call introduced methods using reflection.

Or: Do a dirty cast by first casting the Product to an Object. Then cast the Object
to a ReservationCounter and finally call the method on this.
CHAPTER 5. USING THE JBOSS AOP FRAMEWORK 39

In either case type safety is nonexistent.

Listing 5.11: Specifying introductions in XML


1 < introduction - pointcut class =" jboss . thesis . inventory . model . ProductImpl ">
2 <mixin >
3 < interfaces > jboss . thesis . inventory . service . ReservationCounter </ interfaces >
4 < class > jboss . thesis . inventory . service . ProductMixin </ class >
5 < construction >
6 new jboss . thesis . inventory . service . ProductMixin ( this , 20 , 0 )
7 </ construction >
8 </ mixin >
9 </ introduction - pointcut >

In listing 5.11 the introduction-pointcut makes ProductImpl implement the interface


ReservationCounter using the mixin class ProductMixin. In this case it is also spec-
ified how the mixin class is constructed (line 10) here this is a reference to the
ProductImpl that holds the mixin class.

5.2 Writing an AOP-service

In this section we will explain the shortest path to implementing an AOP-service us-
ing our case application as an example. Note that the examples in this chapter are
simplified and therefore not the actual implementations of the inventory manage-
ment system.

Designing an AOP-service can be seen as a process that takes a number of steps [1]:

1. Identify concerns what kind of requirements does the application have?

2. Specify concerns in more detail.

3. Identify candidate aspects find concerns that are crosscutting.

4. Specify aspects.

In our inventory management system it is possible to identify a list of concerns for


the basic application. One of these is the ability to log certain events.

In the example of a very simple logging service the concern is easily identified as
the need to apply logging to a wide range of classes. It is needed to log both object
creation and decrementation of the stock of a product. Logging can be identified as
a candidate aspect as it is a concern that cuts across otherwise unrelated classes.
We will focus on this for now. Note that there might be other concerns that are not
CHAPTER 5. USING THE JBOSS AOP FRAMEWORK 40

crosscutting, but they will be dealt with by traditional design methods. This is yet
another challenge for AOP to be integrated with existing methodologies, but we will
not deal with this here.

Making the logging aspect more concrete it shows that two kinds of events need to be
monitored: object construction and invocation of decreaseStockBy(int i) on Product.

Thus, after the when and where of the aspect have been found, the pointcuts can be
defined: a constructor-pointcut and a method-pointcut that matches the appropri-
ate methods. Each pointcut will need its own interceptor, as the two events should
be logged in different ways. The constructor-interceptor will log info about the con-
structed object and the method-interceptor will log information about the product
that has been decremented in the inventory:

Listing 5.12: Pointcuts in a simple service


1 <aop >
2 < advisable class =" jboss . thesis . inventory . model .*"/ >
3

4 < interceptor name =" DecreaseLoggerInterceptor "


5 class =" DecreaseLoggingInterceptor "/ >
6

7 < interceptor name =" ConstructionLoggerInterceptor"


8 class =" ConstructionLoggingInterceptor"/ >
9

10 <method - pointcut class =" jboss . thesis . inventory . model .*"


11 methodName =" decreaseStockBy ">
12 < interceptors >
13 < interceptor - ref name =" DecreaseLogggerInterceptor "/ >
14 </ interceptors >
15 </ method - pointcut >
16

17 < constructor - pointcut class =" jboss . thesis . inventory . model .*" >
18 < interceptor - ref name =" ConstructionLoggerInterceptor"/ >
19 </ constructor - pointcut >
20 </aop >

The DecreaseLoggingInterceptor is shown in listing 5.5, and ModelConstructorLog-


gerInterceptor can be found in appendix O.10

5.3 Deploying Applications and AOP-services

As previously explained, an AOP-service can be more or less coupled to the applica-


tion it extends. In our case we have designed an application, where AOP from the
beginning was designed to be integrated. Conceptually our core application can run
CHAPTER 5. USING THE JBOSS AOP FRAMEWORK 41

independently of our AOP-service, but it would not make any sense and the idea of
a core application should be seen as an architectural decision. It would never be
relevant to use the core application alone as it is far too stripped down for real use.

Here we take the consequence of this tight coupling and deploy the application and
the AOP-service together.

In the rest of the report we shall refer to an application that contains classes that are
meant to be extended with AOP-services as an AOP-application. This distinguishes
AOP-applications from normal applications that have nothing to do with AOP. It also
conceptually at least separates the AOP-service from the AOP-application, thus
stressing the fact that an AOP-service can be deployed independently of the AOP-
application it depends on. Using these terms the core application of our inventory
management system would be the AOP-application. The interceptors etc. that extend
the functionality of the AOP-application constitute the AOP-service.

5.3.1 Accessing AOP-applications and AOP-services

As we have done in chapter 4, it is possible to create a client that can access the AOP-
application or AOP-service via JBoss AOP remoting. But at the time of writing, JBoss
AOP remoting functionality is not properly implemented and it has been difficult to
use this for remote access.

It should also be possible to access the AOP-application or AOP-service via a web


interface made with Java Servlets or Java Server Pages (JSPs), but there are prob-
lems with this approach (see section 7.4). However, these problems can be overcome
if it is acceptable to use MBeans and the JBoss web-console as interface to the AOP-
application or AOP-service.

We briefly describe here what is necessary to use MBeans as frontend to the AOP-
application or AOP-service.

The code in listing 5.13 demonstrates how to get hold of a fictive AOP-application
from the web-console. Methods from the AOP-application that should be available
through the web-console must be specified in the MBeanExampleMBean interface. The
callSomeAOPClassMethod() method returns a string that will be printed out in the
console. The console can print out Strings as well as primitive types, when they are
returned from a method. Objects will return the result of their toString() method.

Listing 5.13: A simple MBean (MBeanExample.java)


22 public class MBeanExample implements MBeanExampleMBean , MBeanRegistration {
23 public MBeanExample () {
24 super ();
CHAPTER 5. USING THE JBOSS AOP FRAMEWORK 42

25 }
26

27 public String callSomeAOPClassMethod () {


28 MyAOPClass myaop = new MyAOPClass ();
29 String s = myaop . getMessage ("");
30

31 return s;
32 }
33

34 // The following methods are lifecycle methods used by the framework :


35 public ObjectName preRegister ( MBeanServer preRegister , ObjectName objName )
36 throws Exception {
37 return null ;
38 }
39

40 public void postRegister ( Boolean postRegister ) {}


41 public void preDeregister () throws Exception {}
42 public void postDeregister () {}
43 }

5.3.2 Deployment Units

MBeans are packaged into .sar-files that must contain a directory called META-INF.
This directory contains a deployment descriptor for the MBeans that ends with -ser-
vice.xml. In order to be able to run our AOP-application with the AOP-service on
top, we must deploy the MBean along with it.

The AOP-application should be packaged in a .aop file, which is just an ordinary .jar
archive with a .aop extension. In the .aop file the jboss-aop.xml as described above
is placed within the META-INF directory. The .aop file is then put in a .sar archive with
the MBean facade classes. Figure 5.3 shows how the files are packaged in the .sar
archive.

The process of compiling and packaging the application and service can be automated
with the build tool Ant. See appendix T.2 "Building and deploying with Ant" for the
complete build script we have used.
CHAPTER 5. USING THE JBOSS AOP FRAMEWORK 43

Figure 5.3: The contents of inventory-management.sar

5.4 Built-in services

J2EE application servers should provide a range of services available to EJBs run-
ning in the container. As JBoss 4 aims to provide the same kind of services for ordi-
nary Java classes through the AOP framework, AOP-services corresponding to some
of the EJB-services are under development and available in the Developers Release 3:

Transactions

Security

Remoting

Clustered Remoting

Transactional Locking for synchronizing objects in transactions

TreeCache for replication distributed between multiple nodes in a cluster


CHAPTER 5. USING THE JBOSS AOP FRAMEWORK 44

The basic concepts and steps in the development of AOP-applications described in


this chapter lead to the next phase: actually using the framework for the development
of AOP-services.
Chapter 6

Inventory Management Case


AOP-Services

This chapter will provide a technical walkthrough of the AOP-services that extend
the functionality of the Inventory Management AOP-application (the core applica-
tion) we presented in chapter 4. The AOP-services have been selected with three
things in mind.

They should:

1. Be crosscutting in nature.

2. Provide us with the possibility of using several features of the JBoss AOP frame-
work.

3. Provide solutions to realistic problems found in inventory management sys-


tems.

Based on these conditions we choose three AOP-services.

Handling minimum stock levels: A basic requirement of inventory management


is to control stock levels. Control of inventory stock levels is important for run-
ning an effective business (section 6.1).
This AOP-service requires the use of several features of the AOP framework
and it is crosscutting because a traditional implementation would be scattered
across the core application.

Set a watch on a Product: The ability to add a special watch (or monitor) to a par-
ticular product at runtime. The watch notices and writes to a log whenever the

45
CHAPTER 6. INVENTORY MANAGEMENT CASE AOP-SERVICES 46

stock level of the particular Product is decreased. This can be used for monitor-
ing how many products are sold over a period of time; if the product is hot and
requires a higher minimum stock level.
Because we wanted the watch to be able to be added runtime to particular Pro-
ducts, we use per instance dynamic interceptors, since every product in the
Inventory Management application is an instance of either Product or Product-
Composite (section 6.2).

Logging creation of Products: A logging mechanism that is used to log the cre-
ation of new orders and new reservations. This enables us to make use of
constructor-pointcuts (Section 6.3).

We have chosen to create custom AOP-services that are applied on top of a specific
application. We have not chosen to create AOP-services that are more general like
the ones JBoss AOP offers, eg remoting transactions etc. We find that custom services
are better for illustrating how to use the AOP-framework.

In the following we will go through the different AOP-services. For each service there
will be a short presentation of what the service does, and then a presentation of
the classes and interfaces in the service. Finally there will be a description of the
deployment information in the AOP deployment descriptor for the service.

6.1 Handling of Minimum Stock Levels

The idea is that a given Product has a minimum stock level that is checked against
the actual stock level of the Product. When an Order is processed (createInvoice()
is called), its stock level in the Product instance is decremented with the amount
of products in the reservations. The AOP-service compares the stock level to the
minimum stock level. If the stock level is below minimum a notification is created.

In order to implement the handling of minimum stock levels we need to fulfill the
following requirements:

The interface of a Product must be extended so it is possible to get and set a


minimum stock level on a Product.

The stock levels must be compared to the minimum stock when a product is
reserved. The minimum stock must also be compared to the total number of
reservations made of a particular product.

The Product interface must be extended so it is possible to get and set a total
number of reservations on a Product. The core application has no total number
CHAPTER 6. INVENTORY MANAGEMENT CASE AOP-SERVICES 47

of reservations for a particular Product. Reservations of the same Product in


different Orders is oblivious to the existence of other reservations of the Pro-
duct.

The total number of reservations in Product must be incremented when a reser-


vation is made. It must be decremented when the order containing the reserva-
tion is payed and the stock is decremented.

It must be possible to configure the minimum stock level of products in a prop-


erties file that is read on application startup.

In order to implement stock level control according to the requirements above, we


created the classes below. The classes are all part of the jboss.thesis.inventory.-
service package. The source code for the following classes can be found in appendix
O.

MinimumStock: An interface that defines get and set methods for a minimum stock
integer.

ReservationCounter: An interface that defines methods for incrementing, decre-


menting and getting the total number of reservations (an integer) of a Product.

ProductMixin: A class that implements the MinimumStock and ReservationCounter


interfaces. The mixin class implementation will be added to the ProductImpl
class when the ProductImpl class is loaded by the JVM.

ProductCompositeMixin: A class that implements the MinimumStock and Reserva-


tionCounter interfaces. The mixin class implementation will be added to the
ProductComposite class when the ProductComposite class is loaded.

MinimumStockInterceptor: An interceptor that checks the stock level minus the


total number of reservations on a Product. The result must not be lower than
the minimum stock integer of the Product. If it is, a warning is written to a log.
In practise a notification would be sent to the person responsible for resupplying
stock, or new stock could be ordered automatically.

IncrementReservationInterceptor: An interceptor that increments the total


number of reservations on a Product or ProductComposite.

DecrementreservationInterceptor: An interceptor that decrements the total


number of reservations on a Product or ProductComposite.

ProductConstructionInterceptor: An interceptor that loads minimum stock val-


ues from a properties file and sets them on the products by using the introduced
MinimumStock interface.
CHAPTER 6. INVENTORY MANAGEMENT CASE AOP-SERVICES 48

Since the AOP deployment descriptor, inventory-management-aop.xml1 describes which


classes are advisable and what pointcuts and interceptors are put on which classes,
we added the following in the XML file to configure the minimum stock level AOP-
service:

ProductImpl, ProductComposite and Reservation are marked as advisable.

The four interceptors above are put in and named appropriately.

A method-pointcut is added to the method setQuantity in Reservation. The


MinimumStockInterceptor and the IncrementReservationInterceptor are added
to the interceptor-chain of this pointcut.

method-pointcuts are added to the decreaseStockBy method in both ProductImpl


and ProductComposite. The DecrementReservationInterceptor is added to the
interceptor-chain of these pointcuts.

introduction-pointcuts are added that make the ProductImpl and ProductCom-


posite classes implement the MinimumStock and ReservationCounter interfaces.

A method-pointcut has been added on the method setType in ProductImpl. This


method is called right after a ProductImpl instance has been created. Because
of remoting issues a ProductImpl must be created with an empty constructor,
which means that the Type of a ProductImpl cannot be an argument in the con-
structor and set during instance creation. ProductConstructionInterceptor has
been added to the interceptor-chain of this pointcut.

Since the Unified Modelling Language (UML) does not have a way of modelling as-
pects and crosscutting concerns in a class diagram, we have invented one ourselves.
Figure 6.1 depicts a class diagram with our added syntax for modelling aspects and
crosscutting concerns. It shows introduced interfaces, method-pointcuts, and the in-
terceptors used to take care of minimum stock level control. It also includes the
classes from the core application that are instrumented with the changes from the
mixin class.

AOP Diagram Syntax and Semantics

A box with round edges around a method, field or constructor illustrates a point-
cut. A text in the box describes the pointcut type.

Interceptor chains are illustrated with a heavy frame surrounding the intercep-
tor classes. An arrow connects a pointcut to an interceptor chain.
1 Note that the AOP deployment descriptor file must be renamed to jboss-aop.xml (see appendix
L.1)before deployment.
CHAPTER 6. INVENTORY MANAGEMENT CASE AOP-SERVICES 49

Figure 6.1: Minimum Stock Control AOP-services

Introduced interfaces Interceptor chain


interface interface DecrementReservationInterceptor
MinimumStock ReservationCounter
+getMinimumStock() : int +incrementReservations(in i : int)
+setMinimumStock(in stock : int) +decrementReservations(in i : int)
+getNumberOfReservations() : int

Interceptor chain
ProductConstructionInterceptor

interface
Product

Interceptor chain
ProductComposite ProductImpl MinimumStockInterceptor

Processing order
+decreaseStockBy(in i : int) +decreaseStockBy(in i : int) method-pointcut
+setType(in type : Type) method-pointcut

IncrementReservationInterceptor
Reservation

+setQuantity(in i : int) method-pointcut

Introduced interfaces are surrounded by a heavy, dotted frame.

6.2 Watch on a Product

In order to add a watch on a particular product (per instance monitoring) we created


the following classes:

WatchListInterceptor: The interceptor added to a ProductImpl or ProductCompo-


site instance. It is not possible to add per instance method-, field-, contructor-
or caller-pointcuts. The added interceptor will act as a class-pointcut ie. it
will react to all method invocations or field accesses. Consequently the in-
terceptor must check that the invocation object sent to the interceptor is a
MethodInvocation and furthermore check that the method invoked is decrease-
StockBy. If this is the case it will be written to a log (listing 6.1). The WatchList-
Interceptor is part of the jboss.thesis.inventory.service package.
CHAPTER 6. INVENTORY MANAGEMENT CASE AOP-SERVICES 50

Listing 6.1: WatchListInterceptor


1 InvocationType iType = inv . getType ();
2 if ( iType == InvocationType . METHOD ){
3 MethodInvocation methodInv = ( MethodInvocation ) inv ;
4 Method method = methodInv . method ;
5 if ( method . getName (). equals (" decreaseStockBy ")){
6 Product prod = ( Product ) inv . targetObject ;
7 String decreasedBy = methodInv . arguments [0]. toString ();
8 log . info ( " - - - Begin WatchList Notification - - -" );
9 log . info ( prod . getName () + " was decreased by " + decreasedBy );
10 log . info ( " - - - End WatchList Notification - - -" );
11 }
12 }

AOPService: An Mbean that provides an interface as well as functionality for adding


a watch on a product instance (see section 6.4). It contains the method watch-
Product(..) that adds a new WatchListInterceptor (listing 6.2). AOPService is
part of the jboss.thesis.inventory.model.jmx package

Listing 6.2: The watchProduct(..) method in AOPService


1 public String watchProduct ( long productId ) {
2 Product product = ( Product ) Dispatcher . singleton . getRegistered (
3 " product "+ productId );
4 ClassInstanceAdvisor cia = getAdvisor ( product );
5 cia . appendInterceptor ( new WatchListInterceptor ());
6 StringBuffer sb = new StringBuffer ();
7 ... // build HTML string for web - console output
8 return sb . toString ();
9 }

The only requirement in the AOP deployment descriptor for this service was to mark
the ProductImpl and ProductComposite classes as advisable.

The diagram in figure 6.2 illustrates the relationship between ProductImpl, Product-
Composite and the WatchListInterceptor.
CHAPTER 6. INVENTORY MANAGEMENT CASE AOP-SERVICES 51

Figure 6.2: Product Instance Watch

interface if( method called is decreaseStockBy(..) ){


Product add message to log
}

WatchListInterceptor
ProductComposite ProductImpl Class-pointcut
+invoke() : object
+decreaseStockBy(in i : int) +decreaseStockBy(in i : int)

6.3 Logging of New Orders and Reservations

To implement a logging mechanism for the creation of new orders and reservations,
an interceptor was created:

ModelConstructorLoggingInterceptor An interceptor that logs the creation


of instances of selected classes in the jboss.thesis.inventory.model package.
When an instance of a selected class is created, an entry is written in a log file.
It is stated in the AOP deployment descriptor which classes should be logged at
instance creation.

To setup a logging service for new orders and reservations the following is added to
the AOP deployment descriptor:

The Order and Reservation classes are marked as advisable.

The ModelConstructorLoggingInterceptor

Constructor-pointcuts are added on Reservation and Order. The ModelConstruc-


torLoggingInterceptor is added to the interceptor-chain of both pointcuts.

Figure 6.3 illustrates the relationship between Order, Reservation and the ModelCon-
structorLoggingInterceptor.
CHAPTER 6. INVENTORY MANAGEMENT CASE AOP-SERVICES 52

Figure 6.3: Logging of Order and Reservation Instance Creation

Reservation Order ModelConstructorLoggingInterceptor

+Reservation() : new +Order() : new Constructor-pointcut

6.4 Accessing the AOP-Services

To easily access the AOP-services described above, we have created an MBean called
AOPService. As all other MBeans deployed in JBoss it has an interface, AOPService-
MBean, that dictates the methods available in the web-console (see listing 6.3). Both
the AOPService class and the AOPServiceMBean interface are part of the package:
jboss.thesis.inventory.model.jmx.

Listing 6.3: The AOPServiceMbean Interface


1 public interface AOPServiceMBean extends ServiceMBean {
2 public String listProducts ();
3 public String setMinimumQuantity ( long productid , int minimumStock );
4 public String watchProduct ( long productId );
5 public String unWatchProduct ( long productId );
6 }

At this point we have shown how it is possible to use JBoss-AOP for designing and
implementing AOP-applications. In order to use a framework like this effectively it
is good to know how it works. In other words: it is not sufficient to know how to sit
behind the wheel, you will need to look under the hood as well.

The next part will take you under the hood.


Part III

JBoss AOP Framework Internals

53
Part Overview

The chapters in this part aim at providing a description of the inner workings of the
JBoss AOP framework. The chapters are for those who want to understand how the
framework has been implemented.

The part consists of the following chapters:

Chapter 7 Basic JBoss Functionality. This chapter provides information about


some parts of the JBoss server which are useful for understanding the following
chapters.

Chapter 8 An Example AOP-service. This introduces a simplified version of the


Inventory Management application. It is used as an example in the rest of the
chapters.

Chapter 9 Deployment of AOP-applications. This chapter describes what hap-


pens internally in the JBoss server when an AOP-application or service is de-
ployed how the framework is prepared for the instrumentation of the classes.

Chapter 10 Instrumentation of Classes. This chapter describes in detail how


classes are instrumented while they are loaded by the JVM.

Chapter 11 Initializing an Intrumented Class. In this chapter we describe what


happens just after a class has been loaded and before any instances of the class
are created.

Chapter 12 Using Instrumented Classes. In this chapter we describe in detail


what happens when an instance of an instrumented class is created, and what
happens when methods and fields in the class are used.

Using JBoss-AOP to develop services that support or extend an existing application


will have consequences in regards to implementation details and performance. AOP-
application programmers and AOP-service developers should at least be aware of
these consequences; at best they should understand them fully. For that purpose
we find it necessary to explain how certain parts of the AOP framework have been
implemented.

54
Chapter 7

Basic JBoss Functionality

This chapter will provide a fundamental introduction to the relevant parts of the
JBoss server before we descend into the bowels of the AOP framework.

We will examine:

The main deployment sequence which services that are relevant to the AOP
framework are deployed at startup and how they are deployed.

Scanning for and deploying services while the server is running.

Bytecode manipulation and Javassist.

Class loading in JBoss.

Before explaining about the main deployment sequence, we would like to make a
distinction between two terms:

In the chapters below we talk about system-services (or simply services), which
are not to be confused with AOP-services. The system-services in JBoss are usu-
ally in the form of MBeans and can be anything from the services required by the
J2EE specification, such as transaction support for EJBs (see appendix A.1), to func-
tionality used by JBoss, such as a service that scans the file system for new applica-
tions to deploy. AOP-services are the aspect oriented layer put on top of an existing
AOP-application.

7.1 Main Deployment Sequence

In chapter 5 we described how to deploy an AOP-service on the server. During deploy-


ment of an AOP-service and AOP-application the advisable classes are prepared for

55
CHAPTER 7. BASIC JBOSS FUNCTIONALITY 56

instrumentation. The actual instrumentation of the classes occurs when the classes
are loaded. To get a better understanding of the instrumentation it is necessary to
explain the deployment. We start out by providing a quick overview of what happens
in the main deployment sequence.

In JBoss a deployer is a class that takes care of deploying services and applications
on the server. There are different kinds of deployers for different kind of services
and applications such as MBeans, web applications, EJB applications, and AOP-
applications. Firstly the MainDeployer is set up. The MainDeployer initiates the de-
ployment of all applications and services by finding the right deployer for the given
deployment. Apart from the MainDeployer two other deployers are initially set up
by the server the SARDeployer and the JARDeployer. The SARDeployer takes care
of deploying .sar files and -service.xml files. A -service.xml file is a deployment
descriptor used in .sar files that describes the services contained in the .sar file. A
-service.xml file can also be deployed alone, if the classes it describes are available
on the JBoss servers classpath. The SAR- and JARDeployer need to be initialized
before any other system services, since they are used to deploy other system services.

The main deployment sequence is initiated during the startup of the server, based
on the jboss-service.xml configuration file that specifies which MBeans should be
configured and deployed during startup. Among these services (MBeans) are some
that are essential to the deployment of AOP-services and AOP-applications. The
MainDeployer starts deploying the system services by deploying all the services in
jboss-service.xml.

The first thing the MainDeployer does is to find an appropriate deployer it can delegate
the deployment to. In this case it will be the SARDeployer. This is why the SARDeploy-
er must be started before the MainDeployer starts finding an appropriate deployer for
the XML file. The SARDeployer will parse the XML deployment descriptor and set up
and start all the MBeans specified in the descriptor. Among the MBeans are two that
are relevant to the AOP framework and our description of JBoss below:

AspectDeployer : The deployer for deploying AOP-services and AOP-applications.

URLDeploymentScanner : A service that runs the entire lifetime of the server. It


scans for new services/applications to deploy with a default interval of 5000
milliseconds.

We will explain the scanning process below. The above is a simplified description
of the main deployment process. For a more detailed look at this, see figure H.1 in
appendix H.
CHAPTER 7. BASIC JBOSS FUNCTIONALITY 57

7.2 Scanning for Services

The last service to be deployed is the URLDeploymentScanner. As this is started it


begins to scan for services and applications in the deploy directory of the server.
The URLDeploymentScanner will start a new thread that keeps scanning for new or
changed deployments (.jar/.sar/.zip/.aop or .xml files) until the server is shut down.
The URLDeploymentScanner contains a list of references to URLs that point to services
or applications that have been deployed. If it runs into something that has not yet
been deployed, it will forward the deployment to the MainDeployer. The MainDeployer
will in turn find the proper deployer and delegate the deployment to this. The service
or application will be deployed and the URLDeploymentScanner will add it to the list of
deployed files. For a more detailed look at the scanning process see diagram H.3 in
appendix 20.

7.3 Bytecode Manipulation and Javassist

As previously explained JBoss AOP modifies the bytecode of the classes that are
enhanced via AOP. These changes to the bytecode happen when a class is loaded by
the JVM. In other words the classes are changed to handle pointcuts, interceptors,
introduced interfaces etc. stated in the AOP deployment descriptor.

JBoss uses the open source framework Javassist [13] for bytecode manipulation.
Javassist is a class library for editing bytecode in an easy programmatic way and
provides a mechanism for getting the bytecode of a class and altering it before the
bytecode is loaded by the Java Virtual Machine.

The Javassist library contains abstractions of Java classes, methods, fields and con-
structors that can be used to alter the bytecode and it provides a source level abstrac-
tion for adding bytecode to a class, which means that one does not have to understand
or even see the bytecode of the class. A method can simply added by providing a valid
String of Java source code that Javassist then compiles and inserts into the class.

Without going into details about Javassist there are two core classes that should be
introduced:

CtClass: Represents a .class that is being manipulated. With this you can add
methods, change methods, add fields, change constructors etc. The changes
will not take effect before you write the CtClass either to bytecode in memory,
or in a .class file.

ClassPool: Can read bytecode from a .class file and provide a CtClass object. The
ClassPool can be considered a container for CtClass objects. It provides the
CHAPTER 7. BASIC JBOSS FUNCTIONALITY 58

methods for writing a CtClass object to bytecode.

A description of the core classes in Javassist can be found in appendix G.

When we describe the instrumentation of classes in chapter 10 we illustrate the class


changes as source code that has been added to and/or changed in the class. As ex-
plained above, this is not how the instrumentation really works the Java bytecode
is actually manipulated directly. The reason why we use the source code abstraction
is that it in our opinion provides a better way of communicating the changes in a
class.

7.4 Classloading

At the time of writing there are certain caveats to the way JBoss uses bytecode ma-
nipulation.

JBoss can only make bytecode changes to classes loaded by JBosss own class loader.
Classes loaded by a different class loader cannot be changed. In effect this means
that all classes loaded by the Tomcat Servlet/JSP container in JBoss (Servlets and
JSP pages) cannot be extended with JBoss AOP functionality. This is because Tom-
cat (and other thirdparty Servlet/JSP containers) uses its own class loaders that are
independent of the JBoss class loader. These independent class loaders do not have
the capabilities of starting the instrumentation process.

There has been talk about changing this behaviour in Jboss, so perhaps this is an
issue that will be resolved before the final release of JBoss 4.

This chapter has provided an introduction to subjects that are needed to understand
the description of the implementation of the AOP framework. The next chapter
presents a small two-class application that will be used as an example through chap-
ters 9-12.
Chapter 8

An Example AOP-service

In order to describe what happens to an AOP-application that is deployed, instru-


mented and used in the AOP framework, we have decided to use a small example.
By using an example we will be able to compare the involved classes before and after
deployment and instrumentation.

8.1 A model of Interaction Between Calling and Called


Class

Figure 8.1: Model of Calling - Called Class Interaction

E()

Uninstrumented
Caller
Class

return

Before we go into details with example, we would like to present a model of what
happens to an instrumented class. The model focuses on the interaction between a
calling class and a called class. This interaction will change when a class has been
instrumented. A normal interaction between two classes will appear as in figure
8.1. An event E will be initiated from a calling class to an uninstrumented class,

59
CHAPTER 8. AN EXAMPLE AOP-SERVICE 60

and a result will be returned. In this case the concept of an event refers to either a
constructor call, a field access or a method call.

If a class has been instrumented the interaction between classes will appear as in
figure 8.2. Every event E will be delegated to an advisor. An advisor is a class that
acts as a placeholder for interceptor chains for a particular class. The advisor will
initiate the process of going through the interceptor chain as described in section
5.1.2. The last interceptor in the chain will make sure that E is processed (the code
from the uninstrumented original class is run) and that it returns the result back
to the advisor. The advisor will return the result to the instrumented class which
will return it to the calling class. The instrumentation process will make changes to
a class so it can support the process outlined in the model. We will use this model
throughout the description of the instrumentation process.

Figure 8.2: Model of Calling - Called Class Interaction After Instrumentation

E() Invoke( E ) Invoke( E )


E Interceptor
Stack

Instrumented invokeNext()
Caller Advisor
Class invokeNext()
invokeNext()
invokeNext()
return return invokeNext()

retu
rn

8.2 The Example

The example is inspired by our inventory management case, however it will not be
used in full, as this would be too comprehensive. The example consists of only two
classes, an AOP deployment descriptor and a simple logging interceptor. In addi-
tion the example will use the introduced MinimumStock interface and corresponding
ProductMixin from the Inventory Management application.

8.2.1 ProductImpl

This is a simplified version of the ProductImpl class in the inventory management


system. It contains only two fields, a constructor and a method (listing 8.1). This
CHAPTER 8. AN EXAMPLE AOP-SERVICE 61

class is marked as advisable in the AOP deployment descriptor. The ProductImpl


class can also be found in appendix K.1.

Listing 8.1: Example: ProductImpl Source Code


1 package jboss . thesis . inventory . model ;
2

3 public class ProductImpl {


4 private long id ;
5 public String name ;
6

7 public ProductImpl (){


8 // do nothing
9 }
10

11 public long getID (){


12 return id ;
13 }
14 }

8.2.2 ClassUsingProduct

This simple class is created for the purpose of this example, and it is used to illustrate
changes made to a class using an advisable class, but the class itself is not marked as
advisable in the AOP deployment descriptor. The source code in listing 8.2 illustrates
the use of a ProductImpl inside this class. The ClassUsingProduct source can also be
found in appendix K.3.

Listing 8.2: Example: ClassUsingProduct Source Code


1 package jboss . thesis . inventory . model ;
2

3 public class ClassUsingProduct {


4 ProductImpl product ;
5

6 public ClassUsingProduct () {
7 product = new ProductImpl (); // call constructor
8 product . name = " TestProduct "; // access field directly
9 }
10

11 public long getProductID () {


12 return product . getID (); // call method
13 }
14

15 public String getProductName () {


16 return product . name ; // access field directly
CHAPTER 8. AN EXAMPLE AOP-SERVICE 62

17 }
18 }

8.2.3 LoggingInterceptor

This LoggingInterceptor is a simple interceptor that writes the name of the opera-
tion performed to a log-file. No source code is provided for this as it is only here to
illustrate how an interceptor is used by the framework and not how it is implemented.

8.2.4 AOP Deployment Descriptor

This is the XML-file that describes the pointcuts and interceptors added to the exam-
ple ProductImpl. The AOP deployment descriptor contains the LoggingInterceptor, a
method-pointcut and a caller-pointcut that has the interceptor and an introduction of
the MinimumStock interface (listing 8.3). The deployment descriptor can also be found
in appendix K.5.

Listing 8.3: Example: deployment descriptor


1 <aop >
2 < advisable class =" jboss . thesis . inventory . model . ProductImpl " / >
3

4 < interceptor name =" Logger " singleton =" true "
5 class =" jboss . thesis . inventory . service . logging . LoggingInterceptor ">
6 </ interceptor >
7

8 <method - pointcut class =" jboss . thesis . inventory . model . ProductImpl "
9 methodName =" getID ">
10 < interceptors >
11 < interceptor - ref name =" Logger "/ >
12 </ interceptors >
13 </ method - pointcut >
14

15 < introduction - pointcut class =" jboss . thesis . inventory . model . ProductImpl ">
16 < mixin >
17 < interfaces > jboss . thesis . inventory . service . MinimumStock </ interfaces >
18 <class > jboss . thesis . inventory . service . ProductMixin </ class >
19 < construction >
20 new jboss . thesis . inventory . service . ProductMixin ( this , 20 , 0 )
21 </ construction >
22 </ mixin >
23 </ introduction - pointcut >
24

25 <caller - pointcut
26 class =" jboss . thesis . inventory . model . ClassUsingProduct "
CHAPTER 8. AN EXAMPLE AOP-SERVICE 63

27 calledClass =" jboss . thesis . inventory . model . ProductImpl "


28 calledMethodName =" getID "
29 withinMethodName =" getProductID ">
30 < interceptors >
31 < interceptor - ref name =" Logger "/ >
32 </ interceptors >
33 </ caller - pointcut >
34 </aop >

When we have described the instrumentation process it will be possible to compare


the source code of the example ProductImpl and ClassUsingProduct classes with de-
compiled versions of the instrumented classes.

8.3 From Deployment to Instance Creation at a Glance

ClassUsingProduct and ProductImpl will both go through a process of deployment,


loading, instrumentation and instance creation, and in the following four chapters
we will go through the steps of this process, and use the model in 8.1 as a roadmap
for the reader.
CHAPTER 8. AN EXAMPLE AOP-SERVICE 64

1. A class that is part of an AOP-application is deployed


8.1 From Deployment
and the process begins. Both the ProductImpl and
to Instance Creation
ClassUsingProduct will go through this process, though
the implications on the ClassUsingProduct will be dif-
Uninstrumented
1
Class
ferent as this class is not marked as advisable.

Deploy 2. Information from the AOP deployment descriptor


2 Deploying is processed and then moved into tables in the
AspectManager, a class that manages AOP elements
3 Deployed like pointcuts, interceptors, metadata etc. for all
classes before they are instrumented.

4 Loading
3. The class is waiting to be loaded by the JVM.

4. The class is needed by the JVM and so it must be


5 Instrumenting loaded. The classloader finds the class-file and begins
to load the class.
6 Instrumented
5. The class is instrumented following these steps:

7 Loaded
Create an advisor for the current Class.
Move information on current class from the
8 Initialising Instrumented Class
AspectManager to the advisor.
Add generic methods to delegate field access, con-
9 Creating Class Instance
structor calls and method calls to the advisor.
Make changes to accommodate delegation to the
advisor.

6. Instrumentation is finished.

7. The class has been loaded by the JVM.

8. Information from tables in the Advisor is put into more specific tables in the
Advisor that represent each field, method and constructor.

9. An instance is created together with an advisor specific to that instance.

The next chapter will present the deployment of AOP-applications.


Chapter 9

Deployment of AOP-applications

This chapter will go through the deploying of an AOP-application, covering the two
highlighted boxes in the figure on the right.

9.1 Presentation of the Deployment Process Uninstrumented


Class
Deploy

Deploying
When an AOP-application is deployed a number of things happen:
Deployed

The server must activate the correct deployer for the applica- Loading

tion (see section 9.2).


Instrumenting

The deployment descriptors must be parsed, and deployment Instrumented

information expressed in XML must be turned into object-


Loaded

representations, which are easier to work with in Java. (see


Initialising Instrumented Class
section 9.2)
Creating Class Instance

The framework must be prepared for instrumenting the


classes in the application. (see section 9.3)

9.2 Handling .aop Files

As explained in chapter 5, classes that should be AOP instrumented are packaged


into an .aop file with interceptors, mixin-classes and an AOP deployment descrip-
tor. The AspectDeployer handles the deployment of any such AOP-service or AOP-
application.

When the MainDeployer finds an .aop or -aop.xml file to deploy, it will delegate the de-
ployment to the AspectDeployer. The AspectDeployer will parse the AOP deployment

65
CHAPTER 9. DEPLOYMENT OF AOP-APPLICATIONS 66

descriptor (jboss-aop.xml) and let an AspectXmlLoader create object representations


of the contents and put these into tables in the AspectManager. Figure 9.1 illustrates
the deployment of .aop files in a sequence diagram.

Figure 9.1: AOP deployment sequence

MainDeployer AspectDeployer AspectXmlLoader AspectManager

init( info )
parseDocument( info )
The parameter info contains
information about the current
create( info ) deployment

deployXML(info.url)
loadURL()

deployXML(document, info.url)

deployMethodPointcut(element)

loadInterceptorsElement(element)

MethodPointcut

<new>

addInterceptorPointcut

9.3 Tables in the AspectManager

The AspectManager singleton class is at the core of the deployment and instrumenta-
tion process. It holds information about all advisable classes, interceptors, pointcuts
etc. in a number of tables. These are the tables populated by the AspectXmlLoader,
and will be used when a class in an AOP-application is loaded and instrumented. The
core tables are displayed in table 9.2.
CHAPTER 9. DEPLOYMENT OF AOP-APPLICATIONS 67

Table 9.2: Tables in the AspectManager

Table Name Key Value


Pointcut- Regular expression that Instances of FieldPointcut,
table matches the fully qualified ConstructorPointcut,
name of the class or classes MethodPointcut,
that the pointcut is used on, InterceptorPointcut.
the metadata is applied to or Instances of ClassMetaData and
that are declared advisable. SimpleMetaData.
Instances of jboss.org.aop.Ad-
visable for each class marked
as advisable in the deployment
descriptor.
All types added to this table ul-
timately inherit from Advisable
(Except Advisable itself).
Caller- Regular expression that Instances of CallerPointcut.
pointcut- matches the fully qualified
table name of the class or classes
that are stated as calling
class in the pointcut.
Introduction- Regular expression that Instances of Introduction-
pointcut- matches the fully qualified Pointcut.
table name of the class or classes
that the interface(s) should
be introduced to.
Interceptor- The name of the interceptor Objects that implements the
table stated in the deployment InterceptorFactory interface.
descriptor. This will be instances of default
factory classes if one was not
stated in the descriptor.
Advisor- A string with the fully Instances of ClassAdvisor. This
table qualified name of the class is the advisor, which calls are del-
that the advisor belongs to. egated to when a class is instru-
mented. These are not created
during deployment but during
instrumentation (10.2.1).

All classes mentioned in table 9.2 belongs to the org.jboss.aop package.


CHAPTER 9. DEPLOYMENT OF AOP-APPLICATIONS 68

9.4 Deployment of the Example

When the AOP elements stated in the AOP deployment descriptor (listing 8.3) are
deployed, the following is put into the tables in the AspectManager (see table 9.2):

An instance of Advisable will be added to the Pointcuts-table with the string


"jboss.thesis.inventory.model.ProductImpl" as key.

An instance of MethodPointcut will be added to the Pointcuts-table with the


string "jboss.thesis.inventory.model.ProductImpl" as key.

An instance of CallerPointcut will be added to the Caller-pointcut-table with


the string "jboss.thesis.inventory.model.ClassUsingProduct" as key.

An instance of IntroductionPointcut will be added to the Introduction-pointcut-


table with the string "jboss.thesis.inventory.model.ProductImpl" as key.

An instance of SingletonInterceptorFactory will be added to the Interceptor-


table with the string "Logger" as key.

These will all come into use when the ProductImpl and ClassUsingProduct are loaded.
For more details on the classes mentioned above see appendix D.

In the next chapter the deployed application will be instrumented during the class
loading process.
Chapter 10

Instrumentation of Classes

This chapter will cover the 4 steps highlighted on the figure on the right: the loading
and instrumentation of classes with an emphasis on the instrumentation process.

10.1 An Overview of the Instrumentation Process

When an AOP-application has been deployed, the advisable classes Uninstrumented


Class
are ready for instrumentation. This is a fairly complex sequence of Deploy

operations. We outline the process but will leave out some details Deploying

and try to stick to the core details so as not to make it overly com- Deployed

plicated. For a more detailed look at the instrumentation see figure


Loading
I.1 and the six referenced subdiagrams in appendix I.
Instrumenting
The instrumentation of classes happens at loadtime ie when the
Instrumented
classes are loaded into the JVM. The classloader initiates the pro-
cess by calling the translate() method on the AspectManager. We Loaded

will not strictly follow the chronology of the instrumentation pro- Initialising Instrumented Class

cess here. Instead we will use our example and break up the in- Creating Class Instance

strumentation process into smaller units of changes made to the


ProductImpl and ClassUsingProduct.

The units are:

The creation and adding of advisors to ProductImpl.

The moving of information about ProductImpl pointcuts, interceptors and intro-


ductions from the AspectManager to the advisor.

The adding of generic methods that take care of delegating field access, instance
creation and method calls to the advisor.

69
CHAPTER 10. INSTRUMENTATION OF CLASSES 70

Changes to accommodate delegation to the advisor.

Changes to handle mixin classes.

Changes to the ClassUsingProduct.

10.2 Creating Advisors in ProductImpl

Two references to two different advisors is added to the ProductImpl class:

An Advisor field which references the subclass ClassAdvisor.

An InstanceAdvisor field which references a ClassInstanceAdvisor


(InstanceAdvisor is a java-interface).

These two classes constitutes the advisor from the model in figure 8.2. Listing 10.1
shows the code that is added to the instrumented ProductImpl that has to do with
advisors. The complete instrumented ProductImpl class can be found in appendix
K.2.

Listing 10.1: Advisors in a ProductImpl


1 private static final Class aop$class$WithoutAdvisement ;
2 private static final Advisor aop$classAdvisor$WithoutAdvisement;
3 protected transient ClassInstanceAdvisor _instanceAdvisor ;
4

5 static
6 {
7 aop$class$WithoutAdvisement
8 = Class . forName (" jboss . thesis . inventory . model . ProductImpl ");
9 aop$classAdvisor$WithoutAdvisement
10 = AspectManager . instance (). getAdvisor ( aop$class$WithoutAdvisement );
11 }
12

13 public Advisor _getAdvisor (){


14 return aop$classAdvisor$WithoutAdvisement;
15 }
16

17 public InstanceAdvisor _getInstanceAdvisor (){


18 return _instanceAdvisor ;
19 }
20

21 public void _setInstanceAdvisor ( InstanceAdvisor instanceadvisor ){


22 _instanceAdvisor = ( ClassInstanceAdvisor ) instanceadvisor ;
23 }
CHAPTER 10. INSTRUMENTATION OF CLASSES 71

10.2.1 The ClassAdvisor

A ClassAdvisor is a class that holds information about pointcuts, interceptors, meta-


data etc. The ClassAdvisor is also responsible for initiating the process of running
through interceptor chains for method-, field-, constructor- and caller-pointcuts.

Every instrumented class has a corresponding ClassAdvisor. All instances of an in-


strumented class share the same ClassAdvisor. A static reference to an Advisor is
added to ProductImpl.

Furthermore a static reference to a Class object for the class being instrumented is
added. This will be used to acquire the ClassAdvisor from the AspectManager when
the static initialiser block in ProductImpl is running. In chapter 11 we will go into
detail about what happens when the static block is run.

10.2.2 The ClassInstanceAdvisor

A ClassInstanceAdvisor holds information about interceptors for a particular in-


stance of the class being instrumented. It provides functionality for adding inter-
ceptors to instances. The ClassInstanceAdvisor has two lists of interceptors one for
interceptors inserted in the beginning of the chain and one for interceptors appended
to the chain. See section 5.1.3 on page 34 for details on dynamic and per instance
interceptors. The ClassInstanceAdvisor also has support for per instance metadata.

For every instance of an instrumented class there is an instance of a ClassInstance-


Advisor so an InstanceAdvisor instance field is added to the ProductImpl class. This
field will be initialized with a reference to a new instance of ClassInstanceAdvisor
when an instance of ProductImpl is created.

10.2.3 Initializing the ClassAdvisor

In the beginning of the instrumentation process the ClassAdvisor instance that will
be referenced in ProductImpl will be created and added to the Advisor-table (table
9.2). It should be noted that if the ProductImpl class has previously been loaded but
subsequently unloaded by the garbage collector a new ClassAdvisor instance will not
be created. Instead it will be retrieved from the Advisor-table. This means that the
instrumentation will only occur once per deployment. If an instrumented class needs
to have its bytecode changed it must be redeployed.
CHAPTER 10. INSTRUMENTATION OF CLASSES 72

10.3 Moving Information from the AspectManager to the


Advisor

When the ClassAdvisor instance has been created it is time to move object repre-
sentations of pointcuts and metadata from the AspectManager into the ClassAdvisor.
Like the AspectManager, the ClassAdvisor contains a number of tables that hold these
object representations of AOP-elements. The main tables in the ClassAdvisor are
listed in table 10.2.

Table 10.2: Tables in the ClassAdvisor

Table Name Key Value


Advisor-pointcut- Index value Instances of FieldPointcut,
table ConstructorPointcut, MethodPointcut,
InterceptorPointcut.
Advisor-caller- Calling Instances of CallerPointcut.
pointcut-table method hash
value
Advisor- Index value Instances of IntroductionPointcut.
introduction-
pointcut-table
Advisor-metadata- Index value Instances of ClassMetaData and SimpleMetaData.
table
Method- Method hash Objects that implements the InterceptorFactory
interceptor-table value interface. This will be instances of default fac-
tory classes if one was not stated in the descrip-
tor.
Caller-interceptor- Calling Objects that implements the InterceptorFactory
table method hash interface. This will be instances of default fac-
value tory classes if one was not stated in the descrip-
tor.
Field-interceptor- Index value Objects that implements the InterceptorFactory
table interface. This will be instances of default fac-
tory classes if one was not stated in the descrip-
tor.
Constructor- Index value Objects that implements the InterceptorFactory
interceptor-table interface. This will be instances of default fac-
tory classes if one was not stated in the descrip-
tor.

All classes mentioned in table 9.2 belongs to the org.jboss.aop package.

The framework will go through the Pointcut-table, Caller-pointcut-table and Introduc-


CHAPTER 10. INSTRUMENTATION OF CLASSES 73

tion-pointcut-table in the AspectManager. It will match the AOP-elements in the ta-


bles the class that is being instrumented. If a match is found it will add the AOP-
element to a corresponding table in the ClassAdvisor.

In our example the following is moved from the AspectManager to the ClassAdvisor of
the ProductImpl :

The MethodPointcut instance that was put into the Pointcut-table in section 9.4
is moved to the Advisor-pointcut-table.

The IntroductionPointcut instance is moved from the Introduction-pointcut-


table to the Advisor-introduction-pointcut-table.

Interceptors will not be moved until the static block in ProductImpl is running. The
caller-pointcut we added belongs to ClassUsingProduct. We will go into detail about
caller-pointcuts in section 10.7.3.

10.4 Adding Generic Delegation Methods

In the model of interaction between a calling and a called class in figure 8.2 we il-
lustrated how instance creation, method calls and field access are delegated to an
advisor. The framework adds a number of generic methods that take care of the dele-
gation to the ClassAdvisor. Listing 10.2 shows the format of such a generic delegation
method:

Listing 10.2: Generic Delegation Method Format


1 private Object _added_m$0 ( Object obj [] , long value )
2 throws Throwable {
3 return (( ClassAdvisor ) _getAdvisor ()). invokeMethod ( this , value , obj );
4 }

In some cases the generic methods will be declared static, eg when delegating static
method calls. The different elements of the method requires explanation:

_added_m$0: The name of the generic delegation method is automatically created


by the framework. For each added generic method, the number will be incre-
mented. The next added method would then be called _added_m$1.

Object obj[]: In the case of method and constructor delegation the object array
contains the arguments to the invoked method or constructor. In the case of
field access the first entry in the array contains a reference to the object in
CHAPTER 10. INSTRUMENTATION OF CLASSES 74

which the field is read. For field write the second entry in the array contains
the new value which should be written to the field.

value: In the case of method delegation this is a hash value of the called method.
In the case of constructor calls and field access delegation, this is an int repre-
senting the position of the field or constructor inside the class.

((ClassAdvisor)_getAdvisor()).invokeMethod: This is the method called in


the ClassAdvisor. It may also be a static method.

Table 10.3 illustrates what generic delegation methods the instrumented class can
contain for each kind of delegation event. Events can be: instance method calls, static
method calls, constructor calls, field read, field write or mixin introduced methods.
Furthermore the table shows which methods are called on the ClassAdvisor and with
what arguments.
CHAPTER 10. INSTRUMENTATION OF CLASSES 75

Table 10.3: Generic Delegation Methods

Added generic Method called on ClassAdvisor from generic dele-


delegation methods gation methods
Method to delegate instance invokeMethod(this, Long methodHash, Object[] args)
method calls
this: Reference to the object the method is invoked on
methodHash: Hashvalue of the called method
args: Arguments of the method

Method to delegate static invokeMethod(null, Long methodHash, Object[] args)


method calls
null: It is a static method so there is no object to invoke on
methodHash: Hashvalue of the called method
args: Arguments of the method

Method to delegate constructor static trapConstructor(Object[] args, Advisor classAdvisor, int


calls index)

args: Arguments to the constructor


classAdvisor: ClassAdvisor for the constructed class
index: An index value of the specific constructor in the class

Method to delegate field read static trapRead(Object target, int index, Advisor classAdvisor)
access
target: The instance the field must be read from
index: An index value of the specified field
classAdvisor: ClassAdvisor for the accessed class

Method to delegate Field write static trapWrite(Object target, int index, Object value, Advisor
access classAdvisor)

target: The instance the field must be written to


index: An index value of the specified field
value: The value to write
classAdvisor: ClassAdvisor for the accessed class

Method to delegate method invokeMethod(InstanceAdvisor adv, Object mixinClass, Long methodHash,


calls to mixin introduced Object[] args)
methods
adv: InstanceAdvisor of the called class
mixinClass: Reference to the mixin class that implements the introduced
method
methodHash: Hashvalue of the introduced method
args: Arguments of the method
CHAPTER 10. INSTRUMENTATION OF CLASSES 76

10.5 Making Changes to Accomodate Delegation to the


Advisor

In section 10.4 we described how methods were added to our ProductImpl in order
to delegate field access, constructor calls and method calls to the ClassAdvisor. The
framework must also change the ProductImpl to make sure that these newly added
methods in ClassUsingProduct are actually used instead of the original methods.

We outline these changes from three different angles:

1. Method changes.

2. Field changes.

3. Constructor changes.

10.5.1 Method Changes

To allow interception of method calls, two changes are made for each method in
ProductImpl. Changes that facilitate the use of the newly added generic delegation
methods:

1. All original methods static as well as instance will be renamed according to


this algorithm:

(a) Prepend method name with fully qualified class name, separating elements
with $.
(b) Append the suffix: $WithoutAdvisement

Following this algorithm the method getID() in the class jboss.thesis.inven-


tory.model.ProductImpl gets the name:
jboss$thesis$inventory$model$ProductImpl$getID$WithoutAdvisement().

2. For every method in the class a new method will be created that wraps one of the
generic delegation methods. The original methods were renamed with the al-
gorithm in the previous step, so the original method names are no longer used.
As this would obviously break the functionality of the application (Product-
Impl.getID() no longer exists) it is necessary to give the wrapper methods cre-
ated in this step the names of the original methods. Listing 10.3 shows an
example of what such a wrapper looks like.
CHAPTER 10. INSTRUMENTATION OF CLASSES 77

Listing 10.3: Wrapped Generic Instance Delegation Method


1 public void getID () {
2 if (! _instanceAdvisor . hasAspects ()) {
3 // call original method
4 jboss$thesis$inventory$model$ProductImpl$getID$WithoutAdvisement();
5 return ;
6 }
7 // call generic delegation method
8 _added_m$0 ( new Object [0] , 0 x12a7e75bde237f9fL );
9 }

The hasAspects() method in line 4 will return true if a pointcut has been applied to
a method in the ProductImpl.

10.5.2 Field Changes

In order to be able to intercept field access in the ProductImpl class, field access will
be changed to static method calls, that invokes one of the generic delegation methods
added in section 10.4. The framework must add two static methods for every field
in an advisable class. One for reading a field, and one for writing to a field. The
methods wrap calls to the generic field read and write delegation methods that were
previously added (table 10.3). Listing 10.4 shows examples of both read and write
methods:

Listing 10.4: Field Read and Write Access Methods


1 private static String name_r_$WithoutAdvisement ( Object obj ) {
2 return ( String ) _added_m$1 ( new Object [] { obj } , 3);
3 }
4

5 private static void name_w_$WithoutAdvisement ( Object obj , String s ) {


6 _added_m$2 ( new Object [] { obj , s } , 3);
7 }

In section 10.7.1 it will become obvious why the methods are necessary when we show
in detail how these field access methods are used in the ClassUsingProduct.

10.5.3 Constructor Changes

In order to be able to intercept instance creation of the ProductImpl class, constructor


calls will be replaced with static method calls. This requires that for each constructor
CHAPTER 10. INSTRUMENTATION OF CLASSES 78

in ProductImpl a static method is created that calls the generic constructor delegation
method added in section 10.4. Since there is only one constructor in ProductImpl, only
one method will be added.

Listing 10.5 shows the method added to ProductImpl.

Listing 10.5: Constructor Method


1 public static ProductImpl ProductImpl_new_$WithoutAdvisement()
2 throws InvocationTargetException {
3 return ( ProductImpl ) _added_m$3 ( new Object [0] , 1);
4 }

In section 10.7.2 a more detailed account of how these constructor methods are used
will be provided.

10.6 Making Changes to Handle Mixin Classes

The framework must change the ProductImpl in order to handle the introduced in-
terface MinimumStock. As stated in the AOP deployment descriptor the introduced
methods should be implemented in the ProductMixin class. A number of changes are
made to introduce the interface and use the mixin class in ProductImpl:

1. The framework will add implements MinimumStock to the ProductImpl class dec-
laration.

2. A private field with the mixin class ProductMixin as type is added (listing 10.6).

Listing 10.6: Private Mixin Field


1 private transient ProductMixin
2 _jboss$thesis$inventory$service$ProductMixin$aop$mixin;

3. Initialization of the mixin field is added to the constructor in ProductImpl (list-


ing 10.7). Initialization will be made with the constructor that was added inside
the mixin-tag in the AOP deployment descriptor (Listing 8.3).

Listing 10.7: Mixin Field Initialization


1 _jboss$thesis$inventory$service$ProductMixin$aop$mixin
2 = new ProductMixin ( this , 20 , 0);
CHAPTER 10. INSTRUMENTATION OF CLASSES 79

4. The framework will add the introduced methods to ProductImpl. The methods
will wrap calls to the generic mixin delegation method that was added. Listing
10.8 shows an example of an introduced method.

Listing 10.8: Introduced Method


1 public void setMinimumStock ( int i ) {
2 _added_m$4 ( new Object [] { new Integer (i )} , 0 xdb773c5ac4ef6981L );
3 }

Note that the mixin delegation method took a reference to the mixin instance as
an argument (table 10.3). This means that the call to an introduced method will
be delegated to the ClassAdvisor, and the ClassAdvisor will further delegate the
call to the mixin class when the interceptor chain has been processed.

10.6.1 Handling Introduced Interfaces With an Interceptor

Introduced interfaces can also be handled by an interceptor instead of a mixin class


(section 5.1.5). In this case the introduced methods will also be added to the instru-
mented class. They will wrap a call to the generic instance delegation method that
will delegate the call to the ClassAdvisor. An interceptor must be created in which
the invoke(..) method acts as the body of the introduced method. The invoke(..)
method must return an object of the same type as the introduced methods return
value instead of calling invokeNext() on the invocation object. Primitive types must
be wrapped in their object equivalents. To map the interceptor implementation of
an introduced method a method-pointcut must be added in the AOP deployment de-
scriptor. This method-pointcut must reference the implementing interceptor. The
introduction-pointcut alone will result in runtime reflection exceptions if no method-
pointcuts are specified.

10.7 Making Changes to ClassUsingProduct

Even though the ClassUsingProduct has not been marked as advisable, a number of
changes are still made to it. These changes are made when the ClassUsingProduct
is loaded and instrumented, not when the ProductImpl is loaded and instrumented.
The changes are:

1. To allow interception of field access in ProductImpl, ClassUsingProduct is changed


to use the static field read and write methods that was previously added in sec-
tion 10.5.2.
CHAPTER 10. INSTRUMENTATION OF CLASSES 80

2. To allow interception of constructor calls in ProductImpl, ClassUsingProduct is


changed to use the static method that was previously added in 10.5.3

3. Change and add code to handle caller-pointcuts.

The complete instrumented ClassUsingProduct class can be viewed in appendix K.4.

The changes mentioned above will be described in the sections 10.7.1, 10.7.2 and
10.7.3 below.

10.7.1 Changes made to Handle Field Access

All classes that use direct field access to an advisable class will have this replaced
with static method calls. In the ClassUsingProduct this means that:

Listing 10.9: Normal Field Access


1 // p is a reference to an instance of ProductImpl
2 p. name = " Soundcard "; // write operation
3 String pr = p. name ; // read operation

will be replaced by:

Listing 10.10: Instrumented Field Access


1 // p is a reference to an instance of ProductImpl
2

3 ProductImpl . name_w_$WithoutAdvisement (p , " Soundcard "); // write operation


4 String pr = ProductImpl . name_r_$WithoutAdvisement (p ); // read operation

10.7.2 Changes made to Handle Constructor Calls

As with the field access, the code for creating instances of advisable classes will also
be replaced by static method calls in ClassUsingProduct. This means that:
CHAPTER 10. INSTRUMENTATION OF CLASSES 81

Listing 10.11: Normal Instance Creation


1 ProductImpl p = new ProductImpl ();

will be replaced by:

Listing 10.12: Instrumented Instance Creation


1 ProductImpl p = Product . Product_new_$WithoutAdvisement();

Note that both field access and constructor calls inside the ProductImpl class itself
are changed in the same manner. This happens when the ProductImpl is loaded and
instrumented.

10.7.3 Changes Made to Handle Caller-pointcuts

ClassUsingProduct must be changed to handle the caller-pointcut that runs the Log-
ger interceptor. The interceptor runs when the method getID() in ProductImpl is
called inside the getProductID() method in ClassUsingProduct.

When you consider that an interceptor-chain needs to be attached to the calling


method in the non-advisable class (like ClassUsingProduct), it is easy to see that
even if a class is not marked as advisable in the AOP deployment descriptor, it will
still need to be instrumented if it acts as caller in a caller pointcut.

The changes made to ClassUsingProduct are not very different from those needed by
an advisable class. A reference to a Class instance and a ClassAdvisor must be made
as is done for advisable classes in section 10.2.1. However, no ClassInstanceAdvisor
reference will be added. The object representation of the caller-pointcut in the Caller-
pointcut-table in the AspectManager must be moved to the Advisor-caller-pointcut-
table in the ClassAdvisor.

The instrumentation of the non-advisable class follows this algorithm:

1. Search the ClassAdvisor for caller pointcuts where the non-advisable class (the
ClassUsingProduct) is the calling class.

2. For every matching pointcut:

(a) Find all methods that must be monitored for calls to a method in a class.
(b) In each method replace the method call with a call to invokeCaller(..) in
the ClassAdvisor.
CHAPTER 10. INSTRUMENTATION OF CLASSES 82

In the ClassUsingProduct, this results in:

Listing 10.13: Caller Pointcut Invocation I


1 // p is an instance of a ProductImpl
2 public String getProductID () {
3 return p. getID ();
4 }

will be replaced by:

Listing 10.14: Caller Pointcut Invocation II


1 // p is an instance of a ProductImpl
2 public String getProductID () {
3 return ( String )(( ClassAdvisor ) aop$classAdvisor$WithoutAdvisement)
4 . invokeCaller ( -0 x1768de1f041461e9L , " jboss . thesis . experiments . ProductImpl "
5 , 0 x53e0822d3e3724dfL , p , new Object [0]);
6 }

The variable aop$classAdvisor$WithoutAdvisement was set in the static initialized


block of the class (listing 10.1).

The arguments in the invokeCaller(..) method require explanation:

1. A hash value representing the calling method.

2. The name of the class that contains the called method.

3. A hash value representing the called method.

4. A reference to the object on which the method should be called.

5. An Object array with the arguments to the called method.

Caller-pointcut changes in a non-advisable class will only occur if a class has a caller-
pointcut applied to it in the AOP deployment descriptor. Hence it is not possible to
apply a caller-pointcut dynamically to a class that has not had one applied before the
class was loaded an instrumented.

10.8 Non-instrumentable Classes

There are a number of classes that are not allowed to be instrumented by the frame-
work. When the AspectManager begins the instrumentation of a class it will start by
CHAPTER 10. INSTRUMENTATION OF CLASSES 83

checking if the class is part of a package that figures in a list of non-instrumentable


packages. This list is hard-coded into the AspectManager and it contains system pack-
ages specific to JBoss and Java. The package name of the class is matched against
the list in figure 10.1. If the class package name matches a name from the list or a
subpackage name of a name on the list, then the class is non-instrumentable.

If the class is non-instrumentable, the translate() method will return null, and the
class will not be instrumented but loaded unchanged by the class loader.

Figure 10.1: Non-instrumentable Packages

org.jboss.aop javassist org.jboss.util


org.apache.crimson org.apache.xalan org.apache.xml
org.apache.xpath org.ietf org.omg
org.w3c org.xml.sax sunw
java javax com.sun

It is impossible to intercept anything from classes in the packages in figure 10.1.

10.9 Finishing the Instrumentation Process

When all changes have been made to the ProductImpl (or ClassUsingProduct) the
translate() method in the AspectManager returns the modified bytecode of the class
to the classloader. The classloader will load the class and the static block in the
class will run. Before we go into detail with what happens when this static block is
executed we present a class diagram (figure 10.2) that shows the implications of the
instrumentation on the ProductImpl class.

Decompiled versions of the instrumented ProductImpl and ClassUsingProduct exam-


ple classes can be viewed in appendix K.

Now the AOP-application has been deployed, instrumented and loaded. The next
chapter describes the initialization of static blocks in an instrumented class.
CHAPTER 10. INSTRUMENTATION OF CLASSES 84

Figure 10.2: ProductImpl Class Diagram After Instrumentation

ProductImpl
Class
-aop$class$WithoutAdvisement : Class
-aop$classAdvisor$WithoutAdvisement : ClassAdvisor 0..1 1
#_instanceAdvisor : ClassInstanceAdvisor
+_getAdvisor() : ClassAdvisor 0..1
+_getInstanceAdvisor() : InstanceAdvisor
+_setInstanceAdvisor() 1
ClassAdvisor interface
Interceptor
1 1 0..1 0..*

0..*
0..*
ProductMixin ClassInstanceAdvisor

1 0..1
Chapter 11

Initializing an Instrumented
Class

In Java static blocks are run just after the loading of classes, and this is utilized by
the AOP framework for the initilization of the instrumented classes. This chapter
will describe this process.

11.1 Overview

Immediately after the instrumented ProductImpl has been Uninstrumented


Class
Deploy

loaded by the JVM the static block will be executed, thus ini- Deploying

tializing the added ClassAdvisor field by calling getAdvisor() on Deployed

the AspectManager with the Class instance for the ProductImpl


Loading

as an argument.
Instrumenting
The getAdvisor() method will find the ClassAdvisor that was
Instrumented
created and put into the Advisor-table in the AspectManager
during instrumentation. When the ClassAdvisor is found, the Loaded

getAdvisor() method will fill the interceptor tables in the Class- Initialising Instrumented Class

Advisor with interceptor-chains. Creating Class Instance

Four tables in the ClassAdvisor must be filled with interceptor chains (see table 10.2):

1. The Method-interceptor-table.

2. The Field-interceptor-table.

3. The Constructor-interceptor-table.

4. The Caller-interceptor-table.

85
CHAPTER 11. INITIALIZING AN INSTRUMENTED CLASS 86

How each of these are filled will be described in sections 11.2, 11.3, 11.4 and 11.5.

In order to fill the Method-, Field- and Constructor-interceptor tables in the ClassAd-
visor the Advisor-pointcut-table (see table 10.2) will be searched for method-, field-
and constructor-pointcuts matching the ProductImpl class. Each pointcut has a num-
ber of interceptors, and these interceptors will be put into the appropriate interceptor
tables.

11.2 Method Interceptors

For each method in an advisable class a MethodInfo object is created and added to
the Method-interceptor-table. A MethodInfo object holds information about a given
method in an instrumented class. Most importantly it contains a list of interceptors
for the particular method. The method-pointcuts found in the Advisor-pointcut-table
are checked for referenced interceptors and these are added to the list in the Method-
Info. In addition, interceptors referenced from class-pointcuts are added to the list.
A MethodTailInterceptor is added at the end of the list. The MethodTailInterceptor
will make sure the intercepted method is called (reflectively) and the resulting value
will be returned.

In ProductImpl one MethodInfo object will be added to the Method-interceptor-table,


because there is only one method in ProductImpl. The interceptor-chain in this Met-
hodInfo object will contain two interceptors the LoggingInterceptor that we added
and a MethodTailInterceptor that calls the
jboss$thesis$inventory$model$ProductImpl$getID$WithoutAdvisement() method (see
section 10.5.1).

11.3 Field Interceptors

For each field an Interceptor array is added to the Field-interceptor-table in the


ClassAdvisor. This array ins the interceptor chain of the given field. Field point-
cuts found in the Advisor-pointcut-table are checked for referenced interceptors and
these are added to the Interceptor array. Interceptors that are referenced from class-
pointcuts are added to the array as well. A FieldTailInterceptor is added at the end
of this array. The FieldTailInterceptor will make sure the intercepted field access
is completed (reflectively) and the resulting value is either returned or set.

In ProductImpl two Interceptor arrays will be added to the Field-interceptor-table


in the ClassAdvisor one for each field. Each Interceptor array will contain one
interceptor a FieldTailInterceptor.
CHAPTER 11. INITIALIZING AN INSTRUMENTED CLASS 87

11.4 Constructor Interceptors

For each constructor an Interceptor array is added to the Constructor-interceptor-


table in the ClassAdvisor. Constructor pointcuts found in the Advisor-pointcut-table
are checked for referenced interceptors and these are added to the Interceptor array.
Interceptors referenced from class-pointcuts are added to the array as well. A Con-
structorTailInterceptor is added at the end of this array. The ConstructorTail-
Interceptor will make sure that an instance is created (reflectively) by calling the
original constructor.

In ProductImpl one Interceptor array will be added to the Constructor-interceptor-


table. The Interceptor array will contain one interceptor a ConstructorTailInter-
ceptor.

11.5 Caller Interceptors

As the ClassUsingProduct has a caller-pointcut applied to it, it will also contain a


static block that will run immediately after the class has been loaded by the JVM,
initializing the class. The Caller-interceptor-table in the ClassAdvisor of the Class-
UsingProduct is filled with a comprehensive structure of tables:

For each calling method in a calling class, tables of classes called are put into
the Caller-interceptor-table.

The tables of called classes are filled with tables of called methods.

The tables of called methods are filled with Interceptor arrays the interceptor
chains..

Figure 11.1 displays an example of the table structure in the Caller-interceptor-table.

Caller pointcuts found in the Advisor-caller-pointcut-table (table 10.2) are checked


for referenced interceptors and these are added to a corresponding Interceptor array
in the Caller-interceptor-table structure. At the end of each array a CallerTailInter-
ceptor is added. The CallerTailInterceptor will make sure the intercepted method
is invoked (reflectively) and that the resulting value will be returned.

In ClassUsingProduct one Interceptor array will be added to the Caller-interceptor-


table structure. The Interceptor array will contain one interceptor a CallerTail-
Interceptor, which calls the getID() method reflectively.

At this point the AOP-application and AOP-services are deployed, loaded, instru-
mented and initialized. The next chapter will show what is going on when the appli-
cation is actually running.
CHAPTER 11. INITIALIZING AN INSTRUMENTED CLASS 88

Figure 11.1: Caller-interceptor-table Structure

Calling Methods in
Calling Class

methodA() methodB() methodC()

Called Classes Called Classes Called Classes

Class X Class X Class Y Class Z Class Y Class Z


Class Y

Called Methods in Called Methods in Called Methods in Called Methods in Called Methods in Called Methods in Called Methods in
Class X Class Y Class X Class Y Class Z Class Y Class Z

doP() doQ() doQ() doR() doP() doP() doQ() doP() doP() doQ() doR() doP()
Interceptor Array

Interceptor Array

Interceptor Array

Interceptor Array

Interceptor Array

Interceptor Array
Interceptor Array

Interceptor Array

Interceptor Array

Interceptor Array

Interceptor Array

Interceptor Array
Chapter 12

Using Instrumented Classes

We have now explained how an AOP-application is deployed, how Uninstrumented


Class
classes are instrumented at load time, and what happens when Deploy

instrumented classes are initialized. This chapter describes what Deploying

happens when classes in AOP-applications are used. The descrip- Deployed

tion is broken into four subsections: Loading

1. Instantiating an instrumented class (section 12.1). Instrumenting

Instrumented

2. Accessing fields in an instrumented class (section 12.2).


Loaded

3. Intercepting methods with a method-pointcut (section 12.3). Initialising Instrumented Class

Creating Class Instance


4. Intercepting methods with a caller-pointcut (section 12.4).

12.1 Instantiating an Instrumented Class

As explained in section 10.7.2 all constructor calls are replaced by calls to static meth-
ods added to the instrumented class. The sequence diagram in figure 12.1 illustrates
the process from a call to such a static method in ProductImpl until a new instance is
returned. The numbers in the list below refer to the numbers in figure 12.1.

1. The call to the added static constructor-method is delegated to the generic con-
structor delegation method.

2. The call is further delegated to the static trapConstructor() method in the


ClassAdvisor with the arguments: (a) An Object

89
CHAPTER 12. USING INSTRUMENTED CLASSES 90

Figure 12.1: Instantiating an Instrumented Class

product : ProductImpl advisor : ClassAdvisor constructorInterceptors : ArrayList interceptor : ConstructorTailInterceptor

ProductImpl_new_$WithoutAdvisement()

1
_added_m$3( new Object[0], 0 )()

trapConstructor( Object[], ClassAdvisor, int )


2

invokeNew( Object[], int )

get( int )

returns Interceptor[]

3
new ConstructorInvocation( Interceptor[] ) invocation : ConstructorInvocation

set different values on the invocation object


invokeNext()
4

invoke( invocation )

Constructor.newInstance()
6

return a ProductImpl instance


returns a ProductImpl instance

returns a ProductImpl instance

Creates a java.lang.reflect.Constructor
object and calls newInstance( args[] ) on it.
(The args[] is empty) and thereby running
ProductImpl's real constructor.

with constructor arguments, (b) the ClassAdvisor instance for the instrumented
class and (c) an integer representing the called constructor.

3. All interceptors for this particular constructor are found in the Constructor-
interceptor-table (table 10.2). A ConstructorInvocation instance is created that
contains the interceptors (see appendix F for class descriptions).

4. invokeNext() is called on the ConstructorInvocation instance, thus starting the


processing of the interceptor chain.

5. (Not pictured in the diagram) Each interceptor in the chain calls invokeNext()
on the invocation instance which in turn calls invoke on the next interceptor in
the chain. This way the entire chain will be processed.

6. The last interceptor in the list will be a ConstructorTailInterceptor. The Con-


CHAPTER 12. USING INSTRUMENTED CLASSES 91

structorTailInterceptor will call the original constructor of the instrumented


class via reflection and return this instead of calling invokeNext().

The constructor initializes the InstanceAdvisor reference with a new ClassInstance-


Advisor instance. It will also initialize any mixin classes that the instrumented class
is dependent on.

12.2 Accessing Fields in an Instrumented Class

In section 10.7.1 we explained that field access was replaced by static method calls.
The way field access is handled is very similar to the way instance creation is handled.
A sequence diagram of this process would be very similar to the diagram for instance
creation (figure 12.1). The main difference is that the invocation object will be a
FieldInvocation and that a FieldTailInterceptor will be at the end of the chain.
The FieldTailInterceptor will take care of reading or setting a value on the field via
reflection. For a more detailed look at the interception of instance creation and field
access see diagram J.2 in appendix J.

12.3 Intercepting Methods with a Method-pointcut

The sequence diagram in figure 12.2 illustrates what happens when the method
getID() is invoked and intercepted in a ProductImpl instance. The numbers in the
list below refer to the numbers in figure 12.2:

1. The call to getID() is delegated to the generic invoke method with an Object
array with the arguments to getID() and the hash value of the called method.
The generic invoke method delegates the call by calling invokeMethod on the
ClassAdvisor.

2. The first thing the ClassAdvisor will do is to get the ClassInstanceAdvisor of


the particular instance that getID was called on.

3. Then the MethodInfo object associated with the called method is retrieved from
the Method-interceptor-table (table 10.2).

4. A list of interceptors is retrieved (info.aspects) from the MethodInfo object. By


calling getInterceptors on the ClassInstanceAdvisor all inserted per-instance
interceptors are inserted in the beginning of the list and all per-instance ap-
pended interceptors are added just before the last interceptor in the list.
CHAPTER 12. USING INSTRUMENTED CLASSES 92

Figure 12.2: Invoking the Method getID() on an Instrumented Class.

_instanceAdvisor : ClassInstan
product : ProductImpl advisor : ClassAdvisor info : MethodInfo
ceAdvisor
getID()

The Object array represent the


_added_m$0(new Object[0], methodHash) arguments of a method. As getID
1 has no arguments the array is
empty. From here this array is
((ClassAdvisor)_getAdvisor()).invokeMethod(this, methodHash, args)
referenced as args.

_getInstanceAdvisor() 2
_instanceAdvisor

invokeMethod(_instanceAdvisor, product, methodHash, args)


3
info = methodInterceptors.get(methodHash)
4
getInterceptors(info.aspects)

Interceptor[] aspects
new MethodInvocation(aspects) invocation : MethodInvocation

set different values in the invocation object

methodHash = methodHash
5 arguments = args

targetObject = product

method = info.advisedMethod
Interceptor invokeNext()

invoke(invocation)
invokeNext() 6
result of invoke to the original method

result : Object

result : Object

5. A MethodInvocation object (see appendix F) containing the list of interceptors is


created. A number of values are set on the invocation object and invokeNext is
called on the MethodInvocation, which in turn calls invoke() on the first inter-
ceptor in the list, thus starting the processing of the interceptor chain.

6. The interceptor chain is processed by having all but the last interceptor in the
chain call invokeNext on the invocation object, which in turn calls invoke() on
the next interceptor in the chain.

The last interceptor in the list is a MethodTailInterceptor. The MethodTailIntercep-


tor instance holds a reference to a java.lang.reflect.Method instance. The Method
instance represents the original renamed getID() method:
CHAPTER 12. USING INSTRUMENTED CLASSES 93

jboss$thesis$inventory$model$ProductImpl$getID$WithoutAdvisement()
When invoke() is called on the MethodTailInterceptor it will call invoke() on the
Method instance with the following arguments: (a)An Object array of arguments to
the renamed getID() method, and (b) the reference to the instance the method should
be invoked on (ProductImpl). This process is illustrated in figure 12.3.

Figure 12.3: The MethodTailInterceptor

interceptor : MethodTailInterc
invocation MethodInvocation eptor method : Method

invoke( invocation )

invoke( invocation.targetObject, invocation.arguments )

Object result

Object result

When explaining instance creation and field access interception we left out the Class-
InstanceAdvisor. The interceptor lists in the ClassInstanceAdvisor are also ap-
pended and inserted into the interceptor chain for instance creation and field access
just as they are for interception of methods.

12.4 Intercepting Methods with a Caller-pointcut

Interception of methods from a caller-pointcut perspective is slightly different from


instance creation, field access and method interception as the calling class will have
its own ClassAdvisor and no ClassInstanceAdvisor. The numbers in the list below
refer to the numbers in figure 12.4, illustrating the process.

1. When ProductImpl.getID() is called in the ClassUsingProduct, the call is imme-


diately delegated to the ClassAdvisor of ClassUsingProduct by calling invoke-
Caller() on the ClassAdvisor. The method invokeCaller takes five arguments:

callingHash a hash value of the calling method.


A String with the fully qualified name of the class containing the called
method.
CHAPTER 12. USING INSTRUMENTED CLASSES 94

Figure 12.4: Interception of the method getID() in ProductImpl with a caller-pointcut

productImplsAdvisor :
caller : ProductUsingClass callersAdvisor : ClassAdvisor invocation : CallerInvocation CallerTailInterceptor Method product : ProductImpl ClassAdvisor

product.getID()
1 The callingHash is used as key to
invokeCaller(callingHash, "jboss.thesis.experiments.ProductImpl"
, calledHash, p, new Object[0]) retrieve a table of called classes. The
Interceptor[] aspects string name of the called class is used
as key to retrieve a table of called
new (aspects) methods from the table of called
classes. The calledHash is used to Each interceptor will call
set some values retrieve an interceptor chain from the invokeNext() on the
table of called methods. 2 invocation object which in
invokeNext() 3 turn will call invoke on the
call invoke on the first interceptor in the chain (aspects) next interceptor. The last
interceptor will be a
invoke(invocation)
CallerTailInterceptor.
4
invoke(product,invocation.arguments)

getID()

invokeMethod(..)

result Object

result Object

result Object

result Object

result Object

result Object

result ((Long)Object).longValue()

calledHash a hash value of the called method.


A reference to the instance on which the method should be called.
An Object array of arguments to the called method.

2. The interceptor chain matching the caller-pointcut is extracted from the Caller-
interceptor-table structure (section 11.5).

3. A CallerInvocation instance is created and the invokeNext() method is called


on it, thus starting the processing of the interceptor chain.

4. The last interceptor in the chain is a CallerTailInterceptor. It contains a


java.lang.reflect.Method instance representing the method to call. The invoke
method is called on the Method instance with the following arguments: (a) The
Object array of method arguments to getID(), and (b) the reference to the in-
stance the method should be invoked on (ProductImpl).

If the called class has any method pointcuts, the process will then continue as illus-
trated in figure 12.2.

Until now this report has been rich on information and especially the previous five
chapters have provided an exhaustive detailed description on the internal processes
in JBoss-AOP. The next part is devoted to digestion in the form of conclusions on our
work, wrapping up the report.
Part IV

Critique, Conclusions and


Evaluation

95
Part Overview

The chapters in this part contains an evaluation and critique of the JBoss AOP frame-
work and also the conclusions we have come to since we started work on our thesis.

The part consists of the following chapters:

Chapter 13 Reflections and Conclusion on JBoss 4 This chapter is an evalu-


ation and critique of the JBoss AOP framework. We present the various issues
we have with the framework and give some suggestions for improvements.

Chapter 14 Evaluation of the Process In this chapter we conclude and reflect


on our own working process spanning the past six months, decisions made and
lessons learned.

96
Chapter 13

Reflections and Conclusion on


JBoss 4

The preceding chapters have provided the reader with an understanding of the JBoss
AOP framework on two levels:

What is the JBoss AOP framework, what does it offer and how can it be used to
implement aspect oriented applications and services.

How does the JBoss AOP framework work how is it implemented.

To further help developers of AOP-services and AOP-applications to understand the


implications of the design choices they make, we will here reflect on JBoss and the
AOP framework presented in the preceding chapters.

This discussion can be considered as an evaluation and critique of the JBoss AOP
framework. We will cover the following subjects:

1. The separation of AOP-services from AOP-applications (section 13.1).

2. The use of the supplied AOP remoting service (section 13.2).

3. Performance (section 13.4).

4. Usability (section 13.3).

5. Improvement Suggestions (section 13.5).

6. Conclusions on JBoss 4 (section 13.6).

97
CHAPTER 13. REFLECTIONS AND CONCLUSION ON JBOSS 4 98

13.1 Separating AOP-services from AOP-applications

Ideally an AOP-application and its AOP-service should be kept apart because it al-
lows two different deployments and also allows the development of AOP-services to be
independent of the development of AOP-applications. However, it turns out that this
separation can sometimes be difficult to achieve. At load-time an AOP-application
can implicitly be dependent on classes normally packaged together with the AOP-
service, and therefore the AOP-application cannot always be oblivious of the AOP-
service. In these cases the AOP-application has a tight coupling to the AOP-service.

An area of tight coupling is in the introduction of interfaces. When using introduc-


tions, the instrumentation of a class where introduced methods must be added is a
problem. We illustrate the problem of keeping the AOP-application separate from
the AOP-service when using introductions, with a small example:

Imagine an AOP-application that contains the class A that will have interface B intro-
duced. The AOP deployment descriptor for the AOP-application has only one entry,
which states that A is advisable. The introduction-pointcut for addding B to A is placed
in the AOP deployment descriptor for the AOP-service along with interceptors and
various helper classes for the service.

In this situation the following would happen:

1. The AOP-application with class A is deployed.

2. The JVM loads class A because it is referenced by some other class that is loaded.
Class A is advisable and gets instrumented which results in a ClassAdvisor for
A being stored in the AspectManager.

3. The AOP-service is now deployed along with its introduction-pointcut that in-
troduces interface B to A.

4. The AOP framework tries to extend A with B, but discovers that A already has
a ClassAdvisor and stops. A class in the AOP-service that uses A never realizes
that A was not extended with B.

5. RuntimeException: A class calls a method from B on A; but A never had the B


interface introduced so the method does not exist in A.

This scenario can be avoided entirely if the AOP-service is packaged as part of the
AOP-application. If this is not desirable, the introduction can be packaged together
with the AOP-application, separating it from the rest of the AOP-service. But every
change to introductions in the AOP-application will then require the AOP-application
to be redeployed.
CHAPTER 13. REFLECTIONS AND CONCLUSION ON JBOSS 4 99

Until the day JBoss allows runtime changing of bytecode, there will be potential
problems in separating the AOP-service form the AOP-application.

13.2 Using the Supplied AOP Remoting Service

JBoss 4 is currently a developers release meaning that it is a release, which is


mainly suitable for developers anxious to get a preview of the coming version. De-
spite the fact that AOP remoting is part of this very early release, and therefore not
finished in any way, there are still a few comments to be made.

13.2.1 AOP Framework Error

The documentation available for the AOP framework is slightly too optimistic. We
have not been able to make AOP remoting work without modifying the ClassAd-
visor class. If a method with arguments was called on a remote object, the ar-
guments of the called methods were not passed on once the method call reached
the server-side object. We found that adding this line: nextInvocation.arguments
= methodInvocation.arguments; to the dynamicInvoke method made it work.

This small error is what you can expect from an unfinished product and is not some-
thing we hold against JBoss. Given the problems and frustration we have experi-
enced we hope that these mistakes will be removed before the final release.

13.2.2 Difficult to Use Remoting

Once we got the remoting part to work, we should have been able to make the objects
in the inventory management application work remotely very quickly. This should
have been easy, but turned out to be a hard nut to crack. Again this has to do with
AOP remoting being unfinished, but only partially.

One of the biggest problems with AOP remoting is the dynamic downloading of classes
from the server to the client. In systems such as Java RMI this process is almost in-
visible: An object is declared remote or not and the RMI subsystem automatically
figures out whether a remote reference to the object should be created and sent to
the client, or if a copy of the object should be serialized to the client. This invisibil-
ity makes it very easy to use Java RMI. In JBoss AOP remoting it is not quite as
invisible.

Note that the JBoss AOP remoting is not the same as the remoting facilities already
existing in JBoss. AOP remoting is JBoss remoting implemented using the AOP
framework. It is implemented as a general AOP-service.
CHAPTER 13. REFLECTIONS AND CONCLUSION ON JBOSS 4 100

Whenever a new object that should also be remote is created, a proxy for the object
must also be created. The proxy can be bound in the JNDI tree where clients can look
it up and the original object must be registered with the AOP Dispatcher object.

Creating the proxy cannot be done in the constructor of the object as the proxy itself
creates an instance of the original object on construction. This would result in a stack
overflow error due to a cyclic reference.

In our application we have made a factory, the InventoryFactory instead. So instead


of creating an object directly via the new operator we just use the factory if the in-
stance is created from the client. Easy as it sounds, it has its limitations on the ease
of use. For instance the setup makes it difficult to create a method that returns a
collection of objects used both by remote and local classes: The remote class needs
proxies for the remote objects and a local class needs the original objects. Further-
more the problem remains what to do with object creation locally since the factory
create-methods return proxy objects and not the original objects.

These difficulties may sound trivial, but they are not. In some cases we have not been
able to figure out if a local or remote object was needed and in other cases a proxy
seemed to work when only the original object should have worked. There is no doubt
in our minds that an abstraction like the one made in Java RMI would enhance the
usability of JBoss AOP remoting considerably.

13.2.3 Default Constructors are a Must

One of the requirements of AOP remoting is that the remote object has a default
empty constructor. We find this somewhat restrictive. It is not a serious problem,
as it is an issue that can easily be worked around by the use of a factory, but it is
nonetheless an annoyance.

13.2.4 Equal Methods in Remote Objects

Lastly, we have found that the equals method does not work as expected when an
object is both remote and not. In our first implementation of the equals method in
ProductImpl we had a line that checked if the calling classs type was equal to the
arguments (obj) type:

if( !this.getClass().equals( obj.getClass() ) ){


return false;
}
CHAPTER 13. REFLECTIONS AND CONCLUSION ON JBOSS 4 101

Our implementation of the equals method checks if the IDs of the ProductImpls are
equal. In non-remote objects this method call would return true if the instances
were of the same type and had the same ID. But in AOP remoting it may return
false, even though the instances have the same ID, because it is possible that the
calling instance and the argument are not of the same type. This happens when the
equals method is run on the original object with a proxy as its argument. In that case
the calling instance is an instance of the class jboss.thesis.inventory.model.Pro-
ductImpl, and the argument obj is an instance of org.jboss.aop.proxy$jboss.the-
sis.inventory.model.ProductImpl which extends ProductImpl. In the end we found
an implementation that can match proxies with original objects (see the source code
of ProductImpl in appendix M.6).

Overall we found using AOP remoting a difficult task. Some of our difficulties were
due to the unfinished status of the framework, some could be due to lacking features
or to poor design. It is difficult to tell if lacking features (such as an abstraction
over the dynamic downloading of classes) are because of the unfinished framework,
or simply because it is a feature that was never planned for JBoss remoting.

Since we are not into all details of JBoss remoting, it can be that we have insufficient
knowledge to use it properly, but the fact remains: We found it prohibitively difficult
to work with.

13.3 Usability Issues The Cognitive Burden

The JBoss AOP framework is very flexible and AOP-services and AOP-applications
can be customized in almost every possible way. But the flexibility comes with a price:
it is not quite the simple silverbullet-solution promised by the JBoss Group.

13.3.1 Too Many Combinations

An AOP-application can consist of classes + pointcuts + interceptors + metadata.

Pointcuts match a number of classes via regular expressions.

Interceptors can be applied per instance or per class in a scope ranging from
thread to cluster and implement different functionality.

Metadata can also be applied dynamically with the same scope as the intercep-
tors.

These three variables can result in a vast number of combinations and hence applica-
tion behaviour. Even though it seems simple it can be quite a burden to grasp just the
CHAPTER 13. REFLECTIONS AND CONCLUSION ON JBOSS 4 102

fact that a pointcut can match several classes and methods. It is easy to forget this
when developing an interceptor for a particular pointcut when writing the regular
expressions that matches the classes and methods. Add to this that the interceptor
can be applied to instances or per thread. The staggering number of combinations,
possibilities and sources of errors makes it quite difficult to use the framework. We
feel that it would probably be better to postpone the implementation of some features
until they were actually needed by someone, and thus lifting some of the cognitive
burden from the developers.

13.3.2 Semantic Inconsistencies

It is not sufficient that a complex framework such as JBoss AOP is efficient and
flexible. It should also be possible to understand. People must be able to grasp the
concepts one by one. At first they can understand it through a very abstract model,
like dividing the concerns into vertical and horizontal, and then, later on, in more
detail. The details become clearer when getting deeper into the framework and the
abstract model slowly turns more and more concrete, until people understand enough
to use their knowledge at the required level AOP-application programmers and
AOP-service developers require two different levels of insight.

This descendance into detail can be hindered by inconsistency in the mapping be-
tween the abstract and the concrete. We have found a few of these inconsistencies:

class-pointcut vs. interceptor-pointcut: For the most general type of point-


cut the class-pointcut it is possible to use both class-pointcut and inter-
ceptor-pointcut in the AOP deployment descriptor, and in the API the class is
called InterceptorPointcut. The term interceptor-pointcut does not make any
sense. We would recommend that the term interceptor-pointcut is removed and
the class InterceptorPointcut is renamed to ClassPointcut.

An introduction-pointcut is not really a pointcut: The way it is implemented,


introductions are handled much like the other kind of pointcuts, but seen from
the starters point of view, it is about dynamic implementation of interfaces, and
not interception of method calls. We recommend renaming the introduction-
pointcut to introduction to stress the fact that it is in fact not a pointcut.

We find it confusing that the mapping between the layers of abstraction are not con-
sistent. The examples above are not grave problems, but they serve as an example of
what we believe is an important area in framework design: making it consistent and
easy to understand.
CHAPTER 13. REFLECTIONS AND CONCLUSION ON JBOSS 4 103

13.3.3 An Abundance of Features

JBoss has provided an impressive framework when it comes to flexibility and dynam-
ics. There are a vast number of different approaches, wheels to turn and buttons to
push. But there is a lack of focus in the current version; it looks like JBoss AOP
wants to do everything at once.

When we approached the task of implementing AOP-services for the Inventory Man-
agement application we found it difficult to choose what AOP-elements to use. We
could have used metadata instead of introduction to add minimum stock control. We
could have loaded initial minimum stock values from custom XML-elements in the
interceptor element in the AOP deployment descriptor. These are just a few examples
of things we could have done and considered doing differently.

Choices are a good thing. They provide an opportunity to implement and adjust an
AOP-service to very specific needs. However, we feel that JBoss will have to provide
better guidelines for the intended use of the different AOP-elements, their benefits
and drawbacks. Often the design situation will provide suggestions as to which spe-
cific elements to use, but a guide of Best Practices would be a beneficial tool for
developers of AOP-services.

13.4 Performance of JBoss AOP

An evaluation of a framework like this must also take into consideration: what is
the cost of abstraction and flexibility when it comes to performance? In this section
we will present the results of a range of performance tests run on the JBoss AOP
framework.

In order to find out how the AOP framework performs we have conducted a series of
performance tests. (see appendix R)

As we have seen, the instrumentation process modifies not only the advisable classes,
but also un-advisable classes that create instances of or access fields in advisable
classes. Also un-advisable classes that are callers in caller-pointcuts are modified.
So in the tests we have found four scenarios relevant to test:

1. The called class is not advisable

2. The called class is marked as advisable, but it has no associated pointcuts/in-


terceptors

3. The called class has constructor-, method-, and field-pointcuts with a shared
interceptor that does nothing but call invokeNext() on the invocation object
CHAPTER 13. REFLECTIONS AND CONCLUSION ON JBOSS 4 104

4. The same as 3, but running in a HotSpot JVM using the -server switch.

In these scenarios we look at the differences between an uninstrumented implemen-


tation and an instrumented implementation. The types of operations we measured
were:

Construction.

Construction with field set.

Method calls.

Field access.

13.4.1 Test Results

The tests have been run from within an MBean (appendix R.1). All tests have first
been run 107 times to make sure that the HotSpot compiler has compiled the bytecode
into native machine code. Then the code is run another 107 times wrapped in a timer.
Furthermore all tests have been run twice. The first time a test is run the classes
have not been instrumented. This is designated as Unadvised in the tables below.
On the second run classes have been instrumented. This is designated as Advised
in the tables below. The ratio is the relative difference between the advised and
unadvised test runs. The results have been converted into time spent per method call,
per constructor call or per field access measured in nanoseconds (called ns/access
below). The tests were run on an IBM X23 866MhZ laptop with 392 MB ram. The
JBoss server was started with the default configuration, 128 allocated MB of RAM
and without the -server switch except where otherwise stated.

Test: Advised Classes with no Added Interceptors or Pointcuts

Figure 13.1: Advised with no added interceptors or pointcuts

Advised (ns/access) Unadvised (ns/access) Ratio


Empty constructor 7952.4 135.2 58.819
Constructor w. field set 9936.2 131.2 75.733
Method 41 33.1 1.238
Field access 2168.1 6 361.35

From the numbers in figure 13.1 we can see that:


CHAPTER 13. REFLECTIONS AND CONCLUSION ON JBOSS 4 105

Making a class advisable is costly. There is a significant overhead without any


extension of functionality.

Method calls are both absolutely and relatively the least affected operations.

Field access and constructor calls are relatively the most expensive.

Field access seems to be extremely expensive compared to the operation performed


in an uninstrumented context. The reason is that it is changed from a simple field-
access to a static method call. When the static method is called it results in 12 suc-
ceeding method calls the last one a reflective call from a FieldTailInterceptor to a
get-method (described in section 12.2).

Constructor calls are modified in a similar way (see 10.5.3), and the number of oper-
ations added are also similar (see figure 12.1 in section 12.1).

Test: Advised Classes with Added Interceptors and Pointcuts

Adding an interceptor to a method in a class increases the performance hit by 45.8%,


which is expected. But all of the methods in a class, where an intercepted method
exists, are affected. This requires some explanation: The ClassAdvisor has a boolean
that marks whether or not one of the methods in the class has a pointcut and thus
whether or not it is necessary to traverse an interceptor chain. When an advised
class is loaded the interceptor chain tables for each method, field and constructor
are created. When an interceptor is added to anyone of these chains the boolean
doesHaveAspects in the ClassAdvisor is set to true. Now, if a method is called, that
does not have interceptors associated with it, the interceptor chain for this method
will be traversed and the only interceptor (a MethodTailInterceptor) in the chain
will call the intercepted method reflectively. This seems to be quite ineffective and
improvements could be made by setting this property per method, constructor, and
field and not only per class.

Figure 13.2: Advised with added interceptors and pointcuts

Advised (ns/access) Unadvised (ns/access) Ratio


Empty constructor 7534.8 131.2 57.429
Constructor w. field set 9308.4 124.2 74.946
Method 1293.9 31 41.738
Intercepted method 1419.1 31 45.777
Field access 1858.6 6 309.766
CHAPTER 13. REFLECTIONS AND CONCLUSION ON JBOSS 4 106

Test: Advised Classes with Added Interceptors and Pointcuts Using the
-server Switch on the JVM

Figure 13.3: Advised with added interceptors and pointcuts, in the Server HotSpot
VM

Advised (ns/access) Unadvised (ns/access) Ratio


Empty constructor 5247.6 136.2 38.528
Constructor w. field set 6406.2 137.2 46.692
Method 901.3 2 450.65
Intercepted method 933.3 2 466.65
Field access 1658.4 0.351 4724.786

In figure 13.3 we have used the -server command line switch when starting JBoss,
which selects the Java HotSpot Server VM mode as opposed to the default HotSpot
Client VM mode. The HotSpot VM optimizes hotspots places in the code that
are very busy. The Client mode is designed for fast start-up and low memory foot-
print. The Server mode gives higher operation speed by doing more aggressive code
optimization and dynamic profiling it is a slow starter but designed to host appli-
cations that run for a long time.

Here the HotSpot VM in server mode has done a good job optimizing the uninstru-
mented code, but it has not been able to optimize the instrumented/intercepted ver-
sion because of the reflective method calls.

13.4.2 Filters

There is a yet unimplemented feature, that does not work in this release. It is possible
to reduce performance hit by setting up filters like "field-filter: none", which means
that no fields must be intercepted. This removes the rather aggressive interception-
activity on field access if you do not need it.

It should be possible to apply filters for Field, Method and Constructor.

The feature is documented but not implemented, so we have not been able to make it
work. Therefore we could not measure the difference it presumably would make.
CHAPTER 13. REFLECTIONS AND CONCLUSION ON JBOSS 4 107

13.5 Improvement Suggestions

Even though the JBoss 4 AOP framework is still under development and most likely
will improve in many ways, we still feel that a few suggestions for improvements are
in place.

13.5.1 Support for Multiple Mixin Classes

In Developers Release 3, the version of JBoss 4 we have analyzed, multiple mixin


classes per class are not supported. This is most likely an error that has not yet been
handled. Because of limitations in the Javassist construct used to add generic dele-
gation methods to an advisable class, calls to introduced methods are all delegated
to the first mixin class stated in the AOP deployment descriptor. This will cause er-
rors in any introduced methods for which another mixin class was stated in the AOP
deployment descriptor.

The Javassist construct that adds a generic mixin delegation method uses a string
with the method signature and method body to add the method. When the framework
attempts to add a second mixin delegation method it will appear to Javassist as if the
framework is trying to add a method with the same signature (mixinInvoke(..)) once
more. However this time the method body will be slightly different (a different mixin
reference in the call to the advisor). Adding the method will fail because of name
clashing and the delegation method will not be added. Hence the first delegation
method added will be used by all introduced methods. We offer two slightly different
solutions to this problem:

Either: Give the method used to make the generic mixin invoke method a
unique name for each mixin class so the name clashing will not occur.

Or: Send the mixin reference as an argument to the generic mixin delegation
method from where it is called ie from the introduced method.

The last option is probably the most flexible solution.

13.5.2 Pointcuts on Inherited Methods

The JBoss AOP framework does not provide the possibility of applying pointcuts on
methods inherited from non-advisable classes. With a little work this feature can be
added to the AOP framework. Figure 13.4 illustrates how this can be implemented.
On the left side we have the situation before the classes have been instrumented.
A class C has a method callA() that calls the method a() on a B instance. A is un-
advisable and B is advisable. The method a() in B is inherited from A.
CHAPTER 13. REFLECTIONS AND CONCLUSION ON JBOSS 4 108

Figure 13.4: Pointcuts on Inherited Methods

Before Instrumentation After Instrumentation


C callA(){ C callA(){
A a = new B(); A a = new B();
a.a(); ((B)a).a_Advised(); //Changed during instrumentation
+callA() +callA()
} }

A A a_Advised(){
//delegate call to advisor that
//in the end will call a()
+a() +a()
}

B B

+a_Advised()

The following changes must be made in order to apply pointcuts on inherited methods
in B:

A method (a_Advised()) must be added to B. This method will delegate the call
to the ClassAdvisor which in turn will call a() on the B instance the call that
was originally intended.

The method call in C must be changed via instrumentation to call the added
method in B. This requires a cast of the a reference to the type B.

The right side in figure 13.4 illustrates these changes.

We have not attempted to think a pointcut implementation for inherited methods


into the framework. But with the knowledge we have gained on Javassist, we believe
that Javassist has the necessary capabilities to implement this feature.

13.5.3 Dumping Modified Classes

To really understand the AOP framework it has been invaluable for us to study the
instrumented classes. We have taken the changed classes, created .class files for
them and used a decompiler to get Java source code. But this is not as easy as it
sounds. The instrumented classes in the AOP framework are never actually written
to .class files they are bytecode manipulated in memory and only exist in memory.

Creating .class files for these manipulated classes can be done in several ways. It
could be done by either writing a tool in an MBean to access the Javassist ClassPools
CHAPTER 13. REFLECTIONS AND CONCLUSION ON JBOSS 4 109

in the AspectManager, or the AspectManager class itself could be changed to write the
classes to disk as they are loaded. We investigated the former but chose the latter as
it was the simplest solution.

Ideally a tool for writing these .class files to disk should be written as an AOP-service
that could dump .class files from various points of execution in the JBoss AOP frame-
work. But the JBoss system classes cannot be instrumented, so this approach is out
of the question.

Even though not all users of JBoss AOP are interested in how the framework works,
we believe that a service for dumping the class files will be interesting to a lot of
developers.

Long after we changed the AspectManager to dump the .class files this feature has
been implemented as part of JBoss 4 DR3 in the head branch of CVS. All instru-
mented classes are now written to a temp dir, so they can be re-loaded without doing
the instrumentation all over again. This is relevant when the JVM unloads classes
and then needs to reload them.

13.6 Conclusions on JBoss 4

Here follows some conclusive and summarising remarks on the JBoss AOP frame-
work.

JBoss 4 and its AOP framework has offered us an excellent opportunity to learn
more about AOP and the design of large complex systems and frameworks. It has
also offered an opportunity for us to share this knowledge with other developers who
are interested in using JBoss 4s AOP framework.

A half-finished framework has the potential to render this document utterly useless,
because it might drastically change after this thesis is finished. However, it is our
firm belief that the AOP framework in JBoss has reached a level where changes to it
will not be of a fundamental character as in a complete rewrite. We therefore antic-
ipate that this report will still have its merits even when the framework is released
some time in the future.

Trying to understand the AOP framework we have read thousands of lines of code and
implemented numerous examples using the different functionalities that the frame-
work offers. As the framework is still under development these tasks can be very
tedious. While going through the framework implementation we have often felt that
discovering and understanding certain parts of the framework opened up a range of
new aspects to understand. This was especially true when trying to use remoting and
trying to understand undocumented code.
CHAPTER 13. REFLECTIONS AND CONCLUSION ON JBOSS 4 110

Although development using JBoss AOP is somewhat complex, we see the JBoss AOP
framework as a promising alternative to the complexities of J2EE.

On the one hand, the number of features and the ability to add pointcuts and inter-
ceptors dynamically to ordinary classes are strong arguments for using JBoss AOP
for developing middleware applications. On the other hand, the cognitive burden of
using all these features and keeping track of the different scopes and uses of pointcuts
is heavy. However, we believe that when JBoss 4 is released, proper documentation
and development guidance in the form of best practises will go a long way in mak-
ing the framework easier to use. It is our feeling, that for most developers it will
be easier to use the JBoss AOP framework rather than J2EE. This does not mean
that JBoss AOP will render J2EE obsolete. J2EE is a proven technology and still has
many features that JBoss AOP does not.
Chapter 14

Evaluation of the Process

In this chapter we will do a short evaluation of and conclusion on our own work and
the process we have been through. We separate the conclusions into two areas:

How we have succeeded in communicating the JBoss AOP framework to other


developers (section 14.1).

Thoughts on the process as a whole (section 14.2).

14.1 Communicating the AOP Framework

We feel that we have accomplished what we set out to do:

We have presented the JBoss AOP framework to software developers with an interest
in JBoss and the AOP framework, roughly divided into two groups: AOP-application
developers and AOP-service developers.

People who wish to understand the necessities of creating and deploying an AOP-
application or AOP-service can read part one and two that also serve as stepping
stones to part three, which is for those who are interested in further details on AOP-
service development and the AOP framework.

We also feel that the way we present the rather complex AOP framework is high level
enough to make it understandable for most people in the target groups. There is, of
course, always room for improvements.

14.1.1 Example Programs in the Report

If we had had the time, an area we could have improved is in the use of examples. We
would have liked to avoid using different examples in our report. We would instead

111
CHAPTER 14. EVALUATION OF THE PROCESS 112

have spent more time perfecting the Inventory Management example application and
let it be the only example application. The problem is that we have a fairly complex
example that is not suited for all chapters. The example application is either too
complicated or it lacks particular details needed for demonstration, and as such it
is hardly useful in any chapters without modifications. This is unfortunate since it
forces us to introduce several different examples that are more or less similar, albeit
simpler, versions of the main example.

We think that these different versions of the main example application can confuse
the reader, and it would be better if the example was one and the same throughout the
presentation. This would require more work on the example application possibly
extending it with functionality; but it would make the example consistent throughout
the report and thus save the reader from confusion.

14.2 The Process Working on the Thesis

Overall we are quite happy with the effort and the priorities we have made in the
past six months. During this time we have all worked on all subjects presented in
this report, so we have all got a fairly good understanding of the subjects covered. But
of course we have split up the work load, so some of us know more on some subjects
than the others. We might have been more effective had we not all been part of every
aspect, but we feel that getting an understanding of everything is more important
than being a little more effective.

Looking back on the past six months we can see that not all activities we undertook
were equally necessary, and some things we would have done differently were we
to start all over again. This should not be interpreted as if we are displeased with
everything we have done far from it! But in retrospect there are a few things to
reconsider:

14.2.1 Too Much Time Spent on AOP Remoting

Looking back we have spent a large amount of time on understanding and debugging
AOP remoting. Even though we have obtained valuable information about JBoss
while working with AOP remoting, we feel that we should have stopped working on
it much earlier. Turning our attention away from an unfinished service would have
given us more time to explore details of the actual framework instead.
CHAPTER 14. EVALUATION OF THE PROCESS 113

14.2.2 Graphical Client not Really Needed

We also spent some time creating the graphical client application we have used to
access and test the inventory management system with. In retrospect we can see
that this was not really necessary. We could just as easily have used a simpler text-
based client or even just unit tests. Cancelling the client application would have
saved us only little time, but would have helped us keeping better focus on our main
purpose understanding and communicating the JBoss AOP framework.

Originally we had planned to do a second graphical client application that could be


used by administrators of the inventory management system. This application would
receive notifications and collect log messages from the AOP-services we created and
present them to the user of the system. It would also be used to create new product
types and restock existing products in the system. We decided early on, however,
that this client would be too time consuming to create and also irrelevant to our
main purpose.

14.2.3 Understanding JBoss Source Code

Much of our time during the past six months has been used to unravel the JBoss
source code. This has been very worthwhile for understanding JBoss and the AOP
framework in detail. The only thing we could have wanted more was a little more
time to look into all the details of the framework.

14.2.4 If We had All the Time in the World

It is probably naive to think that dead ends can be avoided in a project such as this,
but should we replan the whole thing there would have been a few things to do:

To communicate the end-user experience we should have demonstrated one of the


AOP-services that ships with JBoss-AOP, eg the transaction service. Showing first
how it is used and then how it has been implemented would have served as a good
complementary introduction to our existing presentation.

Another interesting project would have been to add aspect oriented persistence to our
case application, as this is one of the primary needs for almost any application.
Bibliography

[1] A. Moreira A. Rashid, P. Sawyer and J. Araujo. Early aspects: A model for
aspect-oriented requirements engineering. In IEEE Joint International Con-
ference on Requirements Engineering, pages 199202. IEEE, IEEE Computer
Society Press, 2002. <http://www.early-aspects.net/papers.html> link worked
on February 7, 2004.

[2] Arie van Deursen, Marius Marin and Leon Moonen. Aspect mining and refactor-
ing. In Proceedings of the First International Workshop on REFactoring: Achieve-
ments, Challenges, Effects (REFACE03). University of Waterloo, 2003.

[3] Aspectj website, 2004. <http://eclipse.org/aspectj> link worked on February


7, 2004.

[4] Aspectwerkz website, 2004. <http://aspectwerkz.codehaus.org> link worked


on February 7, 2004.

[5] Sven Axster. Inventory Control. Kluwer Academic Publishers, 2000.

[6] Joshua Bloch. Jsr 175 a metadata facility for the java programming language.
Technical report, Sun Microsystems Inc., 2003.

[7] Edsger W. Dijkstra. A Discipline of Programming. Prentice-Hall, 1976.

[8] Early aspects at lancaster university, 2004. <http://www.early-aspects.net>


link worked on February 7, 2004.

[9] Erich Gamma et al. Design Patterns - Elements of Reusable Object-Oriented


Software. ADDISON-WESLEY, 1994.

[10] Gregor Kiczales, John Lamping, Anurag Menhdhekar, Chris Maeda, Cristina
Lopes, Jean-Marc Loingtier and John Irwin. Aspect-oriented programming. In
Mehmet Aksit and Satoshi Matsuoka, editors, Proceedings European Confer-
ence on Object-Oriented Programming, volume 1241, pages 220242. Springer-
Verlag, Berlin, Heidelberg, and New York, 1997.

114
BIBLIOGRAPHY 115

[11] Jan Hannemann. The aspect mining tool, 2004. <http://www.cs.ubc.ca/jan/-


amt/> link worked on February 7, 2004.

[12] JAC website, 2004. <http://jac.objectweb.org> link worked on February 7,


2004.

[13] Javassist website, 2004. <http://www.jboss.org/developers/projects/-


javassist.html> as of February 7, 2004.

[14] JBoss-AOP website, 2004. <http://jboss.org/developers/projects/jboss/aop>


link worked on February 7, 2004.

[15] Lieberherr, Karl and Lorenz, David H. and Ovlinger, Johan. Aspectual Collab-
orations: Combining Modules and Aspects This work was supported in part
by the National Science Foundation (NSF) under Grants No. CCR-0098643 and
CCR-0204432. The Computer Journal, 46(5):542565, 2003.

[16] Nanning website, 2004. <http://nanning.codehaus.org> link worked on Febru-


ary 7, 2004.

[17] The 4th aosd modeling with uml workshop, 2003. <http://www.cs.iit.edu/-
oaldawud/AOM/> link worked on February 7, 2004.

[18] The j2ee jmx specification website, 2004. <http://java.sun.com/j2ee/tools/-


management/index.jsp> as of February 7, 2004.

[19] The java 2 enterprise edition website, 2004. <http://java.sun.com/j2ee/in-


dex.jsp> link worked on February 7, 2004.

[20] The jmx specification website, 2004. <http://java.sun.com/products/JavaMan-


agement/index.jsp> as of February 7, 2004.

[21] Xdoclet website, 2004. <http://xdoclet.sourceforge.net> as of February 7,


2004.
Part I

Short Introductions to
Technologies Mentioned in the
Report

1
Appendix A

Short Intro to Technologies

A.1 What is J2EE and EJBs?

Java 2 Enterprise Edition (J2EE) is a trademark of Sun Microsystems. J2EE is a


series of standards and specifications provided by Sun Microsystems. The specifica-
tions are designed to standardize the way common functionality for large systems is
implemented. The J2EE 1.4 specification used in Jboss 4 is currently in final draft.

The specification can be used as a reference in implementing an application server.


If the server adequately lives up to the required specifications (which can be deter-
mined by Sun via their certification program), the server can be called a J2EE com-
pliant server. l The J2EE specifications specify certain services that a J2EE server
must provide to the applications running within it. The main services are: Transac-
tion support, Persistence support, Security support, Concurrency handling, Naming
service, Handling of Distributed Objects, Asynchronous messaging and Management.
Since these services are needed by many enterprise scale applications and because
they can be quite difficult to implement, J2EE offers a uniform environment in which
these services are already implemented and readily available to the applications de-
ployed in the J2EE server.

The main way for a J2EE application server to provide these services to applications
running in it, is to provide a container for Enterprise Java Beans (EJB). The applica-
tions themselves are then typically implemented as EJBs, but they do not have to be.
Since management became part of the J2EE specifications (in J2EE 1.4) the use of
JMX (see A.2 below) has also been required. There are further requirements in J2EE
1.4. For a complete listing and all the specifications see the J2EE website [19].

Enterprise Java Beans (EJB) are standard software components defined in one of the
J2EE specifications. A J2EE server must provide an EJB container that offers the
above mentioned services to EJBs. Even though EJBs are standard components they

2
APPENDIX A. SHORT INTRO TO TECHNOLOGIES 3

are often surprisingly difficult to implement and maintain. Many different files are
needed to create and deploy just one EJB. With more EJBs the complexity goes up.
Even if EJBs are somewhat complex to develop and maintain, it is still vastly more
complex to hand code the services mentioned above.

A.2 What is JMX?

JMX stands for Java Management Extensions and is, in short, a Java standard for
managing applications, appliances and environments dynamically. As everything
else in J2EE, JMX is merely a specification that the J2EE server providers must
implement themselves. JMX can be compared to the Simple Network Management
Protocol (SNMP) standard, which is a standard for managing networked devices.
However, JMX is much more flexible than SNMP.

The JMX specification consists of two main parts (for a full discussion on all fea-
tures and details of the JMX specification see [18] and [20]). The first part are the
manageable software components called MBeans. The second part is a server that
can contain the manageable software components and also provide a management
front-end to the components.

A.3 What are MBeans?

Managed Beans or MBeans are the software components that can be managed through
the JMX server (or MBean server). An MBean expose an interface that can be used
by the MBean server to call the methods on the MBean. MBeans themselves are,
in their simplest form, just normal JavaBeans with a few further rules to stick by.
They can, however, be more complicated and abstract. See the JMX specification for
further details [20].

MBeans can be used to provide a management interface to other software components


such as EJBs or perhaps the EJB container. In such a setup, the MBean exposes
methods that again communicate with the component it needs to manage. Since
the MBean management interface consists of pure Java methods, there is nothing
wrong with an application implementing the management methods directly in a class
already part of the application.

In short MBeans can be used to expose management interfaces to applications de-


ployed in an MBean server.
APPENDIX A. SHORT INTRO TO TECHNOLOGIES 4

A.4 JBoss as an MBean Server

The JBoss application server is constructed as a microkernel with a lot of plugin


additions. The microkernel is more or less just an MBean server in which MBeans
can be deployed. Different plugins are provided for the microkernel that extends its
functionality. In this way the EJB container, transaction suppot etc. is plugged in to
the JBoss microkernel, while at the same time exposing a management interface.

Every MBean server must provide a front-end that can be used to manipulate the
MBeans deployed in the server. JBoss is no exception in this regard. JBoss includes
a web-console and a jmx-console that acts as front-end to all the MBeans running
in the server. The front-ends are HTML pages generated through Servlets and JSP
pages. This provides JBoss with an easy to use MBean front-end. All the methods of
the MBean that are manageable are put in the HTML page along with a button to
invoke the method.
Part II

Overview of Classes Used in


JBoss AOP

5
Appendix B

Support Classes for


Instrumented Classes

B.1 Advisor

Fully qualified class name: org.jboss.aop.Advisor


Part of: The JBoss AOP framework.
Description: The Advisor class is super class of the ClassAdvisor and ProxyAdvisor. It
contains functionality they both inherit. The ProxyAdvisor has not been implemented
fully yet and will not be described here.

B.2 ClassAdvisor

Fully qualified class name: org.jboss.aop.ClassAdvisor


Part of: The JBoss AOP framework.
Description: This is the class that contains interceptor-chains for a particular instru-
mented class. All instances of an instrumented class share one ClassAdvisor, since
there is only one ClassAdvisor for each instrumented class. All field accesses, method
and constructor calls in an instrumented class go through the ClassAdvisor in order
to traverse the associated interceptor-chain.

B.3 InstanceAdvisor

Fully qualified class name: org.jboss.aop.InstanceAdvisor


Part of: The JBoss AOP framework.
Description: InstanceAdvisor is an interface. It defines the methods implemented in

6
APPENDIX B. SUPPORT CLASSES FOR INSTRUMENTED CLASSES 7

ClassInstanceAdvisor.

B.4 ClassInstanceAdvisor

Fully qualified class name: org.jboss.aop.ClassInstanceAdvisor


Part of: The JBoss AOP framework.
Description: The ClassInstanceAdvisor class contains interceptor-chains for an in-
stance of a particular instrumented class. For each instance of an instrumented class
there is one ClassInstanceAdvisor. Per instance interceptors from the ClassInstan-
ceAdvisor will be added to ClassAdvisor interceptor chain that must be traversed on
any field access, instance creation or method call.

B.5 InstanceAdvised

Fully qualified class name: org.jboss.aop.InstanceAdvised


Part of: The JBoss AOP framework.
Description: An interface that defines methods to get and set an InstanceAdvisor in
an instrumented class.

B.6 Advised

Fully qualified class name: org.jboss.aop.Advised


Part of: The JBoss AOP framework.
Description: An interface that defines a method to get an Advisor. A class declared
advisable in an AOP deployment descriptor will implement this interface after in-
strumentation. The instrumented class can then be type casted to Advised. Advised
extends the InstanceAdvised interface.
Appendix C

Classes for Deployment and


Instrumentation

C.1 AspectManager

Fully qualified class name: org.jboss.aop.AspectManager


Part of: The JBoss AOP framework.
Description: The AspectManager manages pointcuts, interceptors and metadata for
all classes. It is used during deployment and instrumentation. During deployment
tables in the AspectManager is filled with information on pointcuts, interceptors and
metadata. During instrumentation the AspectManager creates a ClassAdvisor of the
class it is instrumenting and the information in the tables are moved to the ClassAd-
visor. The AspectManager also contains methods for adding and removing pointcuts,
interceptors and metadata dynamically.

C.2 AspectXmlLoader

Fully qualified class name: org.jboss.aop.AspectXmlLoader


Part of: The JBoss AOP framework.
Description: The AspectXmlLoader loads information on pointcuts, interceptors and
metadata from a parsed AOP deployment descriptor into tables in the AspectManag-
er.

8
APPENDIX C. CLASSES FOR DEPLOYMENT AND INSTRUMENTATION 9

C.3 DeploymentInfo

Fully qualified class name: org.jboss.deployment.DeploymentInfo


Part of: The JBoss AOP framework.
Description: A DeploymentInfo object holds information on a service, application or
MBean as it is being deployed.

C.4 Instrumentor

Fully qualified class name: org.jboss.aop.Instrumentor


Part of: The JBoss AOP framework.
Description: The Instrumentor contains a number of methods to handle the instru-
mentation of classes.
Appendix D

Pointcut Classes

D.1 Advisable

Fully qualified class name: org.jboss.aop.Advisable


Part of: The JBoss AOP framework.
Description: The Advisable class is a super class of all pointcut types. It contains
methods for matching regular expressions on class names in pointcuts.

D.2 InterceptorPointcut

Fully qualified class name: org.jboss.aop.InterceptorPointcut


Part of: The JBoss AOP framework.
Description: InterceptorPointcut is the super class of ConstructorPointcut, Field-
Pointcut, MethodPointcut and CallerPointcut. It contains functionality shared by
all the inheriting pointcut classes. It is an immediate subclass of Advisable. It is
also an object representation of a class-pointcut that can match a class via a regular
expression.

D.3 ConstructorPointcut

Fully qualified class name: org.jboss.aop.ConstructorPointcut


Part of: The JBoss AOP framework.
Description: The ConstructorPointcut is an object representation of a constructor-
pointcut. It can match a constructor in a class via a regular expression.

10
APPENDIX D. POINTCUT CLASSES 11

D.4 FieldPointcut

Fully qualified class name: org.jboss.aop.FieldPointcut


Part of: The JBoss AOP framework.
Description: A FieldPointcut is an object representation of a field-pointcut. It can
match a field in a class via a regular expression.

D.5 MethodPointcut

Fully qualified class name: org.jboss.aop.MethodPointcut


Part of: The JBoss AOP framework.
Description: An object representation of a method-pointcut. It can match a method
in a class via a regular expression.

D.6 CallerPointcut

Fully qualified class name: org.jboss.aop.CallerPointcut


Part of: The JBoss AOP framework.
Description: An object representation of a caller-pointcut. It can match a particular
method in a class that is called from another particular method in a particular class
via regular expressions.

D.7 IntroductionPointcut

Fully qualified class name: org.jboss.aop.IntroductionPointcut


Part of: The JBoss AOP framework.
Description: An object representation of an introduction-pointcut. It can match a
class via a regular expression and it holds a reference to a list of interfaces that must
be introduced into a target class. It also holds a reference to a list of mixins that
must implement the same list of interfaces. It contains an inner class Mixin that is
an object representation of a mixin.
Appendix E

Interceptor Classes

E.1 Interceptor

Fully qualified class name: org.jboss.aop.Interceptor


Part of: The JBoss AOP framework.
Description: The Interceptor interface must be implemented by all interceptors. An
interceptor must contain the methods getName() and invoke(Invocation inv). A
singleton property can be set on interceptors, which are not initialized via a factory,
in the AOP deployment descriptor. This property makes sure that only one instance
of the interceptor is made across the entire JVM.

E.2 InterceptorFactory

Fully qualified class name: org.jboss.aop.InterceptorFactory


Part of: The JBoss AOP framework.
Description: The InterceptorFactory is the interface all interceptor factories must
implement. An interceptor factory must contain the method create(Advisor adv).
An InterceptorFactory can be used to create interceptors if the interceptors need
any special initialization done. If no interceptor factory is declared in the AOP de-
ployment descriptor the interceptor is initialized via its default constructor. If the
singleton=true property is set on the interceptor in the AOP deployment descrip-
tor the SingletonInterceptorFactory is used to initialize the inteceptor. This ensures
that only one instance of the interceptor is created across the entire JVM.

12
APPENDIX E. INTERCEPTOR CLASSES 13

E.3 ConstructorTailInterceptor

Fully qualified class name: org.jboss.aop.ClassAdvisor.ConstructorTailInterceptor


Part of: The JBoss AOP framework.
Description: The ConstructorTailInterceptor is an inner class in the ClassAdvisor.
It creates an instance of a class through reflection.

E.4 FieldTailInterceptor

Fully qualified class name: org.jboss.aop.ClassAdvisor.FieldTailInterceptor


Part of: The JBoss AOP framework.
Description: The FieldTailInterceptor is an inner class in the ClassAdvisor. It sets
or gets the value of a field through reflection.

E.5 MethodTailInterceptor

Fully qualified class name: org.jboss.aop.ClassAdvisor.MethodTailInterceptor


Part of: The JBoss AOP framework.
Description: The MethodTailInterceptor is an inner class in the ClassAdvisor. It
invokes a method through reflection.

E.6 CallerTailInterceptor

Fully qualified class name: org.jboss.aop.ClassAdvisor.CallerTailInterceptor


Part of: The JBoss AOP framework.
Description: The CallerTailInterceptor is an inner class in the ClassAdvisor. It
invokes a method through reflection.
Appendix F

Invocation Classes

F.1 Invocation

Fully qualified class name: org.jboss.aop.Invocation


Part of: The JBoss AOP framework.
Description: The Invocation class is super class of all invocation types. It contains
functionality that is shared between all invocation types such as the invokeNext()
method that an interceptor must call. It also contains a reference to the array of
Interceptors (the interceptor chain) that must be processed at the time of intercep-
tion.

F.2 ConstructorInvocation

Fully qualified class name: org.jboss.aop.ConstructorInvocation


Part of: The JBoss AOP framework.
Description: When a constructor call is delegated to the ClassAdvisor, the ClassAd-
visor will create a ConstructorInvocation instance.

F.3 FieldInvocation

Fully qualified class name: org.jboss.aop.FieldInvocation


Part of: The JBoss AOP framework.
Description: The FieldInvocation is the super class of FieldReadInvocation and
FieldWriteInvocation. It contains functionality shared by both.

14
APPENDIX F. INVOCATION CLASSES 15

F.4 FieldReadInvocation

Fully qualified class name: org.jboss.aop.FieldReadInvocation


Part of: The JBoss AOP framework.
Description: When a field read access is delegated to the ClassAdvisor, the ClassAd-
visor will create a FieldReadInvocation instance.

F.5 FieldWriteInvocation

Fully qualified class name: org.jboss.aop.FieldWriteInvocation


Part of: The JBoss AOP framework.
Description: When a field write access is delegated to the ClassAdvisor, the ClassAd-
visor will create a FieldWriteInvocation instance.

F.6 MethodInvocation

Fully qualified class name: org.jboss.aop.MethodInvocation


Part of: The JBoss AOP framework.
Description: When a method call is delegated to the ClassAdvisor, the ClassAdvisor
will create a MethodInvocation instance.

F.7 CallerInvocation

Fully qualified class name: org.jboss.aop.CallerInvocation


Part of: The JBoss AOP framework.
Description: When a method call in a calling class is delegated to the ClassAdvisor,
the ClassAdvisor will create a CallerInvocation instance.

F.8 InvocationType

Fully qualified class name: org.jboss.aop.InvocationType


Part of: The JBoss AOP framework.
Description: The InvocationType class contains fields declared static final. The
fields are of predefined InvocationTypes. All invocation objects have a reference to an
InvocationType instance that corresponds to the type of invocation object.
Appendix G

Javassist Classes

G.1 ClassPool

Fully qualified class name: javassist.ClassPool


Part of: The Javassist API.
Description: The ClassPool is a container from which an object representation of the
bytecode of a class can be retrieved. The ClassPool is a container of CtClass objects.
The pool has methods to write bytecode of a modified class either to a .class file on
disk or to the class in the JVM memory.

G.2 CtClass

Fully qualified class name: javassist.CtClass


Part of: The Javassist API.
Description: The CtClass is an object representation of the bytecode of a class. It
contains fields and methods to manipulate the bytecode of a class through source
code abstractions.

G.3 CtConstructor

Fully qualified class name: javassist.CtConstructor


Part of: The Javassist API.
Description: The CtConstructor is an object representation of a constructor. It con-
tains fields an methods to manipulate the bytecode of a constructor through source
code abstractions.

16
APPENDIX G. JAVASSIST CLASSES 17

G.4 CtField

Fully qualified class name: javassist.CtField


Part of: The Javassist API.
Description: The CtField is an object representation of a field. It contains fields an
methods to manipulate the bytecode of a field through source code abstractions.

G.5 CtMethod

Fully qualified class name: javassist.CtMethod


Part of: The Javassist API.
Description: The CtMethod is an object representation of a method. It contains fields
an methods to manipulate the bytecode of a method through source code abstractions.
Part III

Diagrams

19
Appendix H

Deployment Diagrams

20
APPENDIX H. DEPLOYMENT DIAGRAMS 21

H.1 MBean Deployment Diagrams

Figure H.1: Mbean Deployment Sequence Diagram

This diagram shows the sequence of operations in the MBean deployment process. Illustrates how the
MBeans in jboss-service.xml are deployed an started.

ServerImp MainDeployer SARDeployer SeviceController ServiceConfigurator ServiceCreator


ServerImpls doStart() calls
deploy() on the MainDeployer
instance through a proxy. The (1) (2)
deploy( String url ) info = new
String url contains a path to
DeploymentInfo
the file jboss-service.xml (1)
deploy( info )
A DeploymentInfo is created
from the url (2) init( info )
(3)
findDeployer( info )
findDeployer() iterates
through a list of deployers
and calls their accepts( info ). set info.deployer deployer = (4)
SARDeployer accepts info parseDocument( info )
info.deployer init( info ) Super class is
that contains an url that ends
with -service.xml. (3) SubDeployerSupp
ort. Init notifies the
service MBean that
jboss-service.xml is parsed super.init( info )
the SARDeployer
and set as infos Document. (4) (5) has been
initialized.
The info is added to the list of
deployed deployments (5) create( info ) An Mbean is
registered in the
create() is called on the infos (6) MBeanServer
info.deployer create( info ) (MBeanServerImpl
deployer. A List of Mbeans is
retrieved by calling install with ) with the infos
getServer().registerMBean() UrlClassLoader
the root Element of infos
and this
document, and its install()
ClassLoaders
UrlClassLoaders ObejctName (6) ObjectName
install() (7)
* internalInstall() install() retrieves
For each MBean-tag found in
the document internallInstall() type info from the
is called. (7) install() xml and
(8) reflectively creates
returns MBean instance createMBean() an instance from
The Mbean corresponding to which it can create
the MBean-tag content is an MBean by
registerMBeanClassName(instance)
created (8) calling
(9) createMBean() on
Child-elements of the MBean- configure() the server
tag is used to configure the
Mbean e.g. that the
deployment is dependent on
other deployments. (9)
(10)
mbeanList list of mbean ObjectNames
Add the mbeanList to the
SARDeployers list of
deployed MBeans. Iterate
through the list and call
create() on the
(10)
* create()
ServiceController (10) A proxy instance
create() to the service is
start( info ) created and
create() is called
Iterate through the list and on this
info.deployer start( info )
call start on the (11)
ServiceController. (11) * start()

start()
start() is called on
the proxy instance
APPENDIX H. DEPLOYMENT DIAGRAMS 22

Figure H.2: Classes Involved in the Mbean Deployment

NotificationBroadcasterSupport interface * interface interface interface


interface Deployer MainDeployerMbean SubDeployerMBean SubDeployer
MBeanRegistration
1

ServiceMBeanSupport

interface
ServiceControllerMBean

SubDeployerSupport

interface *
MBeanRegistration 1

MainDeployer
EARDeployer JARDeployer XSLSubDeployer AspectDeployer SARDeployer
1 ServiceController *
1 1

1
1

1
1 DeploymentInfo URLClassLoader
0..1

1 *
MBeanServer ServiceCreator ServiceConfigurator
* 0..1
* *
UnifiedClassLoader

1
APPENDIX H. DEPLOYMENT DIAGRAMS 23

H.2 Scanning for Services and Applications

Figure H.3: URLDeploymentScanner Scanning Process Sequence Diagram

start() is called on
UrlDeploymentScanners parents URLDeploymentScanner ScannerThread MainDeployer SARDeployer SubDeployerSupport
parent ServiceMBeanSupport.
startService() is called on the start()
parent startService()
AbstractDeploymentScanner.

ScannerThread is an inner class doScan


in AbstractDeploymentScanner
that inherits from javas Thread. scan() The scan method iterates
Prior to the call to start(), start() through the list of url's and
has been called on the adds to a list of urls to
ScannerThread (this was during * deployedUrl = new ( urlToDeploy ) deploy. If an url ends with "/"
creation of the service) this will it's a directory and it calls
DeployedUrl
off course mean a call to run() on recursively to locate url's in
the ScannerThread. run() will * deploy( deployedUrl ) the subdirectory.
loop until the server is shutting
down, but will do nothing until it
has been set enabled. deploy( deployedUrl )

info = new DeploymentInfo


UrlDeploymentScanner has a
List of urls to scan for new
deployments. Initially this list
contains only one url the path deploy( info )
to the deploy directory. This
value is stated as an attribute for init( info )
the DeploymentScanner mbean
in jboss-service.xml and has findDeployer( info )
been set during the initial
deployment process (see set info.deployer deployer =
diagram XX).
info.deployer init( info )
scan() iterates through the list of Proceed as in
found urls to deploy, creates a diagram XX.
DeployedUrl object and calls
deploy with this. DeployedUrl is super.init( info )
an inner class of
URLDeploymentScanner. processNestedDeployments( info )

scan() also takes care of


undeploying and redeploying
addDeployableJar( info, jarFile )
we will only focus on initial
deployment here.

A deployment process * deployUrl( info, subUrl, fileName )


recembling the one in diagram
XX is initiated. We will skip a few new
allready illustrated steps. DeploymentInfo

MainDeployer is set as
UrlDeploymentScanners set as parent
deployer during configuration
from jboss-service.xml.

From here we assume that the


value of the url attribute is a path * init( subInfo )
to our inventory-
management.sar that has been Do it all again find
placed in the deploy/ directory. the appropriate
deployer, look for
init() in SARDeployer calls subdeployments etc.
super.init( info ) just before
exiting. This will look for
subdeployments and create new
child DeploymentInfos for these.

If the url does not reference a


directory or an xml-file it is
treated as a jar-file and
setEnabled( true )
addDeployableJar() is called with
this jar file. ScannerThread is now enabled and the
loop() method will be initiated in run().
addDeplyableJar() iterates the loop() will call doScan() for every 5
content of the jar file and checks seconds as long as it is enabled.
for deployable content ( e.g. sar-
files, ear-files, etc. ).

For each deployable file a new


DeploymentInfo is created and
the current one is set as parent
in the new one the
DeploymentInfo constructor will
put the new DeploymentInfo into
a collection of subDeployments
in its parent.

For each of these


subDeployments init() will be
called. The MainDeployers
create() and start() methods will
also iterate the subDeployers
and call create() and start() on
these.
APPENDIX H. DEPLOYMENT DIAGRAMS 24

H.3 AOP Deployment Process

Figure H.4: AOP Deployment Sequence Diagram

MainDeployer DeploymentInfo info AspectDeployer AspectXmlLoader MethodPointcut AspectManager


In this diagram it is assumed that info.deployer init( info )
the MainDeployer has come across
parseDocument( info )
a .aop file that it will attempt to
deploy.
sets infos document
Call init() on the AspectDeployer
with the DeploymentInfo that
contains the Url which reference the
.aop file. info.deployer create( info )

The jboss-aop.xml file in the META- deployXML(info.url)


INF/ library of the .aop file is loadURL()
parsed, and the result is set as the
infos document.

Here the xml-document is iterated


element by element and for each
deployXML(document, info.url)
known element a corresponding
method is called.
We model only the handling of a
<method-pointcut> element. deployMethodPointcut(element)

Extract the class-pattern, the


method-pattern, the group and
associated interceptors from the loadInterceptorsElement(element)
method-pointcut. The embedded
interceptors are deployed.

With the gathered information, a


new MethodPointcut is made and <new>
added to the AspectManager, type-
addInterceptorPointcut
cast as an InterceptorPointcut

AspectManagerService MBeanServer
This is how the AspectManager is
told to handle the instrumentation of
createService()
classes.
setAttribute(DEFAULT_LOADER_REPOSITORY, AspectManager.instance())
APPENDIX H. DEPLOYMENT DIAGRAMS 25

Figure H.5: Classes Involved in the AOP Deployment

NotificationBroadcasterSupport

+sendNotification()
+addNotificationListener()
+handleNotification()

Element * 1 Document DocumentBuilder DocumentBuilderFactory


ServiceMBeanSupport

* * *

SubDeployerSupport

MainDeployer Notification

* *
AspectDeployer AspectXmlLoader *
*
* *
* * *
DeploymentInfo
NodeList
#UnifiedClassLoader *
#SubDeployer
#URLClassLoader *
* #parent : DeploymentInfo 1
Appendix I

Instrumentation Process
Diagrams

I.1 Instrumentation Sequence Diagrams

The instrumentation process is illustrated in the Diagram in figure I.1 and six refer-
enced sub-diagrams (figures I.2 to I.7).

26
APPENDIX I. INSTRUMENTATION PROCESS DIAGRAMS 27

Figure I.1: Main Diagram

UnifiedClassLoader3 AspectManager ClassAdvisor AOPClassPool

When a class is first instrumened translate( classname, this )


the classloader will call translate isNonAdvisableClass()
on the AspectManager, with itself
and a classname String.

translate() checks if it is allowed to


make this class advisable ie. that ClassAdvisor advisor =
its not something like a system findClassAdvisor( classname )
class.

The pointcuts and introductions return if allready exists in hashmap of advisors


hashmap has been filled during
deployment. The pointcuts
hashmap contains classname {OR}
return null if not advisable (see 2)
keys and Advisable objects
derived from ie. States which
classes that are advisable. {OR}
return null if no pointcuts or introductions
attachMetaData() iterates the
pointcuts hashmap and checks for
ClassMetaData instances if any {OR}
it checks that the classname advisor = new
matches the class regex pattern
that this instance holds and adds Replaces field acces to referenced advised classes in
the advisor to the pointcut found. attachMetaData(advisor,classname) current class with methodcalls to methods with the
ClassMetaDatas parent following signature (first one for read acces second
Advisables matches method is for write acces):
called.
attachAdvisableAndInterceptorPointcuts(advisor,classname) <nameOfField><_r_$WithoutAdvisement>(Object o);
As above, but checks for
InterceptorPointcut instances. <nameOfField><_w_$WithoutAdvisement>(Object
Interceptorpointcuts matches o,<fieldType> f);
attachCallerPointcuts(advisor,classname)
method is called.

attachCallerPointcuts() iterates
the callerPointcuts hashmap and attachIntroductionPointcuts(advisor,classname)
checks that the classname Replaces instance creation of referenced
matches the class regex pattern advised classes with static methodcalls. For
that this instance holds and adds add the advisor to the hashmap of advisors each constructorcall a methodcall with the
the advisor to the pointcut found. following signature is inserted:

attachIntroductionPointcuts() aopClassPool = registerClassLoader(urlClassLoader) <Objecttype><_new_$WithoutAdvisement>(<


iterates the introductionPointcuts originalParameters>);
hashmap and checks that the ClassPool pool
classname matches the class
regex pattern that this instance pool.getLocally(classname)
holds and adds the advisor to the
pointcut found. CtClass clazz CtClass clazz

The AspectManager has a instrumentor = new (pool, new CodeConverter) Instrumentor


hashmap of registered
ClassLoaders. This contains
AOPClassPool objects for each convertReferences(instrumentor,urlClassLoader,clazz)
Classloader. We check if there
allready is a classpool for this
ClassLoader if not a new is * instrumentor.replaceFieldAcces(listOfFields,aReferencedClass,theFieldfilter)
created and returned.

A CtClass object is retrieved from * instrumentor.replaceConstructorAccess(aReferencedClass)


the classpool.

Find all classes that this class


references. If any of those classes if( advisor == null ) [current class is not advisable] { instrument( converter ) }
are advised and have field and/or
constructor interception, do
instrumentation on this class so {OR}
that those fields and constructors makeAdvisable( clazz, advisor)
are instrumented. checkNotAdvised()

convertReferences() iterates Calls instrument() on


through all the classes that the addClassReference(clazz) adds a static field to the every CtMethod and
CtClass clazz references. instrumented class and a static block in which it initializes CtConstructor in the
addInterface( i )
Replaces access for all fields and this: CtClass.
constructors with static methods. private static final Class aop$class$WithoutAdvisement
{ addClassReference(clazz)
Even though a class is not aop$class$WithoutAdvisement =
advisable, instrument() is called java.lang.Class.forName(fullNameOfInstrumentedClass); i is a CtClass object
on it in order to proces the } representing the
changes made to the class for Advisable interface.
handling object creation an field
acces of other advised classes addHelperClass(clazz)
that the current class acceses.

If the class is allready advised a addBaseElements(clazz)


AllReadyAdvisedException will be [if a subclass of anything but Object]
thrown.

By adding static references to the See subdiagram 1 instrumentMethods(clazz,methodFilter)


addHelperClass(clazz) adds a static field to the instrumented class and
instrumentet class itself, we a static block in which it initializes this as well as a get method to acces
secure that the class is always this field:
loaded with the context private static final Advisor aop$classAdvisor$WithoutAdvisement See subdiagram 2
classloader. { instrumentFields(clazz,fieldFilter)
aop$classAdvisor$WithoutAdvisement =
AspectManager.instance().getAdvisor(aop$class$WithoutAdvisement);
} See subdiagram 3
instrumentConstructors(clazz,constructorFilter)

See subdiagram 4 instrumentIntroductions(clazz,advisor)

See subdiagram 5
applyCallerPointcuts(clazz,advisor)

Apply all changes


See subdiagram 6
made to CtClass
instrument(converter) object

write(classname)

byte[] result byte[] result [bytearray with changed class]


APPENDIX I. INSTRUMENTATION PROCESS DIAGRAMS 28

Figure I.2: Subdiagram I

Method: addBaseElements(CtClass clazz)

Instrumentor CtClass clazz CtMethod

inside the makeAdvisable method

The addBaseElements method is


addBaseElements(clazz) addProtectedField() adds a new protected field to the clazz
called when the class that the
CtClass represents have object with the following signature:
java.lang.Object as its immediate protected transient ClassInstanceAdvisor _instanceAdvisor:
super class. It will also be called if ...and the following initialization in all the class constructors:
addProtectedField(-,-,-,-)
the immediate super class is not _instanceAdvisor = new ClassInstanceAdvisor(this);
advisable.

A ClassInstanceAdvisor field is
added to the CtClass instance. getter = new

Getter and setter methods for this


field is added to the CtClass
addMethod(getter)
instance.

If an advised class has an advised


immediate super class then it setter = new
shares / gets its
ClassInstanceAdvisor from its
advised immediate super class.
addMethod(setter)
APPENDIX I. INSTRUMENTATION PROCESS DIAGRAMS 29

Figure I.3: Subdiagram II

Method : instrumentMethods(clazz,methodFilter)

Instrumentor CTClass:clazz

Inside the makeAdvisable() method


instrumentMethods(clazz, methodFilter)

clazz is an instance of CTClass


the javassist class-type, and we get getAdvisableMethods(clazz)
a list of CTMethods, that should be
instrumented.
getDeclaredFields()
CTMethod:invokeMethod
Iterating through the returned
methods we determine if the *[while iterator.hasNext()]
new = invokeMethod
method is static or not.
Adds thiis method to the CTClass instance:
All static methods share the createStaticInvokeMethod(clazz)
staticInvoke() method, and all non- public static Object invokeStatic(Object[] args,
static methods share the long i) {
invokeMethod() return ((ClassAdvisor)
aop$classAdvisor$WithoutAdvisement).invoke
Method((Object) null, i, args);
}

{static method
OR Will add the following method to the CTClass
non-static method} Instance:
invokeMethod = createInvokeMethod(clazz) public java.lang.Object
invoke(java.lang.Object[] args, long i) {
return
((org.jboss.aop.ClassAdvisor)this._getAdvisor(
)).invokeMethod(this, i, args);
Renaming the orignal that should }
still exist for unadvised usage. method.setName()

invokeMethod = createDelegatingMethod()
CTNewMethod
Here a delegation method is Bytecode
constructed, wrapping the newly wrapped()
constructed invokeMethod or
newMethod
invokeStatic.
new (newMethod ...)
The Bytecode object is the byte-
representation of our class and addAload()
here it is built step by step. This is
not shown in detail here. addGetField()

addInvokeVirtual()

addReturn()

addMethod(delegatingMethod)

public int getStock() {


if(!_instanceAdvisor.hasAspects())
return jboss$thesis$inventory$model$ItemImpl$getStock$WithoutAdvisement();
else
return ((Integer)_added_m$0(new Object[0], 0xfae8983fe6453c82L)).intValue();
}
APPENDIX I. INSTRUMENTATION PROCESS DIAGRAMS 30

Figure I.4: Subdiagram III

Method: instrumentFields(CtClass clazz, int fieldFilter)

Instrumentor CtClass clazz CtField

inside the makeAdvisable method

The instrumentFields method() will


instrumentFields(clazz, filter)
return immediatly if the filter is set
to InterceptorFilter.NONE.

A list of all advisable CtFields in List fields = getAdvisableFields(clazz)


the CtClazz object is retrieved.
The field is not advisable if:
- it has a final modifier getDeclaredFields()
- it ends with $WithoutAdvisement
- it starts with _
- it contains a $

For all fields where the filter replaceFieldAcces(fields, clazz, filter)


matches the modifiers of the field
(the default is ALL) we replace
access to the fields with static
method calls (see parent diagram
at #xx)
offSet = fieldOffset(clazz.getSuperclass())
Retrieve an offSet - a total offSet = fieldOffset(clazz.getSuperclass())
number of advised fields in all
super classes except Object.
if class is java.lang.Object return 0
Create trapRead and trapWrite
CtMethods and add these to the ctField[] = getDeclaredFields()
CtClass instance.

All fields in the CtClass instance is * if( isAdvisable(ctfield[index]) ) Will add the following method to
iterated we create an index that is the CtClass instance:
initiated to the offSet that was offSet++ Protected static Object trapRead(
found earlier. Object[] args, int name ){
return ClassAdvisor.trapRead(
First set an int that represents the args[0], name,
CtMethod trapRead = createTrapRead(clazz)
modifier of the curent field. Make aop$classAdvisor
the int contain a value that reflects $Withoutadvisement);
static as well. }

Add static methods to represent


field access for all fields. These CtMethod trapWrite = createTrapWrite(clazz) Will add the following method to
methods wrap calls to the the CtClass instance:
trapRead and trapWrite method. Protected static Object trapWrite(
They use the offSet determine Object[] args, int name ){
which field to access. The offSet return ClassAdvisor.trapWrite(
is set based on the number of args[0], name,
fields in super classes. Example: * for (int index = offset; iterator.hasNext(); index++) aop$classAdvisor
A super class that inherits from $Withoutadvisement);
Object has 4 fields they will be }
field = iterator.next()
field 1-4 any fields in the current
class will be field 5-X. set an int to represent modifiers of field Will create a method with the
following signature and body - it
CtMethod wmethod = CtNewMethod.wrapped(-,-,-,-,-,-,-) wraps a call to the trapRead
method above!
addMethod(wmethod)
<modifer> static <type>
wmethod = CtNewMethod.wrapped(-,-,-,-,-,-,-) <fieldname>_r_&WithoutAdvisem
ent ( Object o ){
addMethod(wmethod) return
trapRead(new Object[]{ o },
index )
}

Will create a method with the


following signature and body - it
wraps a call to the trapWrite
method above!
<modifer> static <type>
<fieldname>_w_&WithoutAdvise
ment ( Object o, <fieldType> t ){
return
trapWrite(new Object[]{ o, s },
index )
}
APPENDIX I. INSTRUMENTATION PROCESS DIAGRAMS 31

Figure I.5: Subdiagram IV

Method: instrumentConstructors(CtClass clazz, int constructorFilter)


Instrumentor CtClass clazz CodeConverter

inside the makeAdvisable method

If the filter is set to


instrumentConstructors(clazz, filter)
InterceptorFilterNONE
instrumentConstructors() will
return immediately.
replaceConstructorAccess(clazz)
replaceNew in the CodeConverter
replaces all instatiations of the
class that the clazz represents
with static method calls inside the String s = constructorFactory(classname)
class itself.

Add the trapConstructor method return classname + "_new_$WithoutAdvisement" Replace new <MyClass>()
that wraps calls to the with calls to
replaceNew(clazz, clazz, s) <MyClass>.<MyClass>_new
trapConstructor method in the
classAdvisor for all constructors. _$WithoutAdevisement(
<params> )
Get a list of all constructors in
clazz object.
CtMethod trapConstructor = createTrapConstructor(clazz)
Creates the following method
Create static methods for each and adds it to clazz.
constructor to use instead of using CtNewMethod.make(methodString,clazz)
new <MyClass> and add these to protected static Object
the CtClass instance. trapConstructor(Object[]
List constructors = getConstructors(clazz) args, int i){
return ClassAdvisor
.trapConstructor(args
, (ClassAdvisor)
aop$classAdvisor
$WithoutAdvsiement, i);
* while list has more - constructor = next }

set an int to represent modifiers of the constructor


For each constructor a call to
the trapConstructor mehod
CtMethod wmethod CtNewMethod.wrapped(-,-,-,-,-,-,-)
(above) is wrapped in a
addMethod(wmethod) method with the following
signature:

<modfiers> static <MyClass>


<MyClass>_new_$WithoutA
devisement( <params> )
APPENDIX I. INSTRUMENTATION PROCESS DIAGRAMS 32

Figure I.6: Subdiagram V

Method: instrumentIntroductions(clazz, advisor)


IntroductionPointcut
Instrumentor CtClass clazz ClassAdvisor advisor
pointcut
inside the makeAdvisable method

A list of pointcuts are retrieved Adds a field:


instrumentIntroductions(clazz, advisor)
from the advisor. This list is private transient <mixinShortClassName>
iterated. For each pointcut a list of _jboss<mixinFullClassName>$aop$mixin
mixins are retrieved. The list of getIntroductionPointcuts()
mixins is iterated and addMixin() <mixinFullClassName> is the classname
is called. ArrayList pointcuts with packagename, where the dots in the
packagename has been replaced by $.
addMixin() first adds a private
field. This field is a reference to * while has more pointcuts - pointcut = next
the mixin class we have created
that has implementations for the
introduced interfaces in the getMixins()
introduction pointcuts. Initialization
of this mixin class is added to the ArrayList mixins
constructors of our CtClass
instance. Initialization is based on
* addMixin(clazz, pointcut, mixins.get(index), mapOfBaseMethods)
the info stated in the
<constructor> tag in the aop.xml
file.
addPrivateField(-,-,-,-)
Next the method that transfer all
mixed in invokings to the
classadvisor for this mixin class is
added. CtMethod mixinInvokeMethod = createMixinInvokeMethod(clazz, mixinCtClass)

A String array of interfaces private Object mixinInvoke(Object obj[], long l) throws Throwable{
associated with current return ((ClassAdvisor)_getAdvisor()).invokeMethod(_getInstanceAdvisor(),
introductionpointcut is retrieved. <mixinFullClassName>, l, obj); } is added to the CtClass instance
String[] interfaces = mixin.getInterfaces()
Iterate the list of interfaces. For
each:
* for (int i = 0; i < interfaces.length; i++)
---
Add the interface to the CtClass
instance (adds implements addInterface( interface[i], CtClass )
<interface> to the class)
We add the methods that the interface
Make shure that the each method * addMixinMethod(-,-,-,-) requires as wrappers to the mixinInvoke
that the interface requires us to
method.
implement does not allready exist
in the class or any superclasses
(throws exception if so!).

Implement each method by * while has more pointcuts - pointcut = next


adding it to the CtClass instance
as a wrapper to the mixinInvoke
getInterfaces()
method with the, in the interface,
required signature. String[] interfaces
---
The list of pointcuts are iterated
again to instrument for * addIntroductionPointcutInterface(interfaces[i],-,-);
introductions handled by
interceptors.

A String array of interface names CtMethod mixinInvokeMethod = createInvokeMethod(clazz, mixinCtClass)


are retrieved. This array is iterated
and for each entry: A normal generic delegation method is added to the CtClass instance
---
We add the interface to the
addInterface( interface[i] )
CtClass instance. We add the methods that the interface
requires as wrappers to the generic
Create a standard generic delegation method.
* addMixinMethod(-,-,-,-)
delegation method to delegate the
introduced methods to the
ClassAdvisor with. (Only happens
if one does not allready exist to
service other methods).

Add the introduced methods.


APPENDIX I. INSTRUMENTATION PROCESS DIAGRAMS 33

Figure I.7: Subdiagram VI

Method: applyCallerPointcuts(clazz,advisor)

Instrumentor CtClass clazz ClassAdvisor advisor CallerPointcut pcut

inside the makeAdvisable method

applyCallerPointcuts(clazz, advisor)
All caller-pointcuts that match the
class that is beeing instrumented ArrayList pointcuts = new ArrayList();
will be retrieved from the table of
pointcuts in the AspectManager.
* for all caller-pointcuts in the AspectManager singleton
For each of callerpointcuts calling
method and called method
hashvalues are created. The caller- matches( current caller-pointcut )
pointcut is added to the
ClassAdvisor. The ClassAdvisor will if match - pointcuts.add(pcut)
create a table structure consisting
of a table of calling methods that
contains tables of called classes
that contains tables of called
methods that contains Interceptor * for each pcut in pointcuts
arrays.
- Create hashvalues for the calling method (callingHash) and the
called method (calledHash).
All method calls are replaced and
- Get a String with the classname of the class containg the called
delegated through the
method.
ClassAdvisor.
addCallerPointcut(callingHash, classname, calledHash, pcut)

If a class has any caller-pointcuts applied to it, all method calls will
be replaced with a call to a method in the ClassAdvisor as below:

(ClassAdvisor)aop$classAdvisor$WithoutAdvisement
.invokeCaller( <callingHash>
, <classname>, <calledHash>
, <reference-to-called-class-instance>
, <Object-array-of-arguments>)
APPENDIX I. INSTRUMENTATION PROCESS DIAGRAMS 34

I.2 Instrumentation Classes

Figure I.8: Classes Involved in the Instrumentation Process

* interface
Advisor
Translator
+translate()
+unregisterClassLoader()

CodeConverter
Instrumentor

Singleton 1 1
*
1

*
1 Javassist.ClassPool
interface * 1 AspectManager
InterceptorFactory * 1
1 1
+create() : Interceptor

1 AOPClassPool

Advisable

SingletonInterceptorFactory GenericInterceptorFactory

InterceptorPointcut

interface
Interceptor
+getName() : string
+invoke() : object MethodPointcut
Appendix J

Diagrams of Instrumented Class


Use

J.1 Instance Creation, Field Access and Method Invoca-


tion Sequence Diagrams

35
APPENDIX J. DIAGRAMS OF INSTRUMENTED CLASS USE
Instance Creation
product : ProductImpl advisor : ClassAdvisor constructorInterceptors : ArrayList interceptor : ConstructorTailInterceptor

Create a new ProductImpl.


All code that creates a new
ProductImpl, is in all classes replaced by a call to:
public static ProductImpl
Product_new_$WithoutAdvisement() _added_m$3( new Object[0], 0 )
throws invocationTargetException
This is the last interceptor
trapConstructor( Object[], ClassAdvisor, int ) in the Interceptor array in the invocation.
If there were more interceptors in the array
their invoke() method would have been
called prior to this one

Figure J.1: Instantiating an instrumented ProductImpl


invokeNew( Object[], int )

get( int )

returns Interceptor[]

All Interceptors, except the


new ConstructorInvocation( Interceptor[] ) invocation : ConstructorInvocation last, in the Interceptor array call
invokeNext() on the Invocation
object they got in as parameter.
This result in the invocation of
the next interceptor's invoke
method being called.

set different values on the invocation object

Creates a java.lang.Constructor
object and calls newInstance( args[] ) on it.
(The args[] is empty) and thereby running
invokeNext() ProductImpl's real constructor.

invoke( invocation )

Constructor.newInstance()

returns a ProductImpl instance


return an ProductImpl instance
returns a ProductImpl instance

returns a ProductImpl instance


See diagram Instantiating an
instrumented ProductImpl 2"

36
APPENDIX J. DIAGRAMS OF INSTRUMENTED CLASS USE
Writing to a field
A static initializer is run when the
class is loaded. product : ProductImpl advisor : ClassAdvisor fieldInterceptors : ArrayList interceptor : FieldTailInterceptor
The Class for ProductImpl is saved in a variable.
The ClassAdvisor for ProductImpl is saved in a variable.
(It is taken from the AspectManager)

Constructor.newInstance()

new ClassInstanceAdvisor( product ) _instanceAdvisor : ClassInstanceAdvisor


This is the last interceptor
See diagram Instantiating an in the Interceptor array in the invocation.
instrumented ProductImpl for id_w_$WithoutAdvisement( product, ProductIdUtil.getNextId() ) If there were more interceptors in the array

Figure J.2: Instantiating an instrumented ProductImpl 2


their invoke() method would have been
previous details called prior to this one
The newInstance( args[] ) method
_added_m$2( Object[], 1 )
on a java.lang.Constructor object
is called. This method call results in
the running of ProductImpl's no-args trapWrite( product, 1, product.id, advisor )
constructor.
(The args[] is empty).
classAdvisor.invokeWrite( product, 1, product.id )

The Object[] contains the arguments from the method call.


In this case the Object[] contains: classAdvisor =
{ product, new Long( product.id ) }
((Advised) product)._getAdvisor() {OR} advisor
The number 1, is the number the id field got during
instrumentation.
Interceptor[] aspects =
get( index )

returns an Interceptor[]

{OR}

getInterceptors( aspects )

returns an Interceptor[]

For reference: The


uninstrumented constructor
of ProductImpl: new FieldwriteInvocation( aspects ) invocation : FieldWriteInvocation

public ProductImpl() {
super(); All Interceptors, except the
id = ProductIdUtil.getNextId(); Set different values on the invocation instance last, in the Interceptor array call
} invokeNext() on the Invocation
object they got in as parameter.
invokeNext() This result in the invocation of
the next interceptor's invoke
invoke( invocation ) method being called.

returns null Calls field.set( targetObject, value );


where the field is a Field object
returns null created when the FieldTailInterceptor
object was created.
targetObject is the ProductImpl and
the value is the products new id.

returns null
Returns null

returns null

returns null
returns a ProductImpl instance

37
APPENDIX J. DIAGRAMS OF INSTRUMENTED CLASS USE 38

Figure J.3: Invoking a Method in an Instrumented Class

Invoking the method getID() in ProductImpl


_instanceAdvisor : ClassInstan
product : ProductImpl advisor : ClassAdvisor info : MethodInfo
ceAdvisor

getID()

Some class calls the method hasAspects() Checks a couple of booleans


getID(). set during deployment and
returns accordingly
An instrumented method first
false
checks for aspects through the
ClassInstanceAdvisor. If (as it
is here) the instrumented class
jboss$thesis$inventory$model$ProductImpl$getID$WithoutAdvisement()
is a subclass of another
instrumented class, then it {OR}
gets the _instanceAdvisor
from the superclass. If there
are no aspects the original true
method is called through its
new name given during The Object array represent the
instrumentation. _added_m$0(new Object[0], methodHash) arguments of a method. As getID
has no arguments the array is
If there are any aspects the empty. From here this array is
((ClassAdvisor)_getAdvisor()).invokeMethod(this, methodHash, args)
call is distributed to the referenced as args.
ClassAdvisor through a call to
invokeMethod. _getInstanceAdvisor()

The methodHash is a long _instanceAdvisor


value representing the method
signature of the current invokeMethod(_instanceAdvisor, product, methodHash, args)
method. This value has been
set during the instrumentation
of the class. The ClassAdvisor info = methodInterceptors.get(methodHash)
holds a HashMap with these
methodHashs as keys and getInterceptors(info.aspects)
MethodInfo Objects as values.
Interceptor[] aspects
A MethodInfo is a simple class invocation : MethodInvocation
new MethodInvocation(aspects)
that holds info on a method. It
has:
set different values in the invocation object
- an ArrayList that represents
the interceptorChain for the methodHash = methodHash
method
- an array of interceptors arguments = args
called aspects
- a Method object representing targetObject = product
the advised method
- a Method object representing method = info.advisedMethod
invokeNext() will call invoke
the unadvised method (the on the next Interceptor in
Interceptor invokeNext()
original renamed) the chain with itself as an
argument. The next
In invokeMethod the object we interceptor in the chain will
are invoking getID on (this aka do whatever it has to do,
product) is cast to a invoke(invocation)
and return a call to
InstanceAdvised invokeNext() on the
invokeNext()
invocation object. This
result of invoke to the originalmethod goes on until we reach the
last interceptor in the chain,
result : Object which will be a
MethodTailInterceptor.

See below for invoke call in


result : Object
MethodTailInterceptor

interceptor : MethodTailInterc A MethodTailInterceptor


invocation MethodInvocation eptor method : Method
holds a reference to the
method object that
represents the original
(renamed) method. Invoke
invoke( invocation )
in the interceptor calls
invoke( invocation.targetObject, invocation.arguments ) invoke on this method
object with the
targetObject, and
arguments Object array
Object result from the invocation object
returns the result of this
Object result invoke.
J.2

APPENDIX J. DIAGRAMS OF INSTRUMENTED CLASS USE


interface
InstanceAdvisor
+getMetaData() : SimpleMetaData
+getInterceptors() : Interceptor[] SimpleMetaData FieldMetaData ConstructorMetaData Advisable
interface
InstanceAdvised +getInterceptors(in baseChain : Interceptor[]) : Interceptor[]
+hasAspects() : boolean * *
+_getInstanceAdvisor() : InstanceAdvisor *
+insertInterceptor(in interceptor : Interceptor)

Class Use Class Diagrams


+_setInstanceAdvisor(in newAdvisor : InstanceAdvisor)
+removeInterceptor(in name : String)

Figure J.4: Instrumented ProductImpl Advisor Class Relationship


+appendInterceptor(in interceptor : Interceptor)
+addInterceptorStack(in stackName : String)
+removeInterceptorStack(in name : String)
+appendInterceptorStack(in stackName : String) ClassMetaData
interface
Advised 1
InterceptorFilter
+_getAdvisor() : Advisor *

* * *
*
1 ClassInstanceAdvisor
SimpleClassMetaData
Advisor *
ProductImpl
* *
1 1
1
* * InterceptorPointcut

ClassAdvisor ProxyAdvisor

Holds an object instance's


metadata and attached interceptors CallerPointcut ConstructorPointcut MethodPointcut FieldPointcut

39
Part IV

Simplified Inventory
Management Example

41
Appendix K

Classes used in Part III

The classes below are used as an example Inventory Management system throughout
part III. Below are both the original classes and their instrumented counterparts as
well as the example AOP deployment descriptor.

K.1 Original ProductImpl.java

Source of the original ProductImpl


1 package jboss . thesis . inventory . model ;
2

3 public class ProductImpl {


4 private long id ;
5 public String name ;
6

7 public ProductImpl (){


8 // do nothing
9 }
10

11 public long getID (){


12 return id ;
13 }
14 }

42
APPENDIX K. CLASSES USED IN PART ?? 43

K.2 Instrumented ProductImpl.java

Source of the instrumented ProductImpl


1 package jboss . thesis . inventory . model ;
2

3 import jboss . thesis . inventory . service .*;


4

5 import org . jboss . aop .*;


6

7 import java . lang . reflect . InvocationTargetException ;


8

10 public class ProductImpl implements Product , Advised , MinimumStock {


11 private static final long serialVersionUID = -0 x962aaf2c86a1ac0L ;
12 private static final Class aop$class$WithoutAdvisement ;
13 private static final Advisor aop$classAdvisor$WithoutAdvisement;
14

15 static {
16 aop$class$WithoutAdvisement = Class. forName (
17 " jboss . thesis . inventory . model . ProductImpl ");
18 aop$classAdvisor$WithoutAdvisement = AspectManager . instance (). getAdvisor (
19 aop$class$WithoutAdvisement );
20 }
21

22 private long id ;
23 public String name ;
24 protected transient ClassInstanceAdvisor _instanceAdvisor ;
25 private transient ProductMixin
26 _jboss$thesis$inventory$service$ProductMixin$aop$mixin;
27

28 public ProductImpl () {
29 _instanceAdvisor = new ClassInstanceAdvisor ( this );
30 _jboss$thesis$inventory$service$ProductMixin$aop$mixin = new ProductMixin (
31 this , 20 , 0);
32 }
33

34 public long getID () {


35 if (! _instanceAdvisor . hasAspects ()) {
36 return
37 jboss$thesis$inventory$model$ProductImpl$getId$WithoutAdvisement();
38 }
39 else
40 {
41 return (( Long ) _added_m$0 ( new Object [0] ,
42 0 xac2adf437a698318L )). longValue ();
43 }
44 }
45

46 private Object _added_m$0 ( Object [] aobj , long l ) throws Throwable {


47 return (( ClassAdvisor ) _getAdvisor ()). invokeMethod ( this , l , aobj );
APPENDIX K. CLASSES USED IN PART ?? 44

48 }
49

50 private static Object _added_m$1 ( Object [] aobj , int i ) {


51 return ClassAdvisor . trapRead (
52 aobj [0] , i , aop$classAdvisor$WithoutAdvisement);
53 }
54

55 private static Object _added_m$2 ( Object [] aobj , int i ) {


56 return ClassAdvisor . trapWrite (
57 aobj [0] , i , aobj [1] , aop$classAdvisor$WithoutAdvisement);
58 }
59

60 private static Object _added_m$3 ( Object [] aobj , int i ) {


61 return ClassAdvisor . trapConstructor (
62 aobj , ( ClassAdvisor ) aop$classAdvisor$WithoutAdvisement , i );
63 }
64

65 private Object _added_m$4 ( Object [] aobj , long l ) throws Throwable {


66 return (( ClassAdvisor ) _getAdvisor ()). invokeMethod (
67 _getInstanceAdvisor () ,
68 _jboss$thesis$inventory$service$ProductMixin$aop$mixin , l , aobj );
69 }
70

71 public static ProductImpl ProductImpl_new_$WithoutAdvisement()


72 throws InvocationTargetException {
73 return ( ProductImpl ) _added_m$3 ( new Object [0] , 0);
74 }
75

76 public long
77 jboss$thesis$inventory$model$ProductImpl$getId$WithoutAdvisement() {
78 return id_r_$WithoutAdvisement ( this );
79 }
80

81 public Advisor _getAdvisor () {


82 return aop$classAdvisor$WithoutAdvisement;
83 }
84

85 public InstanceAdvisor _getInstanceAdvisor () {


86 return _instanceAdvisor ;
87 }
88

89 public void _setInstanceAdvisor ( InstanceAdvisor instanceadvisor ) {


90 _instanceAdvisor = ( ClassInstanceAdvisor ) instanceadvisor ;
91 }
92

93 private static long id_r_$WithoutAdvisement ( Object obj ) {


94 return (( Long ) _added_m$1 ( new Object [] { obj } , 1)). longValue ();
95 }
96

97 private static void id_w_$WithoutAdvisement ( Object obj , long l ) {


98 _added_m$2 ( new Object [] { obj , new Long (l ) } , 1);
APPENDIX K. CLASSES USED IN PART ?? 45

99 }
100

101 public static String name_r_$WithoutAdvisement ( Object obj ) {


102 return ( String ) _added_m$1 ( new Object [] { obj } , 3);
103 }
104

105 public static void name_w_$WithoutAdvisement ( Object obj , String s ) {


106 _added_m$2 ( new Object [] { obj , s } , 3);
107 }
108

109 public int getMinimumStock () {


110 return (( Integer ) _added_m$4 ( new Object [0] ,
111 0 x91a734e41d3a147bL )). intValue ();
112 }
113

114 public void setMinimumStock ( int i ) {


115 _added_m$4 ( new Object [] { new Integer (i ) } , 0 xdb773c5ac4ef6981L );
116 }
117 }
APPENDIX K. CLASSES USED IN PART ?? 46

K.3 Original ClassUsingProduct.java

Source of the original jboss.thesis.inventory.model.ClassUsingProduct


1 package jboss . thesis . inventory . model ;
2

3 public class ClassUsingProduct {


4 ProductImpl product ;
5

6 public ClassUsingProduct () {
7 product = new ProductImpl (); // call constructor
8 product . name = " TestProduct "; // access field directly
9 }
10

11 public long getProductID () {


12 return product . getID (); // call method
13 }
14

15 public String getProductName () {


16 return product . name ; // access field directly
17 }
18 }
APPENDIX K. CLASSES USED IN PART ?? 47

K.4 Instrumented ClassUsingProduct.java

Source of the instrumented jboss.thesis.inventory.model.ClassUsingProduct


1 package jboss . thesis . inventory . model ;
2

3 public class ClassUsingProduct {


4 private static final Class aop$class$WithoutAdvisement ;
5 private static final Advisor aop$classAdvisor$WithoutAdvisement;
6

7 static {
8 aop$class$WithoutAdvisement = Class. forName (
9 " jboss . thesis . inventory . model . ClassUsingProduct ");
10 aop$classAdvisor$WithoutAdvisement = AspectManager . instance (). getAdvisor (
11 aop$class$WithoutAdvisement );
12 }
13

14 ProductImpl product ;
15

16 public ClassUsingProduct () {
17 // product = new ProductImpl ();
18 product = ProductImpl . ProductImpl_new_$WithoutAdvisement();
19

20 // access field " directly ": product . name = " TestProduct ";
21 ProductImpl . name_w_$WithoutAdvisement ( product , " TestProduct ");
22 }
23

24 public long getProductID () {


25 // call product . getID ();
26 String _tmp = s;
27 s = ( String )(( ClassAdvisor ) aop$classAdvisor$WithoutAdvisement). invokeCaller (
28 -0 x1768de1f041461e9L , // hash of calling method
29 " jboss . thesis . inventory . model . ProductImpl " , // name of called class
30 0 x53e0822d3e3724dfL , // hash of called method
31 product , // instance to call method on
32 new Object [0]); // arguments to called method
33

34 return s;
35 }
36

37 public String getProductName () {


38 // access field " directly ": return product . name ;
39 String _tmp = s;
40 s = ProductImpl . name_r_$WithoutAdvisement ( product );
41 return s;
42 }
43 }
APPENDIX K. CLASSES USED IN PART ?? 48

K.5 AOP Deployment Descriptor

Source of the example jboss-aop.xml


1 <aop >
2 < advisable class =" jboss . thesis . inventory . model . ProductImpl " / >
3

4 < interceptor name =" Logger " singleton =" true "
5 class =" jboss . thesis . inventory . service . logging . LoggingInterceptor ">
6 </ interceptor >
7

8 <method - pointcut class =" jboss . thesis . inventory . model . ProductImpl "
9 methodName =" getID ">
10 < interceptors >
11 < interceptor - ref name =" Logger "/ >
12 </ interceptors >
13 </ method - pointcut >
14

15 < introduction - pointcut class =" jboss . thesis . inventory . model . ProductImpl ">
16 < mixin >
17 < interfaces > jboss . thesis . inventory . service . MinimumStock </ interfaces >
18 <class > jboss . thesis . inventory . service . ProductMixin </ class >
19 < construction >
20 new jboss . thesis . inventory . service . ProductMixin ( this , 20 , 0 )
21 </ construction >
22 </ mixin >
23 </ introduction - pointcut >
24

25 <caller - pointcut
26 class =" jboss . thesis . inventory . model . ClassUsingProduct "
27 calledClass =" jboss . thesis . inventory . model . ProductImpl "
28 calledMethodName =" getID "
29 withinMethodName =" getProductID ">
30 < interceptors >
31 < interceptor - ref name =" Logger "/ >
32 </ interceptors >
33 </ caller - pointcut >
34 </aop >
Part V

Source Code

49
Appendix L

Deployment Descriptors

L.1 AOP Deployment Descripter

Source of inventory-management-aop.xml (must be renamed to jboss-aop.xml before


deployment)
1 <? xml version ="1.0" encoding =" UTF -8"? >
2 <aop >
3 < advisable class =" jboss . thesis . performancetest . ConstructorTest " / >
4 < advisable class =" jboss . thesis . inventory . model . ProductImpl " / >
5 < advisable class =" jboss . thesis . inventory . model . ProductComposite " / >
6 < advisable class =" jboss . thesis . inventory . model . Order " / >
7 < advisable class =" jboss . thesis . inventory . model . OrderList " / >
8 < advisable class =" jboss . thesis . inventory . model . Customer " / >
9 < advisable class =" jboss . thesis . inventory . model . Reservation " / >
10 < advisable class =" jboss . thesis . inventory . model . Type " / >
11 <!--
12 * This Interceptor logs constructor calls of the classes specified in the
13 * constructor - pointcuts below .
14 -->
15 < interceptor name =" ConstructorLogger " singleton =" true " class =
16 " jboss . thesis . inventory . service . logging . ModelConstructorLoggingInterceptor">
17 </ interceptor >
18

19 < constructor - pointcut class =" jboss . thesis . inventory . model . Order ">
20 < interceptors >
21 < interceptor - ref name =" ConstructorLogger "/ >
22 </ interceptors >
23 </ constructor - pointcut >
24

25 < constructor - pointcut class =" jboss . thesis . inventory . model . Reservation ">
26 < interceptors >
27 < interceptor - ref name =" ConstructorLogger "/ >
28 </ interceptors >

50
APPENDIX L. DEPLOYMENT DESCRIPTORS 51

29 </ constructor - pointcut >


30

31 < interceptor name =" MinimumStockInterceptor " singleton =" true "
32 class =" jboss . thesis . inventory . service . MinimumStockInterceptor ">
33 </ interceptor >
34

35 < interceptor name =" DecrementReservationInterceptor" singleton =" true "


36 class =" jboss . thesis . inventory . service . DecrementReservationInterceptor">
37 </ interceptor >
38

39 < interceptor name =" IncrementReservationInterceptor" singleton =" true "


40 class =" jboss . thesis . inventory . service . IncrementReservationInterceptor">
41 </ interceptor >
42

43 <method - pointcut class =" jboss . thesis . inventory . model . Reservation "
44 methodName =" setQuantity ">
45 < interceptors >
46 < interceptor - ref name =" MinimumStockInterceptor "/ >
47 < interceptor - ref name =" IncrementReservationInterceptor"/ >
48 </ interceptors >
49 </ method - pointcut >
50

51 < introduction - pointcut class =" jboss . thesis . inventory . model . ProductImpl ">
52 < mixin >
53 < interfaces >
54 jboss . thesis . inventory . service . MinimumStock ,
55 jboss . thesis . inventory . service . ReservationCounter
56 </ interfaces >
57 <class > jboss . thesis . inventory . service . ProductMixin </ class >
58 < construction >
59 new jboss . thesis . inventory . service . ProductMixin ( this , 20 , 0 )
60 </ construction >
61 </ mixin >
62 </ introduction - pointcut >
63

64 < introduction - pointcut class =" jboss . thesis . inventory . model . ProductComposite ">
65 < mixin >
66 < interfaces >
67 jboss . thesis . inventory . service . MinimumStock ,
68 jboss . thesis . inventory . service . ReservationCounter
69 </ interfaces >
70 <class > jboss . thesis . inventory . service . ProductCompositeMixin </ class >
71 < construction >
72 new jboss . thesis . inventory . service . ProductCompositeMixin ( this )
73 </ construction >
74 </ mixin >
75 </ introduction - pointcut >
76

77 <!--
78 * this interceptor and pointcut intercept the creation of new Product
79 * objects and looks up a property file - minimumstock . properties -
APPENDIX L. DEPLOYMENT DESCRIPTORS 52

80 * where the default values of the different types of products are


81 * stored . The default minimum stock is stored in the metadata of the
82 * actual product instance to be read by the MinimumStockInterceptor
83 -->
84 < interceptor name =" ProductConstructionInterceptor" singleton =" true "
85 class =" jboss . thesis . inventory . service . ProductConstructionInterceptor">
86 </ interceptor >
87

88 <method - pointcut class =" jboss . thesis . inventory . model . ProductImpl "
89 methodName =" setType ">
90 < interceptors >
91 < interceptor - ref name =" ProductConstructionInterceptor"/ >
92 </ interceptors >
93 </ method - pointcut >
94

95 <method - pointcut class =" jboss . thesis . inventory . model . ProductImpl "
96 methodName =" decreaseStockBy ">
97 < interceptors >
98 < interceptor - ref name =" DecrementReservationInterceptor"/ >
99 </ interceptors >
100 </ method - pointcut >
101

102 <method - pointcut class =" jboss . thesis . inventory . model . ProductComposite "
103 methodName =" decreaseStockBy ">
104 < interceptors >
105 < interceptor - ref name =" DecrementReservationInterceptor"/ >
106 </ interceptors >
107 </ method - pointcut >
108 </aop >
APPENDIX L. DEPLOYMENT DESCRIPTORS 53

L.2 JBoss Service Deployment Descriptor

Source of inventory-management-service.xml
1 <? xml version ="1.0" encoding =" UTF -8"? >
2 <! DOCTYPE server >
3 < server >
4 <depends > jboss : service = DefaultPartition </ depends >
5

6 < mbean code =" jboss . thesis . inventory . model . jmx . InventoryService "
7 name =" jboss . thesis . inventory : name = InventoryService "/ >
8

9 < mbean code =" jboss . thesis . inventory . model . jmx . TestService "
10 name =" jboss . thesis . inventory : name = TestService "/ >
11

12 < mbean code =" jboss . thesis . inventory . model . jmx . RemoteService "
13 name =" jboss . thesis . inventory : name = RemoteService "/ >
14

15 < mbean code =" jboss . thesis . inventory . model . jmx . DynamicAop "
16 name =" jboss . thesis . inventory : name = DynamicAop "/ >
17

18 < mbean code =" jboss . thesis . inventory . model . jmx . AOPService "
19 name =" jboss . thesis . inventory : name = AOPService "/ >
20

21 < mbean code =" org . jboss . remoting . transport . Connector "
22 xmbean - dd =" org / jboss / remoting / transport / Connector . xml "
23 name =" jboss . remoting : type = Connector , transport = socket5150 ">
24 < attribute name =" InvokerLocator "> socket :// localhost :5150 </ attribute >
25 < attribute name =" Configuration ">
26 < handlers >
27 < handler subsystem =" AOP ">
28 org . jboss . aop . remoting . AOPRemotingInvocationHandler
29 </ handler >
30 </ handlers >
31 </ attribute >
32 </ mbean >
33 </ server >
Appendix M

Inventory Managment
AOP-application

All classes below are part of the jboss.thesis.inventory.model package.

M.1 Customer.java

Source of jboss.thesis.inventory.model.Customer
1 package jboss . thesis . inventory . model ;
2

3 import java . rmi . Remote ;


4

6 /**
7 * @author Christian Dalager , Simon Jorsal , Eske Sort
8 */
9 public class Customer implements Remote {
10 private long id = 0;
11 private String name ;
12 private String address ;
13 private String email ;
14

15 public Customer () {
16 this ("" , "" , "");
17 }
18

19 public Customer ( String name , String address , String email ) {


20 this . name = name ;
21 this . address = address ;
22 this . email = email ;
23 }
24

54
APPENDIX M. INVENTORY MANAGMENT AOP-APPLICATION 55

25 public Customer ( String name , String address ) {


26 this ( name , address , "");
27 }
28

29 public Customer ( String name ) {


30 this ( name , "" , "");
31 }
32

33 public long setId () {


34 id = IdUtil . getNextId ( IdUtil . CUSTOMER );
35

36 return id ;
37 }
38

39 public long getId () {


40 return id ;
41 }
42

43 public String getAddress () {


44 return address ;
45 }
46

47 public void setAddress ( String address ) {


48 this . address = address ;
49 }
50

51 public String getEmail () {


52 return email ;
53 }
54

55 public void setEmail ( String email ) {


56 this . email = email ;
57 }
58

59 public String getName () {


60 return name ;
61 }
62

63 public void setName ( String name ) {


64 this . name = name ;
65 }
66 }
APPENDIX M. INVENTORY MANAGMENT AOP-APPLICATION 56

M.2 IdUtil.java

Source of jboss.thesis.inventory.model.IdUtil
1 package jboss . thesis . inventory . model ;
2

3 import org . jboss . logging . Logger ;


4

6 /**
7 * @author Christian Dalager , Simon Jorsal , Eske Sort
8 */
9 public class IdUtil {
10 private static Logger log = Logger . getLogger ( IdUtil . class );
11 public static final int PRODUCT = 0;
12 public static final int ORDER = 1;
13 public static final int RESERVATION = 2;
14 public static final int TYPE = 3;
15 public static final int CUSTOMER = 4;
16 private static long itemCounter = 1;
17 private static long orderCounter = 1;
18 private static long reservationCounter = 1;
19 private static long typeCounter = 1;
20 private static long customerCounter = 1;
21

22 private IdUtil () {}
23

24 public static long getNextId ( int type ) {


25 long returnValue = -1;
26

27 if ( type == PRODUCT ) {
28 if ( log . isDebugEnabled ()) {
29 log . debug (" new PRODUCT id =" + itemCounter );
30 }
31

32 returnValue = itemCounter ++;


33 }
34 else if ( type == ORDER ) {
35 if ( log . isDebugEnabled ()) {
36 log . debug (" new ORDER id =" + orderCounter );
37 }
38

39 returnValue = orderCounter ++;


40 }
41 else if ( type == RESERVATION ) {
42 if ( log . isDebugEnabled ()) {
43 log . debug (" new RESERVATION id =" + reservationCounter );
44 }
45

46 returnValue = reservationCounter ++;


47 }
APPENDIX M. INVENTORY MANAGMENT AOP-APPLICATION 57

48 else if ( type == TYPE ) {


49 if ( log . isDebugEnabled ()) {
50 log . debug (" new TYPE id =" + typeCounter );
51 }
52

53 returnValue = typeCounter ++;


54 }
55 else if ( type == CUSTOMER ) {
56 if ( log . isDebugEnabled ()) {
57 log . debug (" new CUSTOMER id =" + customerCounter );
58 }
59

60 returnValue = customerCounter ++;


61 }
62 else {
63 throw new IllegalArgumentException (" Type =" + type + " is not valid ");
64 }
65

66 return returnValue ;
67 }
68

69 public static long getCurrentId ( int type ) {


70 long returnValue = -1;
71

72 if ( type == TYPE ) {
73 returnValue = typeCounter ;
74 }
75 else if ( type == PRODUCT ) {
76 returnValue = itemCounter ;
77 }
78 else if ( type == ORDER ) {
79 returnValue = orderCounter ;
80 }
81 else if ( type == RESERVATION ) {
82 returnValue = reservationCounter ;
83 }
84 else if ( type == CUSTOMER ) {
85 returnValue = customerCounter ;
86 }
87 else {
88 throw new IllegalArgumentException (" Type =" + type + " is not valid ");
89 }
90

91 return returnValue ;
92 }
93 }
APPENDIX M. INVENTORY MANAGMENT AOP-APPLICATION 58

M.3 Order.java

Source of jboss.thesis.inventory.model.Order
1 package jboss . thesis . inventory . model ;
2

3 import java . io . Serializable ;


4

5 import java . rmi . Remote ;


6

7 import java . util . ArrayList ;


8 import java . util . Date ;
9 import java . util . Iterator ;
10 import java . util . List ;
11

12

13 /**
14 * A order holds information about a purchase . It contains information about
15 * products selected as well as name and address of the customer .
16 *
17 * @author Christian Dalager , Simon Jorsal , Eske Sort
18 */
19 public class Order implements Remote , Serializable {
20 private long id ;
21 private List reservations ;
22 private boolean invoiceCreated ;
23 private Date date ;
24 private Customer customer ;
25

26 public Order () {
27 reservations = new ArrayList ();
28 date = new Date ();
29 }
30

31 public long setId () {


32 id = IdUtil . getNextId ( IdUtil . ORDER );
33

34 return id ;
35 }
36

37 public Iterator getReservationIterator () {


38 return reservations . iterator ();
39 }
40

41 /**
42 * Adds a new product ( Reservation ) to the order .
43 *
44 * @param reservation the Reservation to add .
45 */
46 public void addReservation ( Reservation reservation ) {
47 reservations . add ( reservation );
APPENDIX M. INVENTORY MANAGMENT AOP-APPLICATION 59

48 }
49

50 public void removeReservation ( Reservation reservation ) {


51 reservations . remove ( reservation );
52 }
53

54 public void removeReservation ( int index ) {


55 reservations . remove ( index );
56 }
57

58 public void clearReservations () {


59 reservations . clear ();
60 }
61

62 public Reservation getReservation ( int index ) {


63 Reservation reservation = null ;
64

65 try {
66 reservation = ( Reservation ) reservations . get ( index );
67 }
68 catch ( IndexOutOfBoundsException ignored ) {
69 // if there are no reservations just return null .
70 }
71

72 return reservation ;
73 }
74

75 public Reservation getReservationByProduct ( Product product ) {


76 Iterator i = reservations . iterator ();
77

78 while (i. hasNext ()) {


79 Reservation current = ( Reservation ) i. next ();
80

81 if ( current . getProduct (). equals ( product )) {


82 return ( Reservation ) current ;
83 }
84 }
85

86 return null ;
87 }
88

89 public boolean containsReservation ( Reservation reservation ) {


90 Iterator i = reservations . iterator ();
91

92 while (i. hasNext ()) {


93 if ((( Reservation ) i. next ()). getProduct (). equals (
94 reservation . getProduct ())) {
95 return true ;
96 }
97 }
98
APPENDIX M. INVENTORY MANAGMENT AOP-APPLICATION 60

99 return false ;
100 }
101

102 public int sizeOfReservationList () {


103 return reservations . size ();
104 }
105

106 public void createInvoice () {


107 Iterator i = reservations . iterator ();
108

109 while (i. hasNext ()) {


110 Reservation current = ( Reservation ) i. next ();
111 Product product = current . getProduct ();
112 product . decreaseStockBy ( current . getQuantity ());
113 }
114

115 invoiceCreated = true ;


116 }
117

118 /**
119 * Acumulates the full price of all products in the order .
120 *
121 * @return the acumulated price of the Order .
122 */
123 public double getFullPrice () {
124 double price = 0;
125 Iterator i = reservations . iterator ();
126

127 while (i. hasNext ()) {


128 price += (( Reservation ) i. next ()). getPrice ();
129 }
130

131 return price ;


132 }
133

134 public Customer getCustomer () {


135 return customer ;
136 }
137

138 public void setCustomer ( Customer customer ) {


139 this . customer = customer ;
140 }
141

142 public long getId () {


143 return id ;
144 }
145

146 public Date getDate () {


147 return date ;
148 }
149
APPENDIX M. INVENTORY MANAGMENT AOP-APPLICATION 61

150 public boolean invoiceCreated () {


151 return invoiceCreated ;
152 }
153

154 public boolean equals ( Object obj ) {


155 boolean classesAreCompatible = this . getClass (). isAssignableFrom (
156 obj . getClass ());
157

158 if (! classesAreCompatible ) {
159 // does not work because of AOP remoting
160 // if ( obj . getClass () != this . getClass () ){
161 return false ;
162 }
163

164 if ((( Order ) obj ). getId () == id ) {


165 return true ;
166 }
167

168 return false ;


169 }
170 }
APPENDIX M. INVENTORY MANAGMENT AOP-APPLICATION 62

M.4 OrderList.java

Source of jboss.thesis.inventory.model.OrderList
1 package jboss . thesis . inventory . model ;
2

3 import jboss . thesis . inventory . controller . NoSuchOrderException ;


4

5 import java . rmi . Remote ;


6

7 import java . util . ArrayList ;


8 import java . util . Iterator ;
9

10

11 /**
12 * @author Christian Dalager , Simon Jorsal , Eske Sort
13 */
14 public class OrderList implements Remote {
15 private static OrderList instance ;
16 private ArrayList orders ;
17

18 public OrderList () {
19 orders = new ArrayList ();
20 }
21

22 public static OrderList instance () {


23 if ( instance == null ) {
24 instance = new OrderList ();
25 }
26

27 return instance ;
28 }
29

30 public void add ( Order order ) {


31 orders . add ( order );
32 }
33

34 public Order get ( int index ) {


35 Order order = null ;
36

37 try {
38 order = ( Order ) orders . get ( index );
39 }
40 catch ( IndexOutOfBoundsException ignored ) {
41 // if index is invalid , just return null
42 }
43

44 return order ;
45 }
46

47 public Order getOrder ( long id ) throws NoSuchOrderException {


APPENDIX M. INVENTORY MANAGMENT AOP-APPLICATION 63

48 Iterator i = orders . iterator ();


49

50 while (i. hasNext ()) {


51 Order temp = ( Order ) i. next ();
52

53 if ( temp . getId () == id ) {
54 return temp ;
55 }
56 }
57

58 throw new NoSuchOrderException (" No order with ID : " + id );


59 }
60

61 public int size () {


62 return orders . size ();
63 }
64

65 public void remove ( Order o ) {


66 orders . remove (o );
67 }
68 }
APPENDIX M. INVENTORY MANAGMENT AOP-APPLICATION 64

M.5 Product.java

Source of jboss.thesis.inventory.model.Product
1 package jboss . thesis . inventory . model ;
2

3 import java . io . Serializable ;


4

6 /**
7 * An Product is a representation of a concrete product ( such as an IBM
8 * Deskstar 75 GXP HDD ). < br >
9 * The name should be the name of the product as stated by the manufacturer .
10 * <br >
11 * The description contains all relevant information about the product , that
12 * is not stated in its name , manufacturer information , price or Type .<br >
13 * The manufacturer is the company that manufactors this product .<br >
14 * The price is the price of the product . < br >
15 * The Type is the group into which this product belongs - for example the
16 * IBM Deskstar 75 GXP falls into the category / group HDD .
17 *
18 * @author Christian Dalager , Simon Jorsal , Eske Sort
19 */
20 public interface Product extends Serializable {
21 public long getId ();
22

23 public void setName ( String name );


24

25 public void setType ( Type type );


26

27 public void setDescription ( String description );


28

29 public void setManufacturer ( String manufacturer );


30

31 public void setPrice ( double price );


32

33 public int getStock ();


34

35 public void increaseStockBy ( int number );


36

37 public void decreaseStockBy ( int number );


38

39 /**
40 * Gets the name of this product . The name can be the name of a single
41 * Product or an ProductComposite .
42 *
43 * @return the name of the Product or ProductComposite .
44 */
45 public String getName ();
46

47 /**
APPENDIX M. INVENTORY MANAGMENT AOP-APPLICATION 65

48 * Gets the type of this product . The Type can both describe an Product or a
49 * ProductComposite .
50 *
51 * @return the Type of this Product or ProductComposite .
52 */
53 public Type getType ();
54

55 /**
56 * Gets the description of this product . This describes the Product or the
57 * ProductComposite .
58 *
59 * @return the decription of this Product or ProductComposite .
60 */
61 public String getDescription ();
62

63 /**
64 * Gets the manufacturer of this Product . This should probably be in the
65 * form of some Company object , but for the sake of simplicity , it is just
66 * a String representation here .
67 *
68 * @return a String representing the manufacturer of this Product .
69 */
70 public String getManufacturer ();
71

72 /**
73 * Gets the price of this Product . If the Product is an ProductComposite the
74 * price is calculated form all the Products contained in the
75 * ProductComposite . The price should probably be contained in some Price
76 * object , where VAT etc . can be part of it . For simplicity s sake it is
77 * just a double here .
78 *
79 * @return a double with the price of this Product .
80 */
81 public double getPrice ();
82

83 /**
84 * Sets the ID of this Product . It does so by calling the IdUtil . getNextId (
85 * IdUtil . ITEM ) method .
86 *
87 * @return the id this Product acquired .
88 */
89 public long setId ();
90 }
APPENDIX M. INVENTORY MANAGMENT AOP-APPLICATION 66

M.6 ProductImpl.java

Source of jboss.thesis.inventory.model.ProductImpl
1 package jboss . thesis . inventory . model ;
2

4 /**
5 * Represents a Product .
6 *
7 * @author Christian Dalager , Simon Jorsal , Eske Sort
8 */
9 public class ProductImpl implements jboss . thesis . inventory . model . Product ,
10 java . rmi . Remote {
11 private long id ;
12 private String name ;
13 private Type type ;
14 private String description ;
15 private String manufacturer ;
16 private double price ;
17 private int stock ;
18

19 public ProductImpl () {
20 super ();
21 }
22

23 public ProductImpl ( String name ) {


24 super ();
25 this . name = name ;
26 }
27

28 public long setId () {


29 id = IdUtil . getNextId ( IdUtil . PRODUCT );
30

31 return id ;
32 }
33

34 public void setName ( String name ) {


35 this . name = name ;
36 }
37

38 public long getId () {


39 return id ;
40 }
41

42 public void setType ( Type type ) {


43 this . type = type ;
44 }
45

46 public void setDescription ( String description ) {


47 this . description = description ;
APPENDIX M. INVENTORY MANAGMENT AOP-APPLICATION 67

48 }
49

50 public void setManufacturer ( String manufacturer ) {


51 this . manufacturer = manufacturer ;
52 }
53

54 public void setPrice ( double price ) {


55 this . price = price ;
56 }
57

58 public String getName () {


59 return name ;
60 }
61

62 public Type getType () {


63 return type ;
64 }
65

66 public String getDescription () {


67 return description ;
68 }
69

70 public String getManufacturer () {


71 return manufacturer ;
72 }
73

74 public double getPrice () {


75 return price ;
76 }
77

78 public int getStock () {


79 return stock ;
80 }
81

82 public void setStock ( int stock ) {


83 this . stock = stock ;
84 }
85

86 public String toString () {


87 return " Product :" + getName ();
88 }
89

90 public void decreaseStockBy ( int number ) {


91 stock = stock - number ;
92 }
93

94 public void increaseStockBy ( int number ) {


95 stock = stock + number ;
96 }
97

98 public boolean equals ( Object obj ) {


APPENDIX M. INVENTORY MANAGMENT AOP-APPLICATION 68

99 /*
100 With AOP remoting :
101 ( this . equals ( productImpl ))
102 this . class = jboss . thesis . inventory . model . ProductImpl
103 obj . class = org . jboss . aop . proxy$jboss . thesis . inventory . model . ProductImpl
104 Where obj extends this
105 */
106

107 // is this . class the same as , or superclass or superinterface of


108 // obj . class ?
109 boolean classesAreCompatible = this . getClass (). isAssignableFrom (
110 obj . getClass ());
111

112 if (! classesAreCompatible ) {
113 // does not work because of AOP remoting
114 // if ( obj . getClass () != this . getClass () ){
115 return false ;
116 }
117

118 if ((( Product ) obj ). getId () == id ) {


119 return true ;
120 }
121

122 return false ;


123 }
124

125 public int hashCode () {


126 return ( int ) id ;
127 }
128 }
APPENDIX M. INVENTORY MANAGMENT AOP-APPLICATION 69

M.7 ProductComposite.java

Source of jboss.thesis.inventory.model.ProductComposite
1 package jboss . thesis . inventory . model ;
2

3 import java . util . ArrayList ;


4 import java . util . Iterator ;
5

7 /**
8 * @author Christian Dalager , Simon Jorsal , Eske Sort
9 */
10 public class ProductComposite implements Product , java . io . Serializable ,
11 java . rmi . Remote {
12 private long id ;
13 private String name ;
14 private Type type ;
15 private String description ;
16 private String manufacturer ;
17 private double price ;
18 private ArrayList products = new ArrayList ();
19

20 public ProductComposite () {
21 super ();
22 }
23

24 public ProductComposite ( String name ) {


25 super ();
26 this . name = name ;
27 }
28

29 public long setId () {


30 id = IdUtil . getNextId ( IdUtil . PRODUCT );
31

32 return id ;
33 }
34

35 public void add ( Product product ) {


36 // Disallow cyclic references
37 if (! product . equals ( this )) {
38 products . add ( product );
39 }
40 }
41

42 public long getId () {


43 return id ;
44 }
45

46 public Product get ( int index ) {


47 return ( Product ) products . get ( index );
APPENDIX M. INVENTORY MANAGMENT AOP-APPLICATION 70

48 }
49

50 public int numberOfProducts () {


51 return products . size ();
52 }
53

54 public void setName ( String name ) {


55 this . name = name ;
56 }
57

58 public void setType ( Type type ) {


59 this . type = type ;
60 }
61

62 public void setDescription ( String description ) {


63 this . description = description ;
64 }
65

66 public void setManufacturer ( String manufacturer ) {


67 this . manufacturer = manufacturer ;
68 }
69

70 public void setPrice ( double price ) {


71 this . price = price ;
72 }
73

74 public String getName () {


75 return name ;
76 }
77

78 public Type getType () {


79 return type ;
80 }
81

82 public String getDescription () {


83 return description ;
84 }
85

86 public String getManufacturer () {


87 return manufacturer ;
88 }
89

90 public double getPrice () {


91 return price ;
92 }
93

94 public int getStock () {


95 int minStock = -1;
96 Iterator i = products . iterator ();
97

98 while (i. hasNext ()) {


APPENDIX M. INVENTORY MANAGMENT AOP-APPLICATION 71

99 if ( minStock != -1) {
100 minStock = Math . min ((( Product ) i. next ()). getStock () , minStock );
101 }
102 else {
103 minStock = (( Product ) i. next ()). getStock ();
104 }
105 }
106

107 return minStock ;


108 }
109

110 public String toString () {


111 return " ProductComposite ={" + products + "}";
112 }
113

114 public void decreaseStockBy ( int number ) {


115 Iterator i = products . iterator ();
116

117 while (i. hasNext ()) {


118 (( Product ) i. next ()). decreaseStockBy ( number );
119 }
120 }
121

122 public void increaseStockBy ( int number ) {


123 Iterator i = products . iterator ();
124

125 while (i. hasNext ()) {


126 (( Product ) i. next ()). increaseStockBy ( number );
127 }
128 }
129

130 public boolean equals ( Object obj ) {


131 boolean classesAreCompatible = this . getClass (). isAssignableFrom (
132 obj . getClass ());
133

134 if (! classesAreCompatible ) {
135 return false ;
136 }
137

138 if ((( Product ) obj ). getId () == id ) {


139 return true ;
140 }
141

142 return false ;


143 }
144

145 public int hashCode () {


146 return ( int ) id ;
147 }
148 }
APPENDIX M. INVENTORY MANAGMENT AOP-APPLICATION 72

M.8 Reservation.java

Source of jboss.thesis.inventory.model.Reservation
1 package jboss . thesis . inventory . model ;
2

3 import java . rmi . Remote ;


4

6 /**
7 * @author Christian Dalager , Simon Jorsal , Eske Sort
8 */
9 public class Reservation implements Remote {
10 private long id ;
11 private int quantity ;
12 private Product product ;
13

14 public Reservation () {}
15

16 public long getId () {


17 return id ;
18 }
19

20 public long setId () {


21 id = IdUtil . getNextId ( IdUtil . RESERVATION );
22

23 return id ;
24 }
25

26 public double getPrice () {


27 return product . getPrice () * quantity ;
28 }
29

30 public Product getProduct () {


31 return product ;
32 }
33

34 /**
35 * Sets the Product reserved . The Product designates which product is
36 * reserved . Use the { @link setQuantity } method to set how many Products
37 * are actally reserved .
38 *
39 * @param product the product to set .
40 */
41 public void setProduct ( Product product ) {
42 this . product = product ;
43 }
44

45 public int getQuantity () {


46 return quantity ;
47 }
APPENDIX M. INVENTORY MANAGMENT AOP-APPLICATION 73

48

49 /**
50 * Sets how many Products are reserved via this Reservation . The actual type
51 * of Product reserved is set via the method { @link setProduct }.
52 *
53 * @param quantity the quantity of Products to reserve
54 */
55 public void setQuantity ( int quantity ) {
56 this . quantity = quantity ;
57 }
58

59 public boolean equals ( Object obj ) {


60 // is this . class the same as , or superclass or superinterface of
61 // obj . class ?
62 boolean classesAreCompatible = this . getClass (). isAssignableFrom (
63 obj . getClass ());
64

65 if (! classesAreCompatible ) {
66 // Does not work because of AOP remoting :
67 // if ( obj . getClass () != this . getClass () ){
68 return false ;
69 }
70

71 if ((( Reservation ) obj ). getId () == id ) {


72 return true ;
73 }
74

75 return false ;
76 }
77 }
APPENDIX M. INVENTORY MANAGMENT AOP-APPLICATION 74

M.9 Type.java

Source of jboss.thesis.inventory.model.Type
1 /*
2 * Created on 02 -10 -2003
3 */
4 package jboss . thesis . inventory . model ;
5

7 /**
8 * A Type represents a group of units . It could be for example CPUs , HDDs or
9 * similiar . The name of the Type should categorise the units such
10 * as name = & quot ; CPU & quot ;. < br >
11 * The description should describe common characteristica of the group
12 * designated by the name .
13 *
14 * @author Christian Dalager , Simon Jorsal , Eske Sort
15 */
16 public class Type implements java . rmi . Remote {
17 private long id ;
18 private String name ;
19 private String description ;
20

21 public Type () {}
22

23 public long getId () {


24 return id ;
25 }
26

27 public long setId () {


28 id = IdUtil . getNextId ( IdUtil . TYPE );
29

30 return id ;
31 }
32

33 /**
34 * Gets the description that characterizes this Type .
35 *
36 * @return a String with the description .
37 */
38 public String getDescription () {
39 return description ;
40 }
41

42 /**
43 * Gets the name of this Type . The name should characterize a group of units
44 * ie . CPU or HDD .
45 *
46 * @return
47 */
APPENDIX M. INVENTORY MANAGMENT AOP-APPLICATION 75

48 public String getName () {


49 return name ;
50 }
51

52 /**
53 * Sets the descripton of this Type .
54 *
55 * @param description the description that describes the group of units
56 * designated by the name field .
57 */
58 public void setDescription ( String description ) {
59 this . description = description ;
60 }
61

62 /**
63 * Sets the name of this Type . The name should characterize a group of units
64 * - such as CPU or HDD .
65 *
66 * @param name the name that designates this Type ( or group of units ).
67 */
68 public void setName ( String name ) {
69 this . name = name ;
70 }
71

72 public String toString () {


73 return name + " , " + description ;
74 }
75 }
Appendix N

Inventory Management
Application Controller

All classes below are part of the jboss.thesis.inventory.controller package.

N.1 CreationException.java

Source of jboss.thesis.inventory.controller.CreationException
1

2 package jboss . thesis . inventory . controller ;


3

4 /**
5 * @author Christian Dalager , Simon Jorsal , Eske Sort
6 */
7 public class CreationException extends Exception {
8 public CreationException () {
9 super ();
10 }
11

12 public CreationException ( String msg ) {


13 super ( msg );
14 }
15

16 public CreationException ( String msg , Throwable cause ) {


17 super (msg , cause );
18 }
19

20 public CreationException ( Throwable cause ) {


21 super ( cause );
22 }
23 }

76
APPENDIX N. INVENTORY MANAGEMENT APPLICATION CONTROLLER 77

N.2 InventoryController.java

Source of jboss.thesis.inventory.controller.InventoryController
1 package jboss . thesis . inventory . controller ;
2

3 import jboss . thesis . inventory . model . IdUtil ;


4 import jboss . thesis . inventory . model . Order ;
5 import jboss . thesis . inventory . model . OrderList ;
6 import jboss . thesis . inventory . model . Product ;
7

8 import org . jboss . aop . Dispatcher ;


9 import org . jboss . aop . remoting . Remoting ;
10

11 import java . rmi . Remote ;


12

13 import java . util . ArrayList ;


14 import java . util . Iterator ;
15 import java . util . List ;
16

17 import javax . naming . InitialContext ;


18 import javax . naming . NamingException ;
19

20

21 /**
22 * @author Simon Jorsal , Eske Sort , Christian Dalager .
23 */
24 public class InventoryController implements Remote {
25 static InventoryController me ;
26 OrderList orders ;
27 List products = new ArrayList ();
28

29 public InventoryController () {
30 orders = OrderList . instance ();
31 }
32

33 public static InventoryController instance () {


34 if ( me == null ) {
35 me = new InventoryController ();
36 }
37

38 return me ;
39 }
40

41 /**
42 * This method should only be called by server - side components ! Otherwise
43 * this will throw strange NullPointerExceptions and other
44 * AOP - Remoting - hard -to -see - through errors .
45 */
46 public List getProducts () {
47 return products ;
APPENDIX N. INVENTORY MANAGEMENT APPLICATION CONTROLLER 78

48 }
49

50 /**
51 * This method should only be called by server - side components ! Otherwise
52 * this will throw strange NullPointerExceptions and other
53 * AOP - Remoting - hard -to -see - through errors .
54 */
55 public OrderList getOrders () {
56 return orders ;
57 }
58

59 public Product getProduct ( int index ) {


60 Product product = null ;
61

62 try {
63 product = ( Product ) products . get ( index );
64 }
65 catch ( IndexOutOfBoundsException e ) {
66 // just return null
67 }
68

69 return product ;
70 }
71

72 public Product getProduct ( long productid ) {


73 Iterator i = products . iterator ();
74

75 while (i. hasNext ()) {


76 Product p = ( Product ) i. next ();
77

78 if (p. getId () == productid ) {


79 return p;
80 }
81 }
82

83 return null ;
84 }
85

86 public Order getOrder ( int index ) {


87 Order order = null ;
88

89 try {
90 order = ( Order ) orders . get ( index );
91 }
92 catch ( IndexOutOfBoundsException e ) {
93 // just return null
94 }
95

96 return order ;
97 }
98
APPENDIX N. INVENTORY MANAGEMENT APPLICATION CONTROLLER 79

99 public int getNumberOfProducts () {


100 int number = 0;
101

102 if ( products != null ) {


103 number = products . size ();
104 }
105

106 if ( number < 0) {


107 number = 0;
108 }
109

110 return number ;


111 }
112

113 public int getNumberOfOrders () {


114 int number = 0;
115

116 if ( orders != null ) {


117 number = orders . size ();
118 }
119

120 if ( number < 0) {


121 number = 0;
122 }
123

124 return number ;


125 }
126

127 public void addOrder ( Order order ) {


128 orders . add ( order );
129 }
130

131 public void addProduct ( Product product ) {


132 products . add ( product );
133 }
134

135 public void removeOrder ( Order order ) {


136 orders . remove ( order );
137 }
138

139 public void removeProduct ( Product product ) {


140 products . remove ( product );
141 }
142

143 private static Object createAndRegisterProxy (


144 Object original ,
145 String uniqueId ,
146 boolean registerInJNDI ) throws CreationException {
147 Object proxy = null ;
148

149 try {
APPENDIX N. INVENTORY MANAGEMENT APPLICATION CONTROLLER 80

150 // Create the proxy for the Product object :


151 proxy = Remoting . createRemoteProxy (
152 uniqueId ,
153 original . getClass () ,
154 RemoteUtil . CONNECT_URL );
155 }
156 catch ( Exception e ) {
157 throw new CreationException (e );
158 }
159

160 try {
161 if ( registerInJNDI ) {
162 // Bind the proxy in JNDI :
163 new InitialContext (). rebind ( uniqueId , proxy );
164 }
165 }
166 catch ( NamingException e ) {
167 e. printStackTrace ();
168 throw new CreationException (e );
169 }
170

171 // Register the real product with the Dispatcher :


172 Dispatcher . singleton . registerTarget ( uniqueId , original );
173

174 return proxy ;


175 }
176

177 public long getCurrentProductId () {


178 return IdUtil . getCurrentId ( IdUtil . PRODUCT );
179 }
180

181 public long getCurrentOrderId () {


182 return IdUtil . getCurrentId ( IdUtil . ORDER );
183 }
184

185 public long getCurrentCustomerId () {


186 return IdUtil . getCurrentId ( IdUtil . CUSTOMER );
187 }
188

189 public long getCurrentReservationId () {


190 return IdUtil . getCurrentId ( IdUtil . RESERVATION );
191 }
192

193 public long getCurrentTypeId () {


194 return IdUtil . getCurrentId ( IdUtil . TYPE );
195 }
196 }
APPENDIX N. INVENTORY MANAGEMENT APPLICATION CONTROLLER 81

N.3 InventoryFactory.java

Source of jboss.thesis.inventory.controller.InventoryFactory
1 package jboss . thesis . inventory . controller ;
2

3 import jboss . thesis . inventory . model . Customer ;


4 import jboss . thesis . inventory . model . Order ;
5 import jboss . thesis . inventory . model . Product ;
6 import jboss . thesis . inventory . model . ProductComposite ;
7 import jboss . thesis . inventory . model . ProductImpl ;
8 import jboss . thesis . inventory . model . Reservation ;
9 import jboss . thesis . inventory . model . Type ;
10

11 import org . jboss . aop . Dispatcher ;


12 import org . jboss . aop . remoting . Remoting ;
13

14 import org . jboss . logging . Logger ;


15

16 import java . rmi . Remote ;


17

18 import javax . naming . InitialContext ;


19 import javax . naming . NamingException ;
20

21

22 /**
23 * @author Christian Dalager , Simon Jorsal , Eske Sort
24 */
25 public class InventoryFactory implements Remote {
26 private static Logger log = Logger . getLogger ( InventoryFactory . class );
27 private static InventoryFactory instance ;
28

29 public InventoryFactory () {}
30

31 public static InventoryFactory instance () {


32 if ( instance == null ) {
33 instance = new InventoryFactory ();
34 }
35

36 return instance ;
37 }
38

39 public Product createProductImpl ( String name ) throws CreationException {


40 Product product = new ProductImpl ( name );
41 product . setId ();
42

43 String uniqueId = " product " + product . getId ();


44 Product proxy = ( Product ) createAndRegisterProxy ( product , uniqueId , false );
45 log . debug (
46 " Created an product with id =" + product . getId () +
47 " , name registered with Dispatcher =" + uniqueId + " , class =" +
APPENDIX N. INVENTORY MANAGEMENT APPLICATION CONTROLLER 82

48 product . getClass (). getName ());


49

50 return proxy ;
51 }
52

53 public Product createProductImpl () throws CreationException {


54 return createProductImpl ("");
55 }
56

57 public Product createProductComposite ( String name ) throws CreationException {


58 Product product = new ProductComposite ( name );
59 product . setId ();
60

61 String uniqueId = " product " + product . getId ();


62 Product proxy = ( Product ) createAndRegisterProxy ( product , uniqueId , false );
63 log . debug (
64 " Created a product with id =" + product . getId () +
65 " , name registered with Dispatcher =" + uniqueId + " , class =" +
66 product . getClass (). getName ());
67

68 return proxy ;
69 }
70

71 public Product createProductComposite () throws CreationException {


72 return createProductComposite ("");
73 }
74

75 public Order createOrder () throws CreationException {


76 Order order = new Order ();
77 order . setId ();
78

79 String uniqueId = " order " + order . getId ();


80 Order proxy = ( Order ) createAndRegisterProxy ( order , uniqueId , false );
81 log . debug (
82 " Created an Order with id =" + order . getId () +
83 " , name registered with Dispatcher =" + uniqueId + " , class =" +
84 order . getClass (). getName ());
85

86 return proxy ;
87 }
88

89 public Reservation createReservation () throws CreationException {


90 Reservation reservation = new Reservation ();
91 reservation . setId ();
92

93 String uniqueId = " reservation " + reservation . getId ();


94 Reservation proxy = ( Reservation ) createAndRegisterProxy (
95 reservation , uniqueId , false );
96 log . debug (
97 " Created a reservation with id =" + reservation . getId () +
98 " , name registered with Dispatcher =" + uniqueId + " , class =" +
APPENDIX N. INVENTORY MANAGEMENT APPLICATION CONTROLLER 83

99 reservation . getClass (). getName ());


100

101 return proxy ;


102 }
103

104 public Type createType () throws CreationException {


105 Type type = new Type ();
106 type . setId ();
107

108 String uniqueId = " type " + type . getId ();


109 Type proxy = ( Type ) createAndRegisterProxy ( type , uniqueId , false );
110 log . debug (
111 " Created a Type with id =" + type . getId () +
112 " , name registered with Dispatcher =" + uniqueId + " , class =" +
113 type . getClass (). getName ());
114

115 return proxy ;


116 }
117

118 public Customer createCustomer () throws CreationException {


119 Customer customer = new Customer ();
120 customer . setId ();
121

122 String uniqueId = " customer " + customer . getId ();


123 Customer proxy = ( Customer ) createAndRegisterProxy (
124 customer , uniqueId , false );
125 log . debug (
126 " Created an OrderList with id =" + customer . getId () +
127 " , name registered with Dispatcher =" + uniqueId + " , class =" +
128 customer . getClass (). getName ());
129

130 return proxy ;


131 }
132

133 private static Object createAndRegisterProxy (


134 Object original , String uniqueId , boolean registerInJNDI )
135 throws CreationException {
136 Object proxy = null ;
137

138 try {
139 // Create the proxy for the Product object :
140 proxy = Remoting . createRemoteProxy (
141 uniqueId , original . getClass () , RemoteUtil . CONNECT_URL );
142 }
143 catch ( Exception e ) {
144 throw new CreationException (e );
145 }
146

147 try {
148 if ( registerInJNDI ) {
149 // Bind the proxy in JNDI :
APPENDIX N. INVENTORY MANAGEMENT APPLICATION CONTROLLER 84

150 new InitialContext (). rebind ( uniqueId , proxy );


151 }
152 }
153 catch ( NamingException e ) {
154 e. printStackTrace ();
155 throw new CreationException (e );
156 }
157

158 // Register the real product with the Dispatcher :


159 Dispatcher . singleton . registerTarget ( uniqueId , original );
160

161 return proxy ;


162 }
163

164 public ProductImpl getLocalProductImpl ( long productId ) {


165 return ( ProductImpl ) Dispatcher . singleton . getRegistered (
166 " product " + productId );
167 }
168

169 public ProductComposite getLocalProductComposite ( long productId ) {


170 return ( ProductComposite ) Dispatcher . singleton . getRegistered (
171 " product " + productId );
172 }
173

174 public Product getLocalProduct ( long productId ) {


175 return ( Product ) Dispatcher . singleton . getRegistered (" product " + productId );
176 }
177 }
APPENDIX N. INVENTORY MANAGEMENT APPLICATION CONTROLLER 85

N.4 NoSuchOrderException.java

Source of jboss.thesis.inventory.controller.NoSuchOrderException
1 package jboss . thesis . inventory . controller ;
2

3 /**
4 * @author Christian Dalager , Simon Jorsal , Eske Sort
5 */
6 public class NoSuchOrderException extends Exception {
7 public NoSuchOrderException () {
8 super ();
9 }
10

11 public NoSuchOrderException ( String msg ) {


12 super ( msg );
13 }
14 }
APPENDIX N. INVENTORY MANAGEMENT APPLICATION CONTROLLER 86

N.5 RemoteUtil.java

Source of jboss.thesis.inventory.controller.RemoteUtil
1 package jboss . thesis . inventory . controller ;
2

3 import jboss . thesis . inventory . model . OrderList ;


4

5 import org . jboss . logging . Logger ;


6

7 import java . util . Hashtable ;


8

9 import javax . naming . Context ;


10 import javax . naming . InitialContext ;
11 import javax . naming . NamingException ;
12

13

14 /**
15 * @author Christian Dalager , Simon Jorsal , Eske Sort
16 */
17 public class RemoteUtil {
18 public static final String CONNECT_URL = " socket :// localhost :5150";
19

20 // public static final String CONNECT_URL = " socket ://10.0.0.3:5150";


21 private static Logger log = Logger . getLogger ( RemoteUtil . class );
22

23 public static InventoryController getController () throws NamingException {


24 return ( InventoryController ) getRemoteProxy (" inventoryController ");
25 }
26

27 public static InventoryFactory getFactory () throws NamingException {


28 return ( InventoryFactory ) getRemoteProxy (" inventoryFactory ");
29 }
30

31 public static OrderList getOrderList () throws NamingException {


32 return ( OrderList ) getRemoteProxy (" orderList ");
33 }
34

35 private static Object getRemoteProxy ( String proxyId )


36 throws NamingException {
37 Object value = null ;
38

39 try {
40 // value = getInitialContext (). lookup ( proxyId );
41 value = new InitialContext (). lookup ( proxyId );
42 }
43 catch ( Exception e1 ) {
44 System . out . println (" Exception in getRemoteProxy ");
45 log . debug ("" + e1 . getCause ());
46 e1 . printStackTrace ();
47 // throw e1 ;
APPENDIX N. INVENTORY MANAGEMENT APPLICATION CONTROLLER 87

48 }
49

50 return value ;
51 }
52

53 private static InitialContext getInitialContext () {


54 Hashtable props = new Hashtable ();
55 props . put ( Context . INITIAL_CONTEXT_FACTORY ,
56 " org . jnp . interfaces . NamingContextFactory ");
57

58 // props . put ( Context . PROVIDER_URL , " jnp :// localhost ");


59 // props . put (" java . naming . rmi . security . manager " , " yes ");
60 props . put ( Context . URL_PKG_PREFIXES , " org . jboss . naming : org . jnp . interfaces ");
61

62 InitialContext ctx = null ;


63

64 try {
65 ctx = new InitialContext ( props );
66 }
67 catch ( Exception e1 ) {
68 log . debug (" Got a NamingException :" + e1 . getCause ());
69 e1 . printStackTrace ();
70 }
71

72 return ctx ;
73 }
74 }
Appendix O

Inventory Management
AOP-services

All classes below are part of the jboss.thesis.inventory.service and jboss.the-


sis.inventory.service.logging packages.

O.1 DecrementReservationInterceptor.java

Source of jboss.thesis.inventory.service.DecrementReservationInterceptor
1 package jboss . thesis . inventory . service ;
2

3 import jboss . thesis . inventory . controller . InventoryFactory ;


4 import jboss . thesis . inventory . model . Product ;
5

6 import org . jboss . aop . Interceptor ;


7 import org . jboss . aop . Invocation ;
8 import org . jboss . aop . InvocationType ;
9 import org . jboss . aop . MethodInvocation ;
10

11

12 /**
13 * @author Christian Dalager , Simon Jorsal , Eske Sort
14 *
15 */
16 public class DecrementReservationInterceptor implements Interceptor {
17 private InventoryFactory factory = InventoryFactory . instance ();
18

19 public DecrementReservationInterceptor() {
20 super ();
21 }
22

88
APPENDIX O. INVENTORY MANAGEMENT AOP-SERVICES 89

23 public String getName () {


24 return " DecrementReservationInterceptor";
25 }
26

27 public Object invoke ( Invocation inv ) throws Throwable {


28 if ( inv . getType () == InvocationType . METHOD ) {
29 MethodInvocation minv = ( MethodInvocation ) inv ;
30 Product productProxy = ( Product ) inv . targetObject ;
31 Product realProduct = factory . getLocalProduct ( productProxy . getId ());
32 ReservationCounter rs = ( ReservationCounter ) realProduct ;
33 int decrementBy = (( Integer ) minv . arguments [0]). intValue ();
34 rs . decrementReservations ( decrementBy );
35 }
36

37 return inv . invokeNext ();


38 }
39 }
APPENDIX O. INVENTORY MANAGEMENT AOP-SERVICES 90

O.2 IncrementReservationInterceptor.java

Source of jboss.thesis.inventory.service.IncrementReservationInterceptor
1 package jboss . thesis . inventory . service ;
2

3 import jboss . thesis . inventory . controller . InventoryFactory ;


4 import jboss . thesis . inventory . model . Product ;
5 import jboss . thesis . inventory . model . Reservation ;
6

7 import org . jboss . aop . Interceptor ;


8 import org . jboss . aop . Invocation ;
9 import org . jboss . aop . InvocationType ;
10 import org . jboss . aop . MethodInvocation ;
11

12 import org . jboss . logging . Logger ;


13

14

15 /**
16 * @author Christian Dalager , Simon Jorsal , Eske Sort
17 */
18 public class IncrementReservationInterceptor implements Interceptor {
19 private Logger log = Logger . getLogger ( IncrementReservationInterceptor. class );
20 private InventoryFactory factory = InventoryFactory . instance ();
21

22 public String getName () {


23 return " IncrementReservationInterceptor";
24 }
25

26 public Object invoke ( Invocation inv ) throws Throwable {


27 if ( inv . getType () == InvocationType . METHOD ) {
28 MethodInvocation invocation = ( MethodInvocation ) inv ;
29 Reservation res = ( Reservation ) invocation . targetObject ;
30 Product productProxy = res . getProduct ();
31 Product realProduct = factory . getLocalProduct ( productProxy . getId ());
32 ReservationCounter p = ( ReservationCounter ) realProduct ;
33

34 int newValue = (( Integer ) invocation . arguments [0]). intValue ();


35 int oldQuantity = res . getQuantity ();
36 int total = p. getNumberOfReservations () + ( newValue - oldQuantity );
37

38 if ( log . isDebugEnabled ()) {


39 log . debug (
40 " Incrementing number of reservations of the Product : " +
41 realProduct . getName ());
42 log . debug (" The number of products to be reserved : " + newValue );
43 log . debug (
44 " The number of products reserved until now in this Reservation : " +
45 oldQuantity );
46 log . debug (
47 " The previous total amount of reservations " +
APPENDIX O. INVENTORY MANAGEMENT AOP-SERVICES 91

48 "( in all Reservations ) made for " + realProduct . getName () + ": " +
49 p. getNumberOfReservations ());
50 log . debug (
51 " The new total amount of reservations for " + realProduct . getName () +
52 ": " + total );
53 }
54

55 p. incrementReservations ( newValue - oldQuantity );


56 }
57

58 return inv . invokeNext ();


59 }
60 }
APPENDIX O. INVENTORY MANAGEMENT AOP-SERVICES 92

O.3 MinimumStock.java

Source of jboss.thesis.inventory.service.MinimumStock
1 package jboss . thesis . inventory . service ;
2

4 /**
5 * @author Christian Dalager , Simon Jorsal , Eske Sort
6 *
7 */
8 public interface MinimumStock {
9 public int getMinimumStock ();
10

11 public void setMinimumStock ( int stock );


12 }
APPENDIX O. INVENTORY MANAGEMENT AOP-SERVICES 93

O.4 MinimumStockInterceptor.java

Source of jboss.thesis.inventory.service.MinimumStockInterceptor
1 package jboss . thesis . inventory . service ;
2

3 import jboss . thesis . inventory . controller . InventoryFactory ;


4 import jboss . thesis . inventory . model . Product ;
5 import jboss . thesis . inventory . model . Reservation ;
6

7 import org . jboss . aop . Interceptor ;


8 import org . jboss . aop . Invocation ;
9 import org . jboss . aop . InvocationType ;
10 import org . jboss . aop . MethodInvocation ;
11

12 import org . jboss . logging . Logger ;


13

14

15 /**
16 * @author Christian Dalager , Simon Jorsal , Eske Sort
17 *
18 */
19 public class MinimumStockInterceptor implements Interceptor {
20 private Logger log = Logger . getLogger ( MinimumStockInterceptor . class );
21 private InventoryFactory factory = InventoryFactory . instance ();
22

23 public MinimumStockInterceptor () {
24 super ();
25 }
26

27 public String getName () {


28 return " MinimumStockInterceptor ";
29 }
30

31 public Object invoke ( Invocation inv ) throws Throwable {


32 if ( inv . getType () == InvocationType . METHOD ) {
33 MethodInvocation invocation = ( MethodInvocation ) inv ;
34 Reservation res = ( Reservation ) invocation . targetObject ;
35 Product productProxy = res . getProduct ();
36 Product p = factory . getLocalProduct ( productProxy . getId ());
37

38 int currentStock = p. getStock ();


39 int minimumStock = dirtyCast (p ). getMinimumStock ();
40 int numOfRes = dirtyToRC (p ). getNumberOfReservations ();
41 int reservationQuantity = (( Integer ) invocation . arguments [0]). intValue ();
42

43 if ( currentStock - reservationQuantity - numOfRes < minimumStock ) {


44 if ( log . isInfoEnabled ()) {
45 log . info (
46 " The Reservation ( id =" + res . getId () +
47 ") will get the stock below minimum stock of products !! " +
APPENDIX O. INVENTORY MANAGEMENT AOP-SERVICES 94

48 " See below for details :");


49 log . info (" Product : " + p. getName ());
50 log . info (" Current stock : " + currentStock );
51 log . info (" Minimum stock : " + minimumStock );
52 log . info (" Quantity of reservation : " + reservationQuantity );
53 log . info (" Total number of reservations : " + numOfRes );
54 }
55 }
56 }
57

58 return inv . invokeNext ();


59 }
60

61 private MinimumStock dirtyCast ( Object o ) {


62 return ( MinimumStock ) o;
63 }
64

65 private ReservationCounter dirtyToRC ( Object o ) {


66 return ( ReservationCounter ) o;
67 }
68 }
APPENDIX O. INVENTORY MANAGEMENT AOP-SERVICES 95

O.5 ProductCompositeMixin.java

Source of jboss.thesis.inventory.service.ProductCompositeMixin
1 package jboss . thesis . inventory . service ;
2

3 import jboss . thesis . inventory . controller . InventoryFactory ;


4 import jboss . thesis . inventory . model . Product ;
5 import jboss . thesis . inventory . model . ProductComposite ;
6

8 /**
9 * @author Christian Dalager , Simon Jorsal , Eske Sort
10 */
11 public class ProductCompositeMixin implements MinimumStock ,
12 ReservationCounter {
13 private ProductComposite proxyProduct ;
14 private InventoryFactory factory = InventoryFactory . instance ();
15 private int reservations = 0;
16

17 public ProductCompositeMixin ( Product proxyProduct ) {


18 this . proxyProduct = ( ProductComposite ) proxyProduct ;
19 }
20

21 public synchronized int getMinimumStock () {


22 ProductComposite realProduct = factory . getLocalProductComposite (
23 proxyProduct . getId ());
24

25 int numOfProducts = realProduct . numberOfProducts ();


26 int result = -1;
27

28 for ( int i = 0; i < numOfProducts ; i ++) {


29 long productId = realProduct . get (i ). getId ();
30 Product current = factory . getLocalProduct ( productId );
31 MinimumStock currentMinStockProduct = ( MinimumStock ) current ;
32 int minStock = currentMinStockProduct . getMinimumStock ();
33

34 if ( minStock < result ) {


35 result = minStock ;
36 }
37

38 if ( result == -1) {
39 result = minStock ;
40 }
41 }
42

43 return result ;
44 }
45

46 public void setMinimumStock ( int minimumStock ) {


47 ProductComposite realProduct = factory . getLocalProductComposite (
APPENDIX O. INVENTORY MANAGEMENT AOP-SERVICES 96

48 proxyProduct . getId ());


49

50 int numOfProducts = realProduct . numberOfProducts ();


51

52 for ( int i = 0; i < numOfProducts ; i ++) {


53 long productId = realProduct . get (i ). getId ();
54 Product current = factory . getLocalProduct ( productId );
55 MinimumStock currentMinStockProduct = ( MinimumStock ) current ;
56

57 synchronized ( this ) {
58 int minStock = currentMinStockProduct . getMinimumStock ();
59

60 if ( minStock < minimumStock ) {


61 currentMinStockProduct . setMinimumStock ( minimumStock );
62 }
63 }
64 }
65 }
66

67 /**
68 * This is a bit odd . Because of how this method is called through
69 * interception of the decreaseStockBy method in a ProductImpl and
70 * ProductComposite we do not call decrementReservation in the children .
71 * decreaseStockBy in ProductComposite calls decreaseStockBy in its
72 * children . This will be intercepted and the call to decrementReservations
73 * wil be made then .
74 *
75 * @see jboss . thesis . inventory . service . ReservationCounter #
76 * decrementReservations ( int )
77 */
78 public void decrementReservations ( int numOfReservations ) {
79 this . reservations -= numOfReservations ;
80

81 /*
82 // This is what would logically need to be done according to the
83 // JavaDoc comment above :
84 ProductComposite realProduct = factory . getLocalProductComposite (
85 proxyProduct . getId () );
86 int numOfProducts = realProduct . numberOfProducts ();
87

88 for ( int i = 0; i < numOfProducts ; i ++ ){


89 long productId = realProduct . get ( i ). getId ();
90 Product current = factory . getLocalProduct ( productId );
91 synchronized ( this ){
92 ReservationCounter currentResCounter = ( ReservationCounter ) current ;
93 currentResCounter . decrementReservations ( numOfReservations );
94 }
95 }
96 */
97 }
98
APPENDIX O. INVENTORY MANAGEMENT AOP-SERVICES 97

99 public void incrementReservations ( int numOfReservations ) {


100 ProductComposite realProduct = factory . getLocalProductComposite (
101 proxyProduct . getId ());
102 int numOfProducts = realProduct . numberOfProducts ();
103

104 for ( int i = 0; i < numOfProducts ; i ++) {


105 long productId = realProduct . get (i ). getId ();
106 Product current = factory . getLocalProduct ( productId );
107

108 synchronized ( this ) {


109 ReservationCounter currentResCounter = ( ReservationCounter ) current ;
110 currentResCounter . incrementReservations ( numOfReservations );
111 }
112 }
113

114 this . reservations += numOfReservations ;


115 }
116

117 public synchronized int getNumberOfReservations () {


118 return reservations ;
119 }
120 }
APPENDIX O. INVENTORY MANAGEMENT AOP-SERVICES 98

O.6 ProductConstructionInterceptor.java

Source of jboss.thesis.inventory.service.ProductConstructionInterceptor
1 package jboss . thesis . inventory . service ;
2

3 import jboss . thesis . inventory . controller . InventoryFactory ;


4 import jboss . thesis . inventory . model . Product ;
5 import jboss . thesis . inventory . model . Type ;
6

7 import org . jboss . aop . Advised ;


8 import org . jboss . aop . ClassInstanceAdvisor ;
9 import org . jboss . aop . Interceptor ;
10 import org . jboss . aop . Invocation ;
11 import org . jboss . aop . InvocationType ;
12 import org . jboss . aop . MethodInvocation ;
13 import org . jboss . aop . NotAdvisedException ;
14

15 import org . jboss . logging . Logger ;


16

17 import java . io . FileInputStream ;


18 import java . io . FileNotFoundException ;
19 import java . io . IOException ;
20

21 import java . util . Properties ;


22

23

24 /**
25 * This class intercept on a method - pointcut : product . setType ( Type t )
26 * Originally this interceptor should have been associated with a
27 * constructor - pointcut , but as the aop - remoting framework does not allow for
28 * constructors with arguments .
29 *
30 * @author Christian Dalager , Simon Jorsal , Eske Sort
31 */
32 public class ProductConstructionInterceptor implements Interceptor {
33 private Logger log = Logger . getLogger ( ProductConstructionInterceptor. class );
34 private InventoryFactory factory = InventoryFactory . instance ();
35

36 /**
37 * The method that s invoked on interception . Calls the next interceptor in
38 * the chain and eventually it will return the Object that it has received
39 * from that interceptor .
40 *
41 * @return the response from the next interceptor
42 */
43 public Object invoke ( Invocation inv ) throws Throwable {
44 if ( inv . getType () == InvocationType . METHOD ) {
45 MethodInvocation methodInv = ( MethodInvocation ) inv ;
46 Product target = ( Product ) methodInv . targetObject ;
47 Type productType = ( Type ) methodInv . arguments [0];
APPENDIX O. INVENTORY MANAGEMENT AOP-SERVICES 99

48 int minStock = getMinimumStock ( productType );


49

50 Product realProduct = factory . getLocalProduct ( target . getId ());


51 dirtyCast ( realProduct ). setMinimumStock ( minStock );
52

53 if ( log . isDebugEnabled ()) {


54 log . debug (" New product made of type " + productType . getName ());
55 log . debug (" The minimumStock is set to " + minStock );
56 }
57 }
58

59 return inv . invokeNext ();


60 }
61

62 private MinimumStock dirtyCast ( Object o ) {


63 return ( MinimumStock ) o;
64 }
65

66 /**
67 * Parses the property file from the loadConfiguration () method and returns
68 * the minimumStock for the Type t . If there is no value for the key t , a
69 * default value of 0 is returned .
70 *
71 * @param t
72 *
73 * @return default
74 */
75 private int getMinimumStock ( Type t ) {
76 Properties props = loadConfiguration ();
77 int retVal = 0;
78 String preparedKey = t. getName (). replaceAll (" " , ".");
79

80 if ( props . containsKey ( preparedKey )) {


81 retVal = Integer . parseInt ( props . getProperty ( preparedKey ));
82 }
83

84 return retVal ;
85 }
86

87 /**
88 * This method is a trick we apply to avoid using reflection
89 */
90 private ClassInstanceAdvisor getAdvisor ( Object o ) throws
91 NotAdvisedException {
92 Advised a = ( Advised ) o;
93

94 return ( ClassInstanceAdvisor ) a. _getInstanceAdvisor ();


95 }
96

97 /**
98 * Should intercept on a method - pointcut : product . setType ( Type t );
APPENDIX O. INVENTORY MANAGEMENT AOP-SERVICES 100

99 */
100 public String getName () {
101 return " ProductConstructionInterceptor";
102 }
103

104 /**
105 * Loads a property file with the initial minimumStock for each Type of
106 * Product
107 *
108 * @return Properties from file
109 */
110 private Properties loadConfiguration () {
111 Properties conf = new Properties ();
112 FileInputStream fis = null ;
113

114 try {
115 Properties sysProps = System . getProperties ();
116

117 String jbossServerHome = sysProps . getProperty (" jboss . server . base . dir ");
118

119 fis = new FileInputStream (


120 jbossServerHome + "/ default / conf / minimumstock . properties ");
121 conf . load ( fis );
122 }
123 catch ( FileNotFoundException ignored ) {
124 ignored . printStackTrace ();
125 }
126 catch ( IOException ignored ) {
127 ignored . printStackTrace ();
128 }
129 finally {
130 try {
131 fis . close ();
132 }
133 catch ( IOException ignored ) {}
134 }
135

136 return conf ;


137 }
138 }
APPENDIX O. INVENTORY MANAGEMENT AOP-SERVICES 101

O.7 ProductMixin.java

Source of jboss.thesis.inventory.service.ProductMixin
1 package jboss . thesis . inventory . service ;
2

3 import jboss . thesis . inventory . model . Product ;


4

6 /**
7 * @author Christian Dalager , Simon Jorsal , Eske Sort
8 */
9 public class ProductMixin implements MinimumStock , ReservationCounter {
10 private Product owner ;
11 private int minimumStock ;
12 private int reservations ;
13

14 public ProductMixin () {
15 super ();
16 }
17

18 public ProductMixin ( int minimumStock ) {


19 this ( null , minimumStock );
20 }
21

22 public ProductMixin ( Product owner , int minimumStock ) {


23 this . minimumStock = minimumStock ;
24 this . owner = owner ;
25 }
26

27 public ProductMixin ( Product owner , int minimumStock , int reservations ) {


28 this . minimumStock = minimumStock ;
29 this . reservations = reservations ;
30 this . owner = owner ;
31 }
32

33 public int getMinimumStock () {


34 return minimumStock ;
35 }
36

37 public void setMinimumStock ( int minimumStock ) {


38 this . minimumStock = minimumStock ;
39 }
40

41 public void incrementReservations ( int value ) {


42 reservations = reservations + value;
43 }
44

45 public void decrementReservations ( int value ) {


46 reservations = reservations - value;
47 }
APPENDIX O. INVENTORY MANAGEMENT AOP-SERVICES 102

48

49 public int getNumberOfReservations () {


50 return reservations ;
51 }
52 }
APPENDIX O. INVENTORY MANAGEMENT AOP-SERVICES 103

O.8 ReservationCounter.java

Source of jboss.thesis.inventory.service.ReservationCounter
1 package jboss . thesis . inventory . service ;
2

3 import jboss . thesis . inventory . controller . InventoryFactory ;


4 import jboss . thesis . inventory . model . Product ;
5

6 import org . jboss . aop . Interceptor ;


7 import org . jboss . aop . Invocation ;
8 import org . jboss . aop . InvocationType ;
9 import org . jboss . aop . MethodInvocation ;
10

11

12 /**
13 * @author Christian Dalager , Simon Jorsal , Eske Sort
14 *
15 */
16 public class DecrementReservationInterceptor implements Interceptor {
17 private InventoryFactory factory = InventoryFactory . instance ();
18

19 public DecrementReservationInterceptor() {
20 super ();
21 }
22

23 public String getName () {


24 return " DecrementReservationInterceptor";
25 }
26

27 public Object invoke ( Invocation inv ) throws Throwable {


28 if ( inv . getType () == InvocationType . METHOD ) {
29 MethodInvocation minv = ( MethodInvocation ) inv ;
30 Product productProxy = ( Product ) inv . targetObject ;
31 Product realProduct = factory . getLocalProduct ( productProxy . getId ());
32 ReservationCounter rs = ( ReservationCounter ) realProduct ;
33 int decrementBy = (( Integer ) minv . arguments [0]). intValue ();
34 rs . decrementReservations ( decrementBy );
35 }
36

37 return inv . invokeNext ();


38 }
39 }
APPENDIX O. INVENTORY MANAGEMENT AOP-SERVICES 104

O.9 WatchListInterceptor.java

Source of jboss.thesis.inventory.service.WatchListInterceptor
1 package jboss . thesis . inventory . service ;
2

3 import jboss . thesis . inventory . model . Product ;


4

5 import org . jboss . aop . Interceptor ;


6 import org . jboss . aop . Invocation ;
7 import org . jboss . aop . InvocationType ;
8 import org . jboss . aop . MethodInvocation ;
9

10 import org . jboss . logging . Logger ;


11

12 import java . lang . reflect . Method ;


13

14

15 /**
16 * This Interceptor is meant to be added dynamically to selected instances of
17 * Product objects .
18 *
19 * @author Christian Dalager , Simon Jorsal , Eske Sort
20 */
21 public class WatchListInterceptor implements Interceptor {
22 Logger log = Logger . getLogger ( WatchListInterceptor . class );
23

24 public String getName () {


25 return " WatchListInterceptor ";
26 }
27

28 public Object invoke ( Invocation inv ) throws Throwable {


29 try {
30 InvocationType iType = inv . getType ();
31

32 if ( iType == InvocationType . METHOD ) {


33 MethodInvocation methodInv = ( MethodInvocation ) inv ;
34 Method method = methodInv . method ;
35

36 if ( method . getName (). equals (" decreaseStockBy ")) {


37 Product prod = ( Product ) inv . targetObject ;
38 String decreasedBy = methodInv . arguments [0]. toString ();
39 log . info (" - - - Begin WatchList Notification - - -");
40 log . info ( prod . getName () + " was decreased by " + decreasedBy );
41 log . info (" - - - End WatchList Notification - - -");
42 }
43 }
44 }
45 catch ( Exception e ) {
46 e. printStackTrace ();
47 }
APPENDIX O. INVENTORY MANAGEMENT AOP-SERVICES 105

48

49 return inv . invokeNext ();


50 }
51 }
APPENDIX O. INVENTORY MANAGEMENT AOP-SERVICES 106

O.10 ModelConstructorLoggingInterceptor.java

Source of jboss.thesis.inventory.service.logging.ModelConstructorLoggingInterceptor
1 /*
2 * Created on 19 -12 -2003
3 *
4 */
5 package jboss . thesis . inventory . service . logging ;
6

7 import jboss . thesis . inventory . model . IdUtil ;


8

9 import org . jboss . aop . ConstructorInvocation ;


10 import org . jboss . aop . Interceptor ;
11 import org . jboss . aop . Invocation ;
12

13 import org . jboss . logging . Logger ;


14

15 import java . lang . reflect . Constructor ;


16

17

18 /**
19 * @author Christian Dalager , Simon Jorsal , Eske Sort
20 */
21 public class ModelConstructorLoggingInterceptor implements Interceptor {
22 private static Logger log = Logger . getLogger (
23 ModelConstructorLoggingInterceptor. class );
24

25 public String getName () {


26 return " ModelConstructorLoggingInterceptor";
27 }
28

29 public Object invoke ( Invocation invocation ) throws Throwable {


30 ConstructorInvocation inter = ( ConstructorInvocation ) invocation ;
31 Object target = inter . targetObject ;
32 Constructor cons = inter . constructor ;
33 String className = cons . getDeclaringClass (). getName ();
34

35 StringBuffer buffer = new StringBuffer ();


36 buffer . append (" Creating an instance of " + className );
37

38 if ( className . endsWith (" Order ")) {


39 buffer . append (" with id =" + IdUtil . getCurrentId ( IdUtil . ORDER ));
40 }
41

42 if ( className . endsWith (" Product ")) {


43 buffer . append (" with id =" + IdUtil . getCurrentId ( IdUtil . PRODUCT ));
44 }
45

46 if ( className . endsWith (" Reservation ")) {


47 buffer . append (" with id =" + IdUtil . getCurrentId ( IdUtil . RESERVATION ));
APPENDIX O. INVENTORY MANAGEMENT AOP-SERVICES 107

48 }
49

50 if ( className . endsWith (" Type ")) {


51 buffer . append (" with id =" + IdUtil . getCurrentId ( IdUtil . TYPE ));
52 }
53

54 if ( className . endsWith (" Customer ")) {


55 buffer . append (" with id =" + IdUtil . getCurrentId ( IdUtil . CUSTOMER ));
56 }
57

58 if ( log . isInfoEnabled ()) {


59 log . info ( buffer . toString ());
60 }
61

62 return invocation . invokeNext ();


63 }
64

65 /*
66 * To turn on logging , the following should be
67 * inserted into the JBoss log4j . xml file :
68 * < appender name =" INVENTORY " class =" org . apache . log4j . FileAppender ">
69 * < errorHandler class =" org . jboss . logging . util . OnlyOnceErrorHandler "/ >
70 * < param name =" Append " value =" false "/ >
71 * < param name =" File "
72 * value =" ${ jboss . server . home . dir }/ log / inventory - management . log "/ >
73 * < layout class =" org . apache . log4j. PatternLayout ">
74 * < param name =" ConversionPattern "
75 * value ="% d{ ABSOLUTE } % -5p [% c {1}] % m%n "/ >
76 * </ layout >
77 * </ appender >
78 *
79 * < category name =" jboss. thesis . inventory . service .
80 * logging . ConstructorLoggingInterceptor">
81 * < priority value =" INFO "/ >
82 * < appender - ref ref =" INVENTORY "/ >
83 * </ category >
84 */
85 }
Appendix P

Inventory Management MBeans

All classes below are part of the jboss.thesis.inventory.model.jmx package.

P.1 AOPService.java

Source of jboss.thesis.inventory.model.jmx.AOPService
1 package jboss . thesis . inventory . model . jmx ;
2

3 import jboss . thesis . inventory . controller . InventoryController ;


4 import jboss . thesis . inventory . model . Product ;
5 import jboss . thesis . inventory . service . MinimumStock ;
6 import jboss . thesis . inventory . service . WatchListInterceptor ;
7

8 import org . jboss . aop . Advised ;


9 import org . jboss . aop . ClassInstanceAdvisor ;
10 import org . jboss . aop . Dispatcher ;
11 import org . jboss . aop . Interceptor ;
12 import org . jboss . aop . NotAdvisedException ;
13

14 import org . jboss . logging . Logger ;


15

16 import org . jboss . system . ServiceMBeanSupport ;


17

18 import javax . management . MBeanRegistration ;


19 import javax . management . MBeanServer ;
20

21

22 /**
23 * @author Christian Dalager , Simon Jorsal , Eske Sort
24 */
25 public class AOPService extends ServiceMBeanSupport implements
26 MBeanRegistration , AOPServiceMBean {

108
APPENDIX P. INVENTORY MANAGEMENT MBEANS 109

27 static Logger log = Logger . getLogger ( AOPService . class );


28 MBeanServer m_mbeanServer ;
29 InventoryController controller ;
30

31 public AOPService () {
32 super ();
33 controller = InventoryController . instance ();
34 }
35

36 public String listProducts () {


37 StringBuffer sb = new StringBuffer ();
38 int numOfProducts = controller . getNumberOfProducts ();
39

40 for ( int i = 0; i < numOfProducts ; i ++) {


41 Product proxy = controller . getProduct (i );
42 Product p = ( Product ) Dispatcher . singleton . getRegistered (
43 " product " + proxy. getId ());
44 System . out . println (" p. class =" + p. getClass (). getName ());
45 sb . append (
46 " Product : " + p. getName () + " , " + p. getType (). getName () + " < br / >");
47

48 int minStock = 0;
49

50 try {
51 MinimumStock min = dirtyCast (p );
52 System . out . println (" Calling getMinimumStock ");
53 minStock = min . getMinimumStock ();
54 }
55 catch ( ClassCastException cce ) {
56 System . out . println (" Product is a composite , cannot get Minimum Stock ");
57 System . out . println (" getClass (): " + p. getClass ());
58 cce . printStackTrace ();
59 }
60

61 // check to see if there has been set a watch on the product


62 ClassInstanceAdvisor cia = getAdvisor (p );
63 Interceptor [] interceptors = cia . getInterceptors ();
64

65 String watchlink = " <a href =\" HtmlAdaptor ? action = invokeOpByName & name =" +
66 " jboss . thesis . inventory %3 Aname %3 DAOPService & methodName =" +
67 " watchProduct & argType = long & arg0 =" +
68 p. getId () + "\" > Add watch </a >< br /><br /><br / >";
69

70 for ( int n = 0; n < interceptors . length ; n ++) {


71 if ( interceptors [n ]. getName (). equals (" WatchListInterceptor ")) {
72 watchlink = " < a href =\" HtmlAdaptor ? action = invokeOpByName & name =" +
73 " jboss . thesis . inventory %3 Aname %3 DAOPService & methodName =" +
74 " unWatchProduct & argType = long & arg0 =" +
75 p. getId () + "\" > Remove watch </ a>< br /><br />< br / >";
76 }
77 }
APPENDIX P. INVENTORY MANAGEMENT MBEANS 110

78

79 sb . append (" ID : " + p. getId () + " Stock : " + p. getStock () +


80 " Minimum Stock : " + minStock + " < br / >");
81 sb . append (" < form method =\" get \" action =\" HtmlAdaptor \" >");
82 sb . append (" Set minimum stock : ");
83 sb . append (" < input type =\" hidden \" name =\" action \" value =\" invokeOp \" >");
84 sb . append (" < input type =\" hidden \" name =\" name \" value =" +
85 "\" jboss . thesis . inventory : name = AOPService \" >");
86 sb . append (" < input type =\" hidden \" name =\" methodIndex \" value =\"3\" >");
87 sb . append (
88 "< input type =\" hidden \" name =\" arg0 \" value =\"" + p. getId () + "\" >");
89 sb . append (" < input type =\" text \" name =\" arg1 \" >");
90 sb . append (" < input type =\" submit \" value =\" Invoke \" > </ form >");
91 sb . append ( watchlink );
92 }
93

94 return sb . toString ();


95 }
96

97 public String setMinimumQuantity ( long productid , int minimumStock ) {


98 String result = " Minimum stock set to " + minimumStock ;
99 Object product = ( Product ) Dispatcher . singleton . getRegistered (
100 " product " + productid );
101

102 try {
103 MinimumStock ms = ( MinimumStock ) product ;
104 ms . setMinimumStock ( minimumStock );
105 }
106 catch ( ClassCastException cce ) {
107 result = " Product has not been made advisable " +
108 " - minimum stock not available ";
109 }
110

111 StringBuffer sb = new StringBuffer ();


112 sb . append (" <a href =\" HtmlAdaptor ? action = invokeOpByName & name =" +
113 " jboss . thesis . inventory %3 Aname %3 DAOPService & methodName =" +
114 " listProducts \" > Back to list of products </ a >");
115

116 return result + " < br />< br / >" + sb . toString ();


117 }
118

119 public String watchProduct ( long productId ) {


120 Product product = ( Product ) Dispatcher . singleton . getRegistered (
121 " product " + productId );
122 ClassInstanceAdvisor cia = getAdvisor ( product );
123

124 cia . appendInterceptor ( new WatchListInterceptor ());


125

126 StringBuffer sb = new StringBuffer ();


127

128 sb . append (" You have added " + product . getName () +


APPENDIX P. INVENTORY MANAGEMENT MBEANS 111

129 " to your watchlist .< br /> You will be informed when decreaseStock ()" +
130 " is called < br / >");
131 sb . append ( " < a href =\" HtmlAdaptor ? action = invokeOpByName & name " +
132 " jboss . thesis . inventory %3 Aname %3 DAOPService & methodName =" +
133 " listProducts \" > Back to list of products </ a >");
134

135 return sb . toString ();


136 }
137

138 public String unWatchProduct ( long productId ) {


139 Product product = ( Product ) Dispatcher . singleton . getRegistered (
140 " product " + productId );
141 ClassInstanceAdvisor cia = getAdvisor ( product );
142

143 cia . removeInterceptor (" WatchListInterceptor ");


144

145 StringBuffer sb = new StringBuffer ();


146

147 sb . append ( " You have removed " + product . getName () +


148 " from your watchlist < br / >");
149 sb . append (" <a href =\" HtmlAdaptor ? action = invokeOpByName & name =" +
150 " jboss . thesis . inventory %3 Aname %3 DAOPService & methodName =" +
151 " listProducts \" > Back to list of products </ a >");
152

153 return sb . toString ();


154 }
155

156 private MinimumStock dirtyCast ( Object o ) throws ClassCastException {


157 MinimumStock m = ( MinimumStock ) o;
158

159 return m;
160 }
161

162 private ClassInstanceAdvisor getAdvisor ( Object o ) throws


163 NotAdvisedException {
164 Advised a = ( Advised ) o;
165

166 return ( ClassInstanceAdvisor ) a. _getInstanceAdvisor ();


167 }
168 }
APPENDIX P. INVENTORY MANAGEMENT MBEANS 112

P.2 AOPServiceMBean.java

Source of jboss.thesis.inventory.model.jmx.AOPServiceMBean
1 package jboss . thesis . inventory . model . jmx ;
2

3 import org . jboss . system . ServiceMBean ;


4

6 /**
7 * @author Christian Dalager , Simon Jorsal , Eske Sort
8 */
9 public interface AOPServiceMBean extends ServiceMBean {
10 public String listProducts ();
11 public String setMinimumQuantity ( long productid , int minimumStock );
12 public String watchProduct ( long productId );
13 public String unWatchProduct ( long productId );
14 }
APPENDIX P. INVENTORY MANAGEMENT MBEANS 113

P.3 InventoryService.java

Source of jboss.thesis.inventory.model.jmx.InventoryService
1 package jboss . thesis . inventory . model . jmx ;
2

3 import jboss . thesis . inventory . controller . CreationException ;


4 import jboss . thesis . inventory . controller . InventoryController ;
5 import jboss . thesis . inventory . controller . InventoryFactory ;
6 import jboss . thesis . inventory . controller . RemoteUtil ;
7 import jboss . thesis . inventory . model . OrderList ;
8 import jboss . thesis . inventory . model . Product ;
9 import jboss . thesis . inventory . model . ProductComposite ;
10 import jboss . thesis . inventory . model . Type ;
11

12 import org . jboss . aop . AspectManagerUtil ;


13 import org . jboss . aop . ClassFileWriter ;
14 import org . jboss . aop . Dispatcher ;
15 import org . jboss . aop . remoting . Remoting ;
16

17 import org . jboss . logging . Logger ;


18

19 import org . jboss . system . ServiceMBeanSupport ;


20

21 import java . util . ArrayList ;


22 import java . util . Collection ;
23 import java . util . HashMap ;
24 import java . util . Iterator ;
25 import java . util . Map ;
26

27 import javax . management . MBeanRegistration ;


28 import javax . management . MBeanServer ;
29

30 import javax . naming . InitialContext ;


31 import javax . naming . NamingException ;
32

33

34 /**
35 * @author Christian Dalager , Simon Jorsal , Eske Sort
36 */
37 public class InventoryService extends ServiceMBeanSupport
38 implements MBeanRegistration , InventoryServiceMBean {
39 static Logger log = Logger . getLogger ( InventoryService . class );
40 MBeanServer m_mbeanServer ;
41

42 // ProductComposite list ;
43 public InventoryService () {
44 super ();
45 }
46

47 protected void startService () throws Exception {


APPENDIX P. INVENTORY MANAGEMENT MBEANS 114

48 createInventoryFactory ();
49 createInventoryController ();
50 createOrderList ();
51 createDummyProducts ();
52 }
53

54 /**
55 * Creates and registers an OrderList with the Dispatcher and binds it in
56 * JNDI . If the OrderList is already bound in JNDI it will be replaced by
57 * the newly created OrderList . ( But note that OrderList is Singleton ).
58 */
59 public void createOrderList () throws Exception {
60 OrderList list = OrderList . instance ();
61 String oid = " orderList ";
62

63 // InventoryController . instance (). setOrderList ( list );


64 OrderList listProxy = ( OrderList ) Remoting . createRemoteProxy (
65 oid , list . getClass () , RemoteUtil . CONNECT_URL );
66

67 registerAndBindObject ( list , listProxy , oid );


68 }
69

70 /**
71 * Creates and registers an InventoryFactory with the Dispatcher and binds
72 * it in JNDI . If the InventoryFactory is already bound in JNDI it will be
73 * replaced by the newly created factory . ( But note that InventoryFactory
74 * is Singleton ).
75 */
76 public void createInventoryFactory () throws Exception {
77 InventoryFactory factory = new InventoryFactory ();
78 String oid = " inventoryFactory ";
79

80 InventoryFactory factoryProxy =
81 ( InventoryFactory ) Remoting . createRemoteProxy (
82 oid , factory . getClass () , RemoteUtil . CONNECT_URL );
83

84 registerAndBindObject ( factory , factoryProxy , oid );


85 }
86

87 /**
88 * Creates and registers an InventoryController with the Dispatcher and
89 * binds it in JNDI . If the InventoryController is already bound in JNDI it
90 * will be replaced by the newly created controller . ( InventoryController
91 * is a Singleton ).
92 */
93 public void createInventoryController () throws Exception {
94 InventoryController controller = InventoryController . instance ();
95 String oid = " inventoryController ";
96

97 InventoryController controllerProxy =
98 ( InventoryController ) Remoting . createRemoteProxy (
APPENDIX P. INVENTORY MANAGEMENT MBEANS 115

99 oid , controller . getClass () , RemoteUtil . CONNECT_URL );


100

101 registerAndBindObject ( controller , controllerProxy , oid );


102 }
103

104 private void registerAndBindObject (


105 Object realObject , Object proxy , String oid ) throws NamingException {
106 // register the real object with th eDispatcher
107 Dispatcher . singleton . registerTarget ( oid , realObject );
108

109 // bind the proxy in JNDI


110 new InitialContext (). rebind (oid , proxy );
111 }
112

113 private ArrayList createTypes () {


114 InventoryFactory factory = InventoryFactory . instance ();
115 ArrayList types = new ArrayList ();
116 String [] typeNames = {
117 " CPU " , " HDD " , " Motherboard " , " Cabinet " , " Cooler Fan " , " Ram "
118 };
119 String [] typeDesc = {
120 " Processing unit " , " Hard disk drive " , " Motherboard " , " Computer cabinet ",
121 " Cooler Fan for CPU " , " Memory Module "
122 };
123

124 for ( int i = 0; i < 6; i ++) {


125 Type type = null ;
126

127 try {
128 type = factory . createType ();
129 }
130 catch ( CreationException ignored ) {
131 ignored . printStackTrace ();
132 }
133

134 type . setName ( typeNames [i ]);


135 type . setDescription ( typeDesc [i ]);
136 types . add ( type );
137 }
138

139 return types ;


140 }
141

142 private void createDummyProducts () {


143 InventoryController controller = InventoryController . instance ();
144 InventoryFactory factory = InventoryFactory . instance ();
145 ArrayList typeList = createTypes ();
146 String [] names = {
147 " Pentium 4" , " Pentium 4" , " Athlon XP 1700+" , " IBM 80 Gb HDD ",
148 " Maxtor 80 Gb HDD " , " ASUS Mainboard SKZ7 " , " ASUS Mainboard SKI43 ",
149 " Midi Cabinet " , " Maxi Cabinet " , " Super cool " , " DDR RAM " , " DDR RAM ",
APPENDIX P. INVENTORY MANAGEMENT MBEANS 116

150 " DDR RAM " , " Upgrade kit "


151 };
152

153 String [] desc = {


154 "2 Ghz " , "2 ,3 Ghz " , "1 ,5 Ghz " , "7200 rpm , 80 Gb " , "7200 rpm , 80 Gb ",
155 " AMD Socket " , " Intel Socket " , "12 DFG " , "20 DFG " , " Super silent " , "256 Mb ",
156 "256 Mb " , "512 Mb " , " Gamers pack "
157 };
158

159 String [] manufact = {


160 " Intel " , " Intel " , " AMD " , " IBM " , " Maxtor " , " ASUS " , " ASUS " , " No Name ",
161 " No Name " , " No Name " , " No Name " , " Kingston " , " Kingston " , " Mixed"
162 };
163

164 int [] increase = { 8 , 12 , 7 , 15 , 13 , 18 , 16 , 15 , 16 , 23 , 18 , 17 , 16 , 16 };


165

166 double [] prices = { 100 , 115 , 70 , 80 , 85 , 65 , 65 , 25 , 35 , 25 , 40 , 45 , 65 ,


167 65 };
168

169 Type [] types = {


170 ( Type ) typeList . get (0) , ( Type ) typeList . get (0) , ( Type ) typeList . get (0) ,
171 ( Type ) typeList . get (1) , ( Type ) typeList . get (1) , ( Type ) typeList . get (2) ,
172 ( Type ) typeList . get (2) , ( Type ) typeList . get (3) , ( Type ) typeList . get (3) ,
173 ( Type ) typeList . get (4) , ( Type ) typeList . get (5) , ( Type ) typeList . get (5) ,
174 ( Type ) typeList . get (5) , ( Type ) typeList . get (4)
175 };
176

177 ProductComposite list = null ;


178

179 try {
180 list = ( ProductComposite ) factory . createProductComposite ();
181 }
182 catch ( CreationException ignored ) {}
183

184 list . setName ( names [13]);


185 list . setDescription ( desc [13]);
186 list . setManufacturer ( manufact [13]);
187 list . setPrice ( prices [13]);
188 list . setType ( types [13]);
189 list . increaseStockBy ( increase [13]);
190

191 for ( int i = 0; i < 13; i ++) {


192 Product product = null ;
193

194 try {
195 product = factory . createProductImpl ();
196 }
197 catch ( CreationException ignored ) {}
198

199 product . setName ( names[i ]);


200 product . setDescription ( desc [i ]);
APPENDIX P. INVENTORY MANAGEMENT MBEANS 117

201 product . setManufacturer ( manufact [i ]);


202 product . setPrice ( prices [i ]);
203 product . setType ( types[i ]);
204 product . increaseStockBy ( increase [i ]);
205

206 if (i == 0 || i == 6 || i == 12) {
207 list . add ( product );
208 }
209

210 controller . addProduct ( product );


211 }
212

213 controller . addProduct ( list );


214 }
215

216 public void createProductComposite () {


217 ProductComposite list = null ;
218

219 try {
220 InventoryFactory factory =
221 ( InventoryFactory ) ( new InitialContext ()). lookup (
222 " inventoryFactory ");
223 log . info (" Testing createProductComposite remotely and " +
224 " getting Products not registered in JNDI ");
225 list = ( ProductComposite ) factory . createProductComposite ();
226 list . setName (" productComposite ");
227

228 for ( int i = 0; i < 10; i ++) {


229 Product product = factory . createProductImpl ();
230 product . setName (" Product " + i );
231 list . add ( product );
232 }
233

234 String oid = " productComposite ";


235 Product proxyList = ( Product ) Remoting . createRemoteProxy (
236 oid , list . getClass () , RemoteUtil . CONNECT_URL );
237

238 registerAndBindObject ( list , proxyList , oid );


239

240 // return proxyList ;


241 }
242 catch ( Throwable ex ) {
243 log . error (" failed " , ex );
244 throw new RuntimeException ( ex . getMessage ());
245 }
246 }
247

248 public void registerProduct () {


249 try {
250 InventoryFactory factory =
251 ( InventoryFactory ) ( new InitialContext ()). lookup (
APPENDIX P. INVENTORY MANAGEMENT MBEANS 118

252 " inventoryFactory ");


253 log . info (" Testing getting an Product remotely ");
254

255 Product product = factory . createProductImpl ();


256 product . setName (" Grafikkort ");
257

258 String oid = " product ";


259 Product proxyProduct = ( Product ) Remoting . createRemoteProxy (
260 oid , product . getClass () , RemoteUtil . CONNECT_URL );
261

262 registerAndBindObject ( product , proxyProduct , oid );


263 }
264 catch ( Exception ex ) {
265 log . error (" failed " , ex );
266 ex . printStackTrace ();
267 }
268 }
269

270 public void writeLoadedClassFiles () {


271 ClassFileWriter . writeLoadedClassFiles ();
272 }
273

274 public String printAspectManagerInfo () {


275 AspectManagerUtil util = new AspectManagerUtil ();
276 HashMap maps = new HashMap ();
277 StringBuffer output = new StringBuffer ();
278

279 maps . put (" advisors " , util . getAdvisors ());


280 maps . put (" callerPointcuts " , util . getCallerPointcuts ());
281 maps . put (" introductionPointcuts " , util . getIntroductionPointcuts ());
282 maps . put (" pointcuts " , util . getPointcuts ());
283

284 Collection entries = maps . entrySet ();


285 Iterator it = entries . iterator ();
286

287 while (it . hasNext ()) {


288 // Get the keys
289 Map . Entry entry = ( Map . Entry ) it . next ();
290 String key = ( String ) entry. getKey ();
291 Map map = ( Map ) entry. getValue ();
292 output . append ( key + "\ n ");
293

294 Collection mapEntries = map . entrySet ();


295 Iterator it2 = mapEntries . iterator ();
296

297 while ( it2 . hasNext ()) {


298 // Get the keys
299 Map . Entry mapEntry = ( Map . Entry ) it2 . next ();
300 Object mapKey = mapEntry . getKey ();
301 Object value = mapEntry . getValue ();
302 output . append ("\ t " + mapKey + " = " + value + "\ n ");
APPENDIX P. INVENTORY MANAGEMENT MBEANS 119

303 }
304 }
305

306 return output . toString ();


307 }
308 }
APPENDIX P. INVENTORY MANAGEMENT MBEANS 120

P.4 InventoryServiceMBean.java

Source of jboss.thesis.inventory.model.jmx.InventoryServiceMBean
1 package jboss . thesis . inventory . model . jmx ;
2

3 import org . jboss . system . ServiceMBean ;


4

6 /**
7 * @author Christian Dalager , Simon Jorsal , Eske Sort
8 */
9 public interface InventoryServiceMBean extends ServiceMBean {
10 public void registerProduct ();
11 public void createProductComposite ();
12 public void writeLoadedClassFiles ();
13 public String printAspectManagerInfo ();
14 }
Appendix Q

The Graphical Client

All classes below are part of the jboss.thesis.inventory.client package.

Q.1 AddReservationButton.java

Source of jboss.thesis.inventory.client.AddReservationButton
1 package jboss . thesis . inventory . client ;
2

3 import jboss . thesis . inventory . model . Product ;


4

5 import javax . swing . JButton ;


6

8 /**
9 * @author Christian Dalager , Simon Jorsal , Eske Sort
10 */
11 public class AddReservationButton extends JButton {
12 private Product product ;
13

14 public AddReservationButton ( Product product ) {


15 super (" Add product ");
16 this . product = product ;
17 }
18 }

121
APPENDIX Q. THE GRAPHICAL CLIENT 122

Q.2 ButtonCellRenderer.java

Source of jboss.thesis.inventory.client.ButtonCellRenderer
1 package jboss . thesis . inventory . client ;
2

3 import java . awt . Component ;


4

5 import javax . swing . JTable ;


6 import javax . swing . table . DefaultTableCellRenderer ;
7

9 /**
10 * @author Christian Dalager , Simon Jorsal , Eske Sort
11 */
12 public class ButtonCellRenderer extends DefaultTableCellRenderer {
13 public Component getTableCellRendererComponent( JTable table ,
14 Object value , boolean isSelected , boolean hasFocus , int nRow ,
15 int nCol ) {
16 return ( OrderDetailButton ) value ;
17 }
18 }
APPENDIX Q. THE GRAPHICAL CLIENT 123

Q.3 ColumnData.java

Source of jboss.thesis.inventory.client.ColumnData
1 package jboss . thesis . inventory . client ;
2

3 /**
4 * @author Christian Dalager , Simon Jorsal , Eske Sort
5 */
6 public class ColumnData {
7 public String title ;
8 public int width ;
9 public int alignment ;
10

11 public ColumnData ( String title , int width , int alignment ) {


12 super ();
13 this . title = title ;
14 this . width = width ;
15 this . alignment = alignment ;
16 }
17 }
APPENDIX Q. THE GRAPHICAL CLIENT 124

Q.4 InventoryProxyClient.java

Source of jboss.thesis.inventory.client.InventoryProxyClient
1 package jboss . thesis . inventory . client ;
2

3 import jboss . thesis . inventory . model . ProductImpl ;


4

5 import org . jboss . jmx . adaptor . rmi . RMIAdaptor ;


6

7 import org . jboss . mx . util . ObjectNameFactory ;


8

9 import java . rmi . RMISecurityManager ;


10 import java . rmi . RemoteException ;
11

12 import java . security . AccessControlException ;


13

14 import java . util . ArrayList ;


15 import java . util . Hashtable ;
16 import java . util . Iterator ;
17

18 import javax . management . InstanceNotFoundException ;


19 import javax . management . MBeanException ;
20 import javax . management . ObjectName ;
21 import javax . management . ReflectionException ;
22

23 import javax . naming . Context ;


24 import javax . naming . InitialContext ;
25 import javax . naming . NamingException ;
26

27

28 /**
29 * @author Christian Dalager , Simon Jorsal , Eske Sort
30 */
31 public class InventoryProxyClient {
32 private ObjectName serviceName = ObjectNameFactory . create (
33 " jboss . thesis . inventory : name = RemoteService ");
34 private Object [] noparams = { };
35 private String [] nosig = { };
36 private RMIAdaptor server = null ;
37

38 /**
39 * The constructor initializes the connection with the server running on
40 * localhost .
41 */
42 public InventoryProxyClient () {
43 try {
44 server = ( RMIAdaptor ) getInitialContext (). lookup (" jmx / rmi / RMIAdaptor ");
45 }
46 catch ( NamingException e1 ) {
47 System . out . println (" Error happened !");
APPENDIX Q. THE GRAPHICAL CLIENT 125

48 e1 . printStackTrace ();
49 }
50 catch ( AccessControlException e2 ) {
51 e2 . printStackTrace ();
52 }
53

54 System . out . println (" server =" + server );


55 }
56

57 public void invokeAOPMethod () {


58 try {
59 String s = ( String ) server . invoke ( serviceName , " testAOPRemote ",
60 noparams , nosig );
61 System . out . println (" invokeAOPMethod invoked , result = " + s );
62 }
63 catch ( InstanceNotFoundException e ) {
64 e. printStackTrace ();
65 }
66 catch ( MBeanException e ) {
67 e. printStackTrace ();
68 }
69 catch ( ReflectionException e ) {
70 e. printStackTrace ();
71 }
72 catch ( RemoteException e ) {
73 e. printStackTrace ();
74 }
75 }
76

77 /**
78 * @return ArrayList of Products on the server . These Products are <i > not </i >
79 * remote objects .
80 */
81 public ArrayList getRemoteProducts () {
82 ArrayList list = null ;
83

84 try {
85 list = ( ArrayList ) server . invoke (
86 serviceName , " retrieveAllProducts " , noparams , nosig );
87 System . out . println (" list =" + list );
88 }
89 catch ( InstanceNotFoundException e2 ) {
90 e2 . printStackTrace ();
91 }
92 catch ( MBeanException e2 ) {
93 e2 . printStackTrace ();
94 }
95 catch ( ReflectionException e2 ) {
96 e2 . printStackTrace ();
97 }
98 catch ( RemoteException e2 ) {
APPENDIX Q. THE GRAPHICAL CLIENT 126

99 e2 . printStackTrace ();
100 }
101

102 return list ;


103 }
104

105 public static void main ( String [] args ) {


106 InventoryProxyClient ipt = new InventoryProxyClient ();
107 ArrayList al = ipt . getRemoteProducts ();
108

109 System . out . println (" Number of prodcts = " + al . size ());
110 System . out . println ("\ nProducts on server : ");
111

112 Iterator i = al . iterator ();


113 while (i. hasNext ()) {
114 System . out . println ((( ProductImpl ) i. next ()). getName ());
115 }
116

117 ipt . invokeAOPMethod ();


118 }
119

120 /**
121 * Sets up a default security manager
122 */
123 private void setupSecurityManager () {
124 System . out . println (" SecurityManager =" + System . getSecurityManager ());
125 System . out . println (" Setting security manager ");
126

127 try {
128 if ( System . getSecurityManager () == null ) {
129 System . setSecurityManager ( new RMISecurityManager ());
130 }
131 }
132 catch ( SecurityException se ) {
133 System . out . println (" SecurityManager already set !");
134 }
135

136 System . out . println (" security manager set ");


137 }
138

139 /**
140 * @return InitialContext
141 */
142 private InitialContext getInitialContext () {
143 Hashtable props = new Hashtable ();
144 props . put ( Context . INITIAL_CONTEXT_FACTORY ,
145 " org . jnp . interfaces . NamingContextFactory ");
146 props . put ( Context . URL_PKG_PREFIXES , " org . jboss . naming : org . jnp . interfaces ");
147

148 InitialContext ctx = null ;


149 try {
APPENDIX Q. THE GRAPHICAL CLIENT 127

150 ctx = new InitialContext ( props );


151 }
152 catch ( NamingException e1 ) {
153 e1 . printStackTrace ();
154 }
155

156 return ctx ;


157 }
158 }
APPENDIX Q. THE GRAPHICAL CLIENT 128

Q.5 JTableButtonListener.java

Source of jboss.thesis.inventory.client.JTableButtonListener
1 package jboss . thesis . inventory . client ;
2

3 import java . awt . event . MouseEvent ;


4 import java . awt . event . MouseListener ;
5

6 import javax . swing . JButton ;


7 import javax . swing . JTable ;
8 import javax . swing . SwingUtilities ;
9 import javax . swing . table . TableColumnModel ;
10

11 /**
12 * @author Christian Dalager , Simon Jorsal , Eske Sort
13 */
14 class JTableButtonListener implements MouseListener {
15 private JTable table ;
16

17 JTableButtonListener ( JTable table ) {


18 this . table = table ;
19 }
20

21 private void forwardEventToButton ( MouseEvent e ) {


22 TableColumnModel columnModel = table . getColumnModel ();
23 int column = columnModel . getColumnIndexAtX (e. getX ());
24 int row = e. getY () / table . getRowHeight ();
25 Object value ;
26 JButton button ;
27 MouseEvent buttonEvent ;
28

29 if (( row >= table . getRowCount ()) || ( row < 0) ||


30 ( column >= table . getColumnCount ()) || ( column < 0)) {
31 return ;
32 }
33

34 value = table . getValueAt ( row , column );


35

36 if (!( value instanceof JButton )) {


37 return ;
38 }
39

40 button = ( JButton ) value ;


41 buttonEvent = ( MouseEvent ) SwingUtilities . convertMouseEvent ( table ,
42 e , button );
43 button . dispatchEvent ( buttonEvent );
44

45 // This is necessary so that when a button is pressed and released


46 // it gets rendered properly . Otherwise , the button may still appear
47 // pressed down when it has been released .
APPENDIX Q. THE GRAPHICAL CLIENT 129

48 table . repaint ();


49 }
50

51 public void mouseClicked ( MouseEvent e ) {


52 forwardEventToButton (e );
53 }
54

55 public void mousePressed ( MouseEvent e ) {


56 forwardEventToButton (e );
57 }
58

59 public void mouseReleased ( MouseEvent e ) {


60 forwardEventToButton (e );
61 }
62

63 public void mouseEntered ( MouseEvent e ) {


64 forwardEventToButton (e );
65 }
66

67 public void mouseExited ( MouseEvent e ) {


68 forwardEventToButton (e );
69 }
70 }
APPENDIX Q. THE GRAPHICAL CLIENT 130

Q.6 MainWindow.java

Source of jboss.thesis.inventory.client.MainWindow
1 package jboss . thesis . inventory . client ;
2

3 import jboss . thesis . inventory . controller . CreationException ;


4 import jboss . thesis . inventory . controller . InventoryController ;
5 import jboss . thesis . inventory . controller . InventoryFactory ;
6 import jboss . thesis . inventory . controller . RemoteUtil ;
7 import jboss . thesis . inventory . model . Customer ;
8 import jboss . thesis . inventory . model . Order ;
9

10 import org . jboss . logging . Logger ;


11

12 import java . awt . BorderLayout ;


13 import java . awt . Color ;
14 import java . awt . Font ;
15 import java . awt . event . ActionEvent ;
16 import java . awt . event . ActionListener ;
17 import java . awt . event . MouseAdapter ;
18 import java . awt . event . MouseEvent ;
19

20 import java . rmi . RMISecurityManager ;


21

22 import java . security . AllPermission ;


23 import java . security . CodeSource ;
24 import java . security . PermissionCollection ;
25 import java . security . Permissions ;
26 import java . security . Policy ;
27

28 import javax . naming . NamingException ;


29

30 import javax . swing . JButton ;


31 import javax . swing . JFrame ;
32 import javax . swing . JLabel ;
33 import javax . swing . JPanel ;
34 import javax . swing . JScrollPane ;
35 import javax . swing . JTable ;
36 import javax . swing . SwingConstants ;
37 import javax . swing . event . TableModelEvent ;
38 import javax . swing . table . DefaultTableCellRenderer ;
39 import javax . swing . table . JTableHeader ;
40 import javax . swing . table . TableColumn ;
41

42

43 /**
44 * @author Christian Dalager , Simon Jorsal , Eske Sort
45 */
46 public class MainWindow extends JFrame implements ActionListener {
47 private static Logger log = Logger . getLogger ( MainWindow . class );
APPENDIX Q. THE GRAPHICAL CLIENT 131

48 private static MainWindow instance ;


49 JLabel title ;
50 JButton newOrder ;
51 JScrollPane scrollPane ;
52 JTable orderTable ;
53 OrderTableData data ;
54 InventoryController controller ;
55 private InventoryFactory factory ;
56

57 private MainWindow () {
58 super (" Inventory Management Client ");
59

60 try {
61 factory = RemoteUtil . getFactory ();
62 controller = RemoteUtil . getController ();
63 }
64 catch ( NamingException e1 ) {
65 System . out . println (" Exception in MainWindow constructor ");
66 e1 . printStackTrace ();
67 }
68

69 // by feeding the TableModel with an arrayList of orders


70 // we might get sync - problems .
71 data = new OrderTableData ();
72

73 // fixing the dimensions and basic stuff


74 setDefaultCloseOperation ( JFrame . EXIT_ON_CLOSE );
75 setSize (800 , 600);
76 setBackground ( Color . darkGray );
77

78 title = new JLabel (" Registered orders " , SwingConstants . CENTER );


79 title . setFont ( new Font (" Helvetica " , Font . PLAIN , 18));
80 newOrder = new JButton (" Create New Order ");
81 newOrder . setFocusPainted ( false );
82 newOrder . setBackground ( Color . GRAY );
83 this . getContentPane (). setLayout ( new BorderLayout ());
84

85 orderTable = new JTable ();


86

87 // we make our own columns so we don t want autostuff here


88 orderTable . setAutoCreateColumnsFromModel( false );
89 orderTable . setModel ( data );
90

91 // creates each specific tablecolumn


92 for ( int k = 0; k < data . getColumnCount (); k ++) {
93 DefaultTableCellRenderer renderer ;
94

95 if (k == 5) {
96 renderer = new ButtonCellRenderer ();
97 }
98 else {
APPENDIX Q. THE GRAPHICAL CLIENT 132

99 renderer = new DefaultTableCellRenderer ();


100 }
101

102 renderer . setHorizontalAlignment ( OrderTableData . columns [k ]. alignment );


103

104 TableColumn column = new TableColumn (k , OrderTableData . columns [k ]. width ,


105 renderer , null );
106 orderTable . addColumn ( column );
107 }
108

109 orderTable . addMouseListener ( new JTableButtonListener ( orderTable ));


110 newOrder . addMouseListener ( new MouseAdapter () {
111 public void mouseClicked ( MouseEvent e ) {
112 Order newOrd = null ;
113

114 try {
115 Customer customer = factory . createCustomer ();
116 customer . setAddress (" Enter Address ");
117 customer . setEmail (" Enter Email ");
118 customer . setName (" Enter Name ");
119

120 newOrd = factory . createOrder ();


121 newOrd . setCustomer ( customer );
122 controller . addOrder ( newOrd );
123 }
124 catch ( CreationException ce ) {
125 log . debug (" CreationException =" + ce . getCause ());
126 }
127

128 orderTable . tableChanged ( new TableModelEvent ( orderTable . getModel ()));


129

130 OrderFrame of = new OrderFrame ( newOrd );


131 of . setSize (800 , 600);
132 of . setVisible ( true );
133 }
134 });
135

136 JTableHeader header = orderTable . getTableHeader ();


137 header . setUpdateTableInRealTime ( false );
138 header . setReorderingAllowed ( false );
139 scrollPane = new JScrollPane ();
140 scrollPane . getViewport (). setBackground ( orderTable . getBackground ());
141 scrollPane . getViewport (). add ( orderTable );
142

143 BorderLayout grid = new BorderLayout ();


144 JPanel topView = new JPanel ( grid );
145 topView . add ( title , BorderLayout . WEST );
146 topView . add ( newOrder , BorderLayout . EAST );
147

148 getContentPane (). add ( topView , BorderLayout . NORTH );


149 getContentPane (). add ( scrollPane , BorderLayout . CENTER );
APPENDIX Q. THE GRAPHICAL CLIENT 133

150 }
151

152 public static MainWindow instance () {


153 if ( instance == null ) {
154 instance = new MainWindow ();
155 }
156

157 return instance ;


158 }
159

160 public void actionPerformed ( ActionEvent e ) {}


161

162 public static void main ( String [] args ) {


163 setupSecurityManager ();
164

165 MainWindow window = MainWindow . instance ();


166 window . setVisible ( true );
167 }
168

169 private static void setupSecurityManager () {


170 Policy . setPolicy ( new Policy () {
171 public PermissionCollection getPermissions ( CodeSource codesource ) {
172 Permissions perms = new Permissions ();
173 perms . add ( new AllPermission ());
174

175 return ( perms );


176 }
177

178 public void refresh () {}


179 });
180

181 try {
182 if ( System . getSecurityManager () == null ) {
183 System . setSecurityManager ( new RMISecurityManager ());
184 }
185 }
186 catch ( SecurityException se ) {
187 System . out . println (" Exception in setSecurityManager ");
188 }
189 }
190

191 public void updateMainWindow () {


192 orderTable . tableChanged ( new TableModelEvent ( orderTable . getModel ()));
193 this . show ();
194 this . repaint ();
195 }
196 }
APPENDIX Q. THE GRAPHICAL CLIENT 134

Q.7 OrderDetailButton.java

Source of jboss.thesis.inventory.client.OrderDetailButton
1 package jboss . thesis . inventory . client ;
2

3 import jboss . thesis . inventory . model . Order ;


4

5 import javax . swing . JButton ;


6

8 /**
9 * @author Christian Dalager , Simon Jorsal , Eske Sort
10 */
11 public class OrderDetailButton extends JButton {
12 Order order ;
13

14 public OrderDetailButton ( Order o ) {


15 super (" Details ");
16 this . order = o;
17 }
18 }
APPENDIX Q. THE GRAPHICAL CLIENT 135

Q.8 OrderFrame.java

Source of jboss.thesis.inventory.client.OrderFrame
1 package jboss . thesis . inventory . client ;
2

3 import jboss . thesis . inventory . controller . InventoryController ;


4 import jboss . thesis . inventory . controller . RemoteUtil ;
5 import jboss . thesis . inventory . model . Order ;
6

7 import java . awt . BorderLayout ;


8 import java . awt . Color ;
9 import java . awt . FlowLayout ;
10 import java . awt . Font ;
11 import java . awt . GridLayout ;
12 import java . awt . event . FocusAdapter ;
13 import java . awt . event . FocusEvent ;
14 import java . awt . event . MouseAdapter ;
15 import java . awt . event . MouseEvent ;
16 import java . awt . event . WindowAdapter ;
17 import java . awt . event . WindowEvent ;
18

19 import javax . naming . NamingException ;


20

21 import javax . swing . DefaultCellEditor ;


22 import javax . swing . JButton ;
23 import javax . swing . JFrame ;
24 import javax . swing . JLabel ;
25 import javax . swing . JPanel ;
26 import javax . swing . JScrollPane ;
27 import javax . swing . JTable ;
28 import javax . swing . JTextField ;
29 import javax . swing . SwingConstants ;
30 import javax . swing . event . CellEditorListener ;
31 import javax . swing . event . ChangeEvent ;
32 import javax . swing . event . TableModelEvent ;
33 import javax . swing . table . DefaultTableCellRenderer ;
34 import javax . swing . table . JTableHeader ;
35 import javax . swing . table . TableCellEditor ;
36 import javax . swing . table . TableColumn ;
37

38

39 /**
40 * @author Christian Dalager , Simon Jorsal , Eske Sort
41 */
42 public class OrderFrame extends JFrame {
43 private static InventoryController controller ;
44 Order order ;
45 ReservationTableData reservationData ;
46 ProductTableData productData ;
47 JLabel title ;
APPENDIX Q. THE GRAPHICAL CLIENT 136

48 JTable reservationTable ;
49 JTable productTable ;
50 JScrollPane productScrollPane ;
51 JScrollPane reservationScrollPane ;
52 final JTextField nameTxt ;
53 final JTextField addressTxt ;
54 final JTextField emailTxt ;
55 JButton deleteButton ;
56 JButton saveButton ;
57 JButton invoiceButton ;
58

59 public OrderFrame ( final Order order ) {


60 super (" Edit Order # " + order. getId ());
61

62 try {
63 // factory = RemoteUtil . getFactory ();
64 controller = RemoteUtil . getController ();
65 }
66 catch ( NamingException e1 ) {
67 e1 . printStackTrace ();
68 }
69

70 this . order = order ;


71

72 this . addWindowListener ( new WindowAdapter () {


73 public void windowClosed ( WindowEvent e ) {
74 OrderFrame . this . setVisible ( false );
75 MainWindow . instance (). updateMainWindow ();
76 }
77 });
78

79 reservationData = new ReservationTableData ( order );


80 productData = new ProductTableData ( order );
81

82 // fixing the dimensions and basic stuff


83 setDefaultCloseOperation ( JFrame . DISPOSE_ON_CLOSE );
84 setSize (800 , 600);
85 setBackground ( Color . darkGray );
86

87 title = new JLabel (" Edit order # " + order . getId () , SwingConstants . LEFT );
88 title . setFont ( new Font (" Helvetica " , Font . PLAIN , 18));
89 this . getContentPane (). setLayout ( new BorderLayout ());
90

91 reservationTable = new JTable ();


92 productTable = new JTable ();
93

94 // we make our own columns so we don t want autostuff here


95 reservationTable . setAutoCreateColumnsFromModel( false );
96 reservationTable . setModel ( reservationData );
97

98 productTable . setAutoCreateColumnsFromModel( false );


APPENDIX Q. THE GRAPHICAL CLIENT 137

99 productTable . setModel ( productData );


100

101 // creates each specific tablecolumn


102 for ( int k = 0; k < productData . getColumnCount (); k ++) {
103 DefaultTableCellRenderer renderer ;
104

105 if (k == 2) {
106 renderer = new ReservationButtonCellrenderer();
107 }
108 else {
109 renderer = new DefaultTableCellRenderer ();
110 }
111

112 renderer . setHorizontalAlignment ( ProductTableData . columns [k ]. alignment );


113

114 TableColumn column = new TableColumn (k ,


115 ProductTableData . columns [k ]. width , renderer , null );
116 productTable . addColumn ( column );
117 }
118

119 for ( int k = 0; k < reservationData . getColumnCount (); k ++) {


120 DefaultTableCellRenderer renderer = new DefaultTableCellRenderer ();
121 renderer . setHorizontalAlignment (
122 ReservationTableData . columns [k ]. alignment );
123

124 TableColumn column = new TableColumn (k ,


125 ReservationTableData . columns [k ]. width , renderer , null );
126

127 if (k == 1) {
128 JTextField text = new JTextField ();
129 text . setBorder ( null );
130

131 TableCellEditor editor = new DefaultCellEditor ( text );


132

133 editor . addCellEditorListener ( new CellEditorListener () {


134 public void editingCanceled ( ChangeEvent e ) {}
135

136 public void editingStopped ( ChangeEvent e ) {


137 reservationTable . repaint ();
138 }
139 });
140 column . setCellEditor ( editor );
141 }
142

143 reservationTable . addColumn ( column );


144 }
145

146 // Forward events to buttons on productTable


147 productTable . addMouseListener ( new JTableButtonListener ( productTable ));
148 productTable . addMouseListener ( new MouseAdapter () {
149 public void mouseClicked ( MouseEvent e ) {
APPENDIX Q. THE GRAPHICAL CLIENT 138

150 reservationTable . tableChanged (


151 new TableModelEvent ( reservationTable . getModel ()));
152 }
153 });
154

155 JTableHeader productHeader = productTable . getTableHeader ();


156 productHeader . setUpdateTableInRealTime ( false );
157 productHeader . setReorderingAllowed ( false );
158

159 JTableHeader reservationHeader = reservationTable . getTableHeader ();


160 reservationHeader . setUpdateTableInRealTime ( false );
161 reservationHeader . setReorderingAllowed ( false );
162 reservationTable . setCellSelectionEnabled ( true );
163

164 GridLayout grid = new GridLayout (1 , 2 , 5 , 5);


165

166 productScrollPane = new JScrollPane ();


167 productScrollPane . getViewport (). setBackground (
168 productTable . getBackground ());
169 productScrollPane . getViewport (). add ( productTable );
170

171 reservationScrollPane = new JScrollPane ();


172 reservationScrollPane . getViewport (). setBackground (
173 reservationTable . getBackground ());
174 reservationScrollPane . getViewport (). add ( reservationTable );
175

176 JPanel centerTable = new JPanel ( grid );


177 centerTable . add (" products " , productScrollPane );
178 centerTable . add (" reservations " , reservationScrollPane );
179

180 nameTxt = new JTextField ( null , order . getCustomer (). getName () , 15);
181 nameTxt . addFocusListener ( new FocusAdapter () {
182 public void focusLost ( FocusEvent e ) {
183 order . getCustomer (). setName ( nameTxt . getText ());
184 }
185 });
186 addressTxt = new JTextField ( order . getCustomer (). getAddress () , 25);
187 addressTxt . addFocusListener ( new FocusAdapter () {
188 public void focusLost ( FocusEvent e ) {
189 order . getCustomer (). setAddress ( addressTxt . getText ());
190 }
191 });
192

193 emailTxt = new JTextField ( order . getCustomer (). getEmail () , 15);


194 addressTxt . addFocusListener ( new FocusAdapter () {
195 public void focusLost ( FocusEvent e ) {
196 order . getCustomer (). setEmail ( emailTxt . getText ());
197 }
198 });
199

200 FlowLayout topFlow = new FlowLayout ( FlowLayout . LEFT );


APPENDIX Q. THE GRAPHICAL CLIENT 139

201 JPanel topBar = new JPanel ( topFlow );


202

203 topBar . add ( title );


204 topBar . add ( nameTxt );
205 topBar . add ( addressTxt );
206 topBar . add ( emailTxt );
207

208 FlowLayout bottomFlow = new FlowLayout ( FlowLayout . RIGHT );


209 JPanel bottomBar = new JPanel ( bottomFlow );
210

211 deleteButton = new JButton (" Delete Order ");


212 deleteButton . setBackground ( Color . LIGHT_GRAY );
213 deleteButton . addMouseListener ( new MouseAdapter () {
214 public void mouseClicked ( MouseEvent e ) {
215 controller . removeOrder ( order );
216 OrderFrame . this . setVisible ( false );
217 MainWindow . instance (). updateMainWindow ();
218 }
219 });
220

221 saveButton = new JButton (" Close ");


222 saveButton . setBackground ( Color . LIGHT_GRAY );
223 saveButton . addMouseListener ( new MouseAdapter () {
224 public void mouseClicked ( MouseEvent e ) {
225 OrderFrame . this . setVisible ( false );
226 MainWindow . instance (). updateMainWindow ();
227 }
228 });
229

230 invoiceButton = new JButton (" Create Invoice ");


231 invoiceButton . setBackground ( Color . LIGHT_GRAY );
232 invoiceButton . addMouseListener ( new MouseAdapter () {
233 public void mouseClicked ( MouseEvent e ) {
234 order . createInvoice ();
235 OrderFrame . this . setVisible ( false );
236 MainWindow . instance (). updateMainWindow ();
237 }
238 });
239

240 bottomBar . add ( saveButton );


241

242 if ( order . invoiceCreated ()) {


243 productTable . disable ();
244 reservationTable . disable ();
245 nameTxt . disable ();
246 addressTxt . disable ();
247 emailTxt . disable ();
248 }
249 else {
250 bottomBar . add ( deleteButton );
251 bottomBar . add ( invoiceButton );
APPENDIX Q. THE GRAPHICAL CLIENT 140

252 }
253

254 getContentPane (). add ( topBar , BorderLayout . NORTH );


255 getContentPane (). add ( centerTable , BorderLayout . CENTER );
256 getContentPane (). add ( bottomBar , BorderLayout . SOUTH );
257 }
258 }
APPENDIX Q. THE GRAPHICAL CLIENT 141

Q.9 OrderTableData.java

Source of jboss.thesis.inventory.client.OrderTableData
1 package jboss . thesis . inventory . client ;
2

3 import jboss . thesis . inventory . controller . InventoryController ;


4 import jboss . thesis . inventory . controller . RemoteUtil ;
5 import jboss . thesis . inventory . model . Customer ;
6 import jboss . thesis . inventory . model . Order ;
7

8 import org . jboss . logging . Logger ;


9

10 import java . awt . event . MouseAdapter ;


11 import java . awt . event . MouseEvent ;
12 import java . awt . event . MouseListener ;
13

14 import java . text . DateFormat ;


15

16 import java . util . Date ;


17

18 import javax . naming . NamingException ;


19

20 import javax . swing . JLabel ;


21 import javax . swing . table . AbstractTableModel ;
22

23

24 /**
25 * @author Christian Dalager , Simon Jorsal , Eske Sort
26 */
27 public class OrderTableData extends AbstractTableModel {
28 private static Logger log = Logger . getLogger ( OrderTableData . class );
29 static final public ColumnData [] columns = {
30 new ColumnData (" OrderNo " , 50 , JLabel . LEFT ),
31 new ColumnData (" Customer " , 100 , JLabel . LEFT ),
32 new ColumnData (" Date " , 50 , JLabel . LEFT ),
33 new ColumnData (" Price " , 50 , JLabel . LEFT ),
34 new ColumnData (" Paid " , 20 , JLabel . LEFT ),
35 new ColumnData (" " , 30 , JLabel . LEFT )
36 };
37 private InventoryController controller ;
38

39 public OrderTableData () {
40 try {
41 controller = RemoteUtil . getController ();
42 log . debug (" controller =" + controller );
43 }
44 catch ( NamingException e1 ) {
45 log . debug (" NamingException occured : " + e1 . getMessage ());
46 }
47 }
APPENDIX Q. THE GRAPHICAL CLIENT 142

48

49 public int getRowCount () {


50 int rowCount = 0;
51

52 if ( controller != null ) {
53 rowCount = controller . getNumberOfOrders ();
54 }
55

56 return rowCount ;
57 }
58

59 public int getColumnCount () {


60 return columns . length ;
61 }
62

63 public String getColumnName ( int column ) {


64 return columns [ column ]. title ;
65 }
66

67 public boolean isCellEditable ( int row , int col ) {


68 return false ;
69 }
70

71 public Object getValueAt ( int rowIndex , int columnIndex ) {


72 if ( rowIndex < 0 || rowIndex >= getRowCount ()) {
73 return " ";
74 }
75

76 final Order order = ( Order ) controller . getOrder ( rowIndex );


77

78 if ( order == null ) {
79 return " ";
80 }
81

82 switch ( columnIndex ) {
83 case 0 :
84 long id = order . getId ();
85 if ( id < 0) {
86 return " ";
87 }
88 return new Long ( id );
89

90 case 1 :
91 Customer customer = order. getCustomer ();
92 if ( customer == null ) {
93 return " ";
94 }
95 return customer . getName ();
96

97 case 2 :
98 Date date = order . getDate ();
APPENDIX Q. THE GRAPHICAL CLIENT 143

99 if ( date == null ) {
100 return " ";
101 }
102 return DateFormat . getDateInstance (). format ( date );
103

104 case 3 :
105 double price = order . getFullPrice ();
106 if ( price < 0) {
107 return " ";
108 }
109 return new Double ( price );
110

111 case 4 :
112 return ( order . invoiceCreated () ? " yes " : " no ");
113

114 case 5 :
115

116 OrderDetailButton button = new OrderDetailButton ( order );


117 MouseListener lst = new MouseAdapter () {
118 public void mouseClicked ( MouseEvent e ) {
119 System . out . println (" Get details on order nr : " + order . getId ());
120

121 OrderFrame of = new OrderFrame ( order );


122 of . setSize (800 , 600);
123 of . setVisible ( true );
124 }
125 };
126

127 button . addMouseListener ( lst );


128 return button ;
129 }
130

131 return " ";


132 }
133 }
APPENDIX Q. THE GRAPHICAL CLIENT 144

Q.10 ProductTableData.java

Source of jboss.thesis.inventory.client.ProductTableData
1 package jboss . thesis . inventory . client ;
2

3 import jboss . thesis . inventory . controller . CreationException ;


4 import jboss . thesis . inventory . controller . InventoryController ;
5 import jboss . thesis . inventory . controller . InventoryFactory ;
6 import jboss . thesis . inventory . controller . RemoteUtil ;
7 import jboss . thesis . inventory . model . Order ;
8 import jboss . thesis . inventory . model . Product ;
9 import jboss . thesis . inventory . model . Reservation ;
10

11 import java . awt . event . MouseAdapter ;


12 import java . awt . event . MouseEvent ;
13 import java . awt . event . MouseListener ;
14

15 import java . util . List ;


16

17 import javax . naming . NamingException ;


18

19 import javax . swing . JLabel ;


20 import javax . swing . table . AbstractTableModel ;
21

22

23 /**
24 * @author Christian Dalager , Simon Jorsal , Eske Sort
25 */
26 public class ProductTableData extends AbstractTableModel {
27 static final public ColumnData [] columns = {
28 new ColumnData (" Product " , 200 , JLabel . LEFT ),
29 new ColumnData (" Price " , 30 , JLabel . LEFT ),
30 new ColumnData (" Action " , 90 , JLabel . LEFT )
31 };
32 private InventoryFactory factory ;
33 private InventoryController controller ;
34 private List products ;
35 private Order order ;
36

37 public ProductTableData ( Order order ) {


38 try {
39 factory = RemoteUtil . getFactory ();
40 controller = RemoteUtil . getController ();
41 }
42 catch ( NamingException e1 ) {
43 e1 . printStackTrace ();
44 }
45

46 this . order = order ;


47 }
APPENDIX Q. THE GRAPHICAL CLIENT 145

48

49 public int getColumnCount () {


50 return columns . length ;
51 }
52

53 public int getRowCount () {


54 return controller . getNumberOfProducts ();
55 }
56

57 public String getColumnName ( int column ) {


58 return columns [ column ]. title ;
59 }
60

61 public boolean isCellEditable ( int row , int col ) {


62 return false ;
63 }
64

65 public Object getValueAt ( int rowIndex , int columnIndex ) {


66 if ( rowIndex < 0 || rowIndex >= getRowCount ()) {
67 return " ";
68 }
69

70 final Product product = ( Product ) controller . getProduct ( rowIndex );


71

72 switch ( columnIndex ) {
73 case 0 :
74 return product . getName () + " , " + product . getType () + " , " +
75 product . getDescription ();
76

77 case 1 :
78 return new Double ( product . getPrice ());
79

80 case 2 :
81

82 AddReservationButton button = new AddReservationButton ( product );


83

84 if (! order . invoiceCreated ()) {


85 MouseListener lst = new MouseAdapter () {
86 public void mouseClicked ( MouseEvent e ) {
87 Reservation resToAdd = null ;
88

89 if ( order . getReservationByProduct ( product ) == null ) {


90 try {
91 resToAdd = factory . createReservation ();
92 }
93 catch ( CreationException e1 ) {
94 e1 . printStackTrace ();
95 }
96

97 resToAdd . setProduct ( product );


98 resToAdd . setQuantity (1);
APPENDIX Q. THE GRAPHICAL CLIENT 146

99 order . addReservation ( resToAdd );


100 }
101 else {
102 Reservation current = order . getReservationByProduct ( product );
103 current . setQuantity ( current . getQuantity () + 1);
104 }
105 }
106 };
107

108 button . addMouseListener ( lst );


109 }
110

111 return button ;


112 }
113

114 return " ";


115 }
116 }
APPENDIX Q. THE GRAPHICAL CLIENT 147

Q.11 ReservationButtonCellRenderer.java

Source of jboss.thesis.inventory.client.ReservationButtonCellRenderer
1 package jboss . thesis . inventory . client ;
2

3 import java . awt . Component ;


4

5 import javax . swing . JTable ;


6 import javax . swing . table . DefaultTableCellRenderer ;
7

9 /**
10 * @author Christian Dalager , Simon Jorsal , Eske Sort
11 */
12 public class ReservationButtonCellrenderer extends DefaultTableCellRenderer {
13 public Component getTableCellRendererComponent( JTable table , Object value ,
14 boolean isSelected , boolean hasFocus , int nRow , int nCol ) {
15 return ( AddReservationButton ) value;
16 }
17 }
APPENDIX Q. THE GRAPHICAL CLIENT 148

Q.12 ReservationTableData.java

Source of jboss.thesis.inventory.client.ReservationTableData
1 package jboss . thesis . inventory . client ;
2

3 import jboss . thesis . inventory . model . Order ;


4 import jboss . thesis . inventory . model . Reservation ;
5

6 import javax . swing . JLabel ;


7 import javax . swing . table . AbstractTableModel ;
8

10 /**
11 * @author Christian Dalager , Simon Jorsal , Eske Sort
12 */
13 public class ReservationTableData extends AbstractTableModel {
14 static final public ColumnData [] columns = {
15 new ColumnData (" Product " , 200 , JLabel . LEFT ),
16 new ColumnData (" Quantity " , 30 , JLabel . LEFT ),
17 new ColumnData (" Price " , 70 , JLabel . LEFT )
18 };
19 private Order order ;
20

21 public ReservationTableData ( Order order ) {


22 this . order = order ;
23 }
24

25 public int getColumnCount () {


26 return columns . length ;
27 }
28

29 public int getRowCount () {


30 return order . sizeOfReservationList ();
31 }
32

33 public String getColumnName ( int column ) {


34 return columns [ column ]. title ;
35 }
36

37 public boolean isCellEditable ( int row , int col ) {


38 if ( col == 1) {
39 return true ;
40 }
41

42 return false ;
43 }
44

45 public Object getValueAt ( int rowIndex , int columnIndex ) {


46 if ( rowIndex < 0 || rowIndex >= getRowCount ()) {
47 return " ";
APPENDIX Q. THE GRAPHICAL CLIENT 149

48 }
49

50 Reservation reservation = ( Reservation ) order . getReservation ( rowIndex );


51

52 switch ( columnIndex ) {
53 case 0 :
54 return reservation . getProduct (). getName () + " , " +
55 reservation . getProduct (). getType () + " , " +
56 reservation . getProduct (). getDescription ();
57

58 case 1 :
59 return new Integer ( reservation . getQuantity ());
60

61 case 2 :
62 return new Double ( reservation . getPrice ());
63 }
64

65 return " ";


66 }
67

68 public void setValueAt ( Object value , int row , int coll ) {


69 if ( coll == 1) {
70 order . getReservation ( row ). setQuantity ( new Integer (
71 ( String ) value ). intValue ());
72 }
73 }
74 }
Appendix R

AOP Performance Test

All classes below are part of the jboss.thesis.performancetest, jboss.thesis.util


and jboss.thesis.inventory.model.jmx packages.

R.1 PerformanceTest.java

Source of jboss.thesis.inventory.model.jmx.PerformanceTest
1 package jboss . thesis . inventory . model . jmx ;
2

3 import jboss . thesis . performancetest . ConstructorTest ;


4 import jboss . thesis . performancetest . ConstructorTestUnadvised ;
5 import jboss . thesis . performancetest . SimplePerformanceClassA ;
6 import jboss . thesis . performancetest . SimpleUnadvisedPerformanceClassA;
7

8 import jboss . thesis . util . Timer ;


9

10 import javax . management . MBeanRegistration ;


11 import javax . management . MBeanServer ;
12 import javax . management . ObjectName ;
13

14

15 /**
16 * @author Christian Dalager , Simon Jorsal , Eske Sort
17 */
18 public class PerformanceTest implements PerformanceTestMBean ,
19 MBeanRegistration {
20 MBeanServer m_mbeanServer ;
21 Timer t;
22

23 public PerformanceTest () {
24 super ();
25 }

150
APPENDIX R. AOP PERFORMANCE TEST 151

26

27 public double testFallThroughConstruction ( int iterations ) {


28 t = new Timer ();
29

30 for ( int i = 0; i < iterations ; i ++) {


31 ConstructorTest perf = new ConstructorTest ();
32 }
33

34 return t. check ();


35 }
36

37 public double testFallThroughConstructionUnadvised( int iterations ) {


38 t = new Timer ();
39

40 for ( int i = 0; i < iterations ; i ++) {


41 ConstructorTestUnadvised perf = new ConstructorTestUnadvised ();
42 }
43

44 return t. check ();


45 }
46

47 public double testConstruction ( int iterations ) {


48 t = new Timer ();
49

50 for ( int i = 0; i < iterations ; i ++) {


51 SimplePerformanceClassA perf = new SimplePerformanceClassA ();
52 }
53

54 return t. check ();


55 }
56

57 public double testConstructionWithFieldSet ( int iterations ) {


58 t = new Timer ();
59

60 for ( int i = 0; i < iterations ; i ++) {


61 SimplePerformanceClassA perf = new SimplePerformanceClassA (10);
62 }
63

64 return t. check ();


65 }
66

67 public double testUnadvisedConstruction ( int iterations ) {


68 t = new Timer ();
69

70 for ( int i = 0; i < iterations ; i ++) {


71 SimpleUnadvisedPerformanceClassA perf =
72 new SimpleUnadvisedPerformanceClassA();
73 }
74

75 return t. check ();


76 }
APPENDIX R. AOP PERFORMANCE TEST 152

77

78 public double testUnadvisedConstructionWithFieldSet( int iterations ) {


79 t = new Timer ();
80

81 for ( int i = 0; i < iterations ; i ++) {


82 SimpleUnadvisedPerformanceClassA perf =
83 new SimpleUnadvisedPerformanceClassA(10);
84 }
85

86 return t. check ();


87 }
88

89 public double testMethodStatic ( int iterations ) {


90 t = new Timer ();
91 SimplePerformanceClassA .k ++;
92

93 for ( int i = 0; i < iterations ; i ++) {


94 SimplePerformanceClassA . methodStatic (2.3);
95 }
96

97 return t. check ();


98 }
99

100 public double testUnadvisedMethodStatic ( int iterations ) {


101 t = new Timer ();
102 SimpleUnadvisedPerformanceClassA.k ++;
103

104 for ( int i = 0; i < iterations ; i ++) {


105 SimpleUnadvisedPerformanceClassA. methodStatic (2.3);
106 }
107

108 return t. check ();


109 }
110

111 public double testMethod ( int iterations ) {


112 t = new Timer ();
113 SimplePerformanceClassA .k ++;
114

115 SimplePerformanceClassA perf = new SimplePerformanceClassA ();


116

117 for ( int i = 0; i < iterations ; i ++) {


118 perf . method (2.3);
119 }
120

121 return t. check ();


122 }
123

124 public double testUnadvisedMethod ( int iterations ) {


125 t = new Timer ();
126 SimpleUnadvisedPerformanceClassA.k ++;
127
APPENDIX R. AOP PERFORMANCE TEST 153

128 SimpleUnadvisedPerformanceClassA perf =


129 new SimpleUnadvisedPerformanceClassA();
130

131 for ( int i = 0; i < iterations ; i ++) {


132 perf . method (2.3);
133 }
134

135 return t. check ();


136 }
137

138 public double testInterceptedMethod ( int iterations ) {


139 t = new Timer ();
140 SimplePerformanceClassA .k ++;
141

142 SimplePerformanceClassA perf = new SimplePerformanceClassA ();


143

144 for ( int i = 0; i < iterations ; i ++) {


145 perf . interceptorMethod (2.3);
146 }
147

148 return t. check ();


149 }
150

151 public double testPublicMethod ( int iterations ) {


152 t = new Timer ();
153 SimplePerformanceClassA .k ++;
154

155 SimplePerformanceClassA perf = new SimplePerformanceClassA ();


156

157 for ( int i = 0; i < iterations ; i ++) {


158 perf . publicMethod (2.3);
159 }
160

161 return t. check ();


162 }
163

164 public double testNonPublicMethod ( int iterations ) {


165 t = new Timer ();
166 SimplePerformanceClassA .k ++;
167

168 SimplePerformanceClassA perf = new SimplePerformanceClassA ();


169

170 for ( int i = 0; i < iterations ; i ++) {


171 perf . nonPublicMethod (2.3);
172 }
173

174 return t. check ();


175 }
176

177 public double testFieldAccess ( int iterations ) {


178 t = new Timer ();
APPENDIX R. AOP PERFORMANCE TEST 154

179

180 String strHolder ;


181 SimplePerformanceClassA .k ++;
182

183 SimplePerformanceClassA perf = new SimplePerformanceClassA ();


184

185 for ( int i = 0; i < iterations ; i ++) {


186 strHolder = perf . str ;
187 }
188

189 return t. check ();


190 }
191

192 public double testUnadvisedFieldAccess ( int iterations ) {


193 t = new Timer ();
194

195 String strHolder ;


196 SimplePerformanceClassA .k ++;
197

198 SimpleUnadvisedPerformanceClassA perf =


199 new SimpleUnadvisedPerformanceClassA();
200

201 for ( int i = 0; i < iterations ; i ++) {


202 strHolder = perf . str ;
203 }
204

205 return t. check ();


206 }
207

208 public String runPerformanceSuite ( int iterations ) {


209 StringBuffer sb = new StringBuffer ();
210

211 testConstruction ( iterations );


212 double tc = testConstruction ( iterations );
213

214 testConstructionWithFieldSet ( iterations );


215 double tcw = testConstructionWithFieldSet ( iterations );
216

217 testMethod ( iterations );


218 double tm = testMethod ( iterations );
219

220 testInterceptedMethod ( iterations );


221 double tim = testInterceptedMethod ( iterations );
222

223 testUnadvisedConstruction ( iterations );


224 double tuc = testUnadvisedConstruction ( iterations );
225

226 testUnadvisedConstructionWithFieldSet( iterations );


227 double tucw = testUnadvisedConstructionWithFieldSet( iterations );
228

229 testUnadvisedMethod ( iterations );


APPENDIX R. AOP PERFORMANCE TEST 155

230 double tum = testUnadvisedMethod ( iterations );


231

232 testPublicMethod ( iterations );


233 double tpm = testPublicMethod ( iterations );
234

235 testNonPublicMethod ( iterations );


236 double tnpm = testNonPublicMethod ( iterations );
237

238 testFallThroughConstruction ( iterations );


239 double tftc = testFallThroughConstruction ( iterations );
240

241 testFallThroughConstructionUnadvised( iterations );


242 double tftcu = testFallThroughConstructionUnadvised( iterations );
243

244 testFieldAccess ( iterations );


245 double tfa = testFieldAccess ( iterations );
246

247 testUnadvisedFieldAccess ( iterations );


248 double tufa = testUnadvisedFieldAccess ( iterations );
249

250 double consDiff = tc / tuc ;


251 double consDiffField = tcw / tucw ;
252 double methodDiff = tm / tum ;
253 double interceptDiff = tim / tum ;
254 double fallThroughDiff = tftc / tftcu ;
255 double fieldAccessDiff = tfa / tufa ;
256

257 sb . append (" <h1 > Testing Performance </ h1 >");


258 sb . append (" <p > Number of iterations : " + iterations + " </ p >");
259 sb . append (" < table border =1 > <tr ><th > </ th ><th > Advised </ th >" +
260 "<th > Unadvised </ th ><th > Factor </ th > </ tr >\ n ");
261 sb . append (" <tr ><td > Empty constructor </ td ><td >" + tc +
262 " </ td ><td >" + tuc + " </ td ><td >" + consDiff + " </ td > </ tr >\ n ");
263 sb . append (" <tr ><td > Constructor w . field set </ td ><td >" + tcw +
264 " </ td ><td >" + tucw + " </ td ><td >" + consDiffField + " </ td > </ tr >\ n ");
265 sb . append (" <tr ><td > Method </ td ><td >" + tm + " </ td ><td >" + tum +
266 " </ td ><td >" + methodDiff + " </ td > </ tr >\ n ");
267 sb . append (" <tr ><td > Intercepted method </ td ><td >" + tim +
268 " </ td ><td >" + tum + " </ td ><td >" + interceptDiff +
269 " </ td > </tr >\ n ");
270 sb . append (" <tr ><td > Public method </ td ><td >" + tpm +
271 " </ td ><td > - </td ><td > - </td > </ tr >\ n ");
272 sb . append (" <tr ><td > Non - public method ) </ td ><td >" + tnpm +
273 " </ td ><td > - </td ><td > - </td > </ tr >\ n ");
274 sb . append (" <tr ><td > Fall - through constructor </ td ><td >" + tftc +
275 " </ td ><td >" + tftcu + " </ td ><td >" + fallThroughDiff + " </ td > </ tr >\ n ");
276 sb . append (" <tr ><td > Field Access </ td ><td >" + tfa + " </ td ><td >" + tufa +
277 " </ td ><td >" + fieldAccessDiff + " </ td > </ tr >\ n ");
278

279 sb . append (" </ table >");


280
APPENDIX R. AOP PERFORMANCE TEST 156

281 return sb . toString ();


282 }
283

284 public ObjectName preRegister ( MBeanServer arg0 , ObjectName arg1 )


285 throws Exception {
286 return null ;
287 }
288

289 public void postRegister ( Boolean arg0 ) {}


290

291 public void preDeregister () throws Exception {}


292

293 public void postDeregister () {}


294 }
APPENDIX R. AOP PERFORMANCE TEST 157

R.2 PerformanceTestMBean.java

Source of jboss.thesis.inventory.model.jmx.PerformanceTestMBean
1 package jboss . thesis . inventory . model . jmx ;
2

4 /**
5 * @author Christian Dalager , Simon Jorsal , Eske Sort
6 */
7 public interface PerformanceTestMBean {
8 public String runPerformanceSuite ( int iterations );
9 public double testConstruction ( int iterations );
10 public double testConstructionWithFieldSet ( int iterations );
11 public double testUnadvisedConstructionWithFieldSet( int iterations );
12 public double testUnadvisedConstruction ( int iterations );
13 public double testMethodStatic ( int iterations );
14 public double testUnadvisedMethodStatic ( int iterations );
15 public double testMethod ( int iterations );
16 public double testUnadvisedMethod ( int iterations );
17 public double testInterceptedMethod ( int iterations );
18 public double testNonPublicMethod ( int iterations );
19 public double testPublicMethod ( int iterations );
20 public double testFallThroughConstructionUnadvised( int iterations );
21 public double testFallThroughConstruction ( int iterations );
22 public double testFieldAccess ( int iterations );
23 public double testUnadvisedFieldAccess ( int iterations );
24 }
APPENDIX R. AOP PERFORMANCE TEST 158

R.3 ConstructorTest.java

Source of jboss.thesis.performancetest.ConstructorTest
1 package jboss . thesis . performancetest ;
2

3 /**
4 * @author Christian Dalager , Simon Jorsal , Eske Sort This Class is used to
5 * test , how fall - through constructors are performing aop vs .
6 * nonadvised
7 */
8 public class ConstructorTest {
9 // these fields are not used in this class , but they are used in
10 // the SimplePerformClassA
11 public static int k = 0;
12 public String str = " myString ";
13 private int i = 0;
14

15 public ConstructorTest () {
16 this ( null );
17 }
18

19 public ConstructorTest ( String s ) {


20 this (s , null );
21 }
22

23 public ConstructorTest ( String s , String p ) {}


24 }
APPENDIX R. AOP PERFORMANCE TEST 159

R.4 ConstructorTestUnadvised.java

Source of jboss.thesis.performancetest.ConstructorTestUnadvised
1 package jboss . thesis . performancetest ;
2

3 /**
4 * @author Christian Dalager , Simon Jorsal , Eske Sort This Class is used to
5 * test , how fall - through constructors are performing aop vs .
6 * nonadvised
7 */
8 public class ConstructorTestUnadvised {
9 // these fields are not used in this class , but they are used in
10 // the SimplePerformClassA
11 public static int k = 0;
12 public String str = " myString ";
13 private int i = 0;
14

15 public ConstructorTestUnadvised () {
16 this ( null );
17 }
18

19 public ConstructorTestUnadvised ( String s ) {


20 this (s , null );
21 }
22

23 public ConstructorTestUnadvised ( String s , String p ) {}


24 }
APPENDIX R. AOP PERFORMANCE TEST 160

R.5 PerformanceInterceptor.java

Source of jboss.thesis.performancetest.PerformanceInterceptor
1 package jboss . thesis . performancetest ;
2

3 import org . jboss . aop . Interceptor ;


4 import org . jboss . aop . Invocation ;
5

7 /**
8 * @author Christian Dalager , Simon Jorsal , Eske Sort
9 */
10 public class PerformanceInterceptor implements Interceptor {
11 public String getName () {
12 return " PerformanceInterceptor ";
13 }
14

15 public Object invoke ( Invocation invocation ) throws Throwable {


16 return invocation . invokeNext ();
17 }
18 }
APPENDIX R. AOP PERFORMANCE TEST 161

R.6 SimplePerformanceClassA.java

Source of jboss.thesis.performancetest.SimplePerformanceClassA
1 package jboss . thesis . performancetest ;
2

3 /**
4 * @author Christian Dalager , Simon Jorsal , Eske Sort
5 */
6 public class SimplePerformanceClassA {
7 public static int k = 0;
8 public String str = " myString ";
9 private int i = 0;
10

11 public SimplePerformanceClassA () {}
12

13 public SimplePerformanceClassA ( int i ) {


14 this .i = i;
15 }
16

17 public static double methodStatic ( double x ) {


18 if (k > 0) {
19 return x * x;
20 }
21 else
22 {
23 return 2 * methodStatic (x );
24 }
25 }
26

27 public double method ( double x ) {


28 if (k > 0) {
29 return x * x;
30 }
31 else
32 {
33 return 2 * method (x );
34 }
35 }
36

37 public double interceptorMethod ( double x ) {


38 if (k > 0) {
39 return x * x;
40 }
41 else
42 {
43 return 2 * interceptorMethod (x );
44 }
45 }
46

47 public double nonPublicMethod ( double x ) {


APPENDIX R. AOP PERFORMANCE TEST 162

48 return npm (x);


49 }
50

51 double npm ( double x ) {


52 if (k > 0) {
53 return x * x;
54 }
55 else
56 {
57 return 2 * npm (x);
58 }
59 }
60

61 public double publicMethod ( double x ) {


62 return npm (x);
63 }
64

65 double pm ( double x ) {
66 if (k > 0) {
67 return x * x;
68 }
69 else
70 {
71 return 2 * pm (x );
72 }
73 }
74 }
APPENDIX R. AOP PERFORMANCE TEST 163

R.7 SimplePerformanceClassB.java

Source of jboss.thesis.performancetest.SimplePerformanceClassB
1 package jboss . thesis . performancetest ;
2

3 /**
4 * @author Christian Dalager , Simon Jorsal , Eske Sort
5 */
6 public class SimplePerformanceClassB {
7 int i = 0;
8

9 public SimplePerformanceClassB ( int i ) {


10 this .i = i;
11 }
12 }
APPENDIX R. AOP PERFORMANCE TEST 164

R.8 SimpleUnadvisedPerformanceClassA.java

Source of jboss.thesis.performancetest.SimpleUnadvisedPerformanceClassA
1 package jboss . thesis . performancetest ;
2

3 /**
4 * @author Christian Dalager , Simon Jorsal , Eske Sort
5 */
6 public class SimpleUnadvisedPerformanceClassA {
7 public static int k = 0;
8 public String str = " myString ";
9 private int i = 0;
10

11 public SimpleUnadvisedPerformanceClassA() {}
12

13 public SimpleUnadvisedPerformanceClassA( int i ) {


14 this .i = i;
15 }
16

17 public static double methodStatic ( double x ) {


18 if (k > 0) {
19 return x * x;
20 }
21 else {
22 return 2 * methodStatic (x );
23 }
24 }
25

26 public double method ( double x ) {


27 if (k > 0) {
28 return x * x;
29 }
30 else {
31 return 2 * method (x );
32 }
33 }
34 }
APPENDIX R. AOP PERFORMANCE TEST 165

R.9 SimpleUnadvisedPerformanceClassB.java

Source of jboss.thesis.performancetest.SimpleUnadvisedPerformanceClassB
1 package jboss . thesis . performancetest ;
2

3 /**
4 * @author Christian Dalager , Simon Jorsal , Eske Sort
5 */
6 public class SimpleUnadvisedPerformanceClassB {
7 int i = 0;
8

9 public SimpleUnadvisedPerformanceClassB( int i ) {


10 this .i = i;
11 }
12 }
APPENDIX R. AOP PERFORMANCE TEST 166

R.10 Timer.java

Source of jboss.thesis.util.Timer
1 package jboss . thesis . util ;
2

3 /**
4 * @author Christian Dalager , Simon Jorsal , Eske Sort
5 */
6 public class Timer {
7 private long start ;
8

9 public Timer () {
10 start = System . currentTimeMillis ();
11 }
12

13 public double check () {


14 return ( System . currentTimeMillis () - start ) / 1000.0;
15 }
16 }
Part VI

Source of Instrumented Classes

167
Appendix S

Instrumented Decompiled
Classes

The classes below are a selection of instrumented classes from the Inventory Manage-
ment AOP-application. The classes were decompiled with the DJ Java Decompiler.

The classes below are all part of the jboss.thesis.inventory.model and jboss.the-
sis.inventory.controller packages.

S.1 Order.java

Source of jboss.thesis.inventory.model.Order
1 package jboss . thesis . inventory . model ;
2

3 import org . jboss . aop .*;


4

5 import java . io . Serializable ;


6

7 import java . lang . reflect . InvocationTargetException ;


8

9 import java . rmi . Remote ;


10

11 import java . util .*;


12

13

14 public class Order implements Remote , Serializable , Advised {


15 private static final long serialVersionUID = 0 x8b28c15036188a0L ;
16 private static final Class aop$class$WithoutAdvisement ;
17 private static final Advisor aop$classAdvisor$WithoutAdvisement;
18

19 static {

168
APPENDIX S. INSTRUMENTED DECOMPILED CLASSES 169

20 aop$class$WithoutAdvisement = Class. forName (


21 " jboss . thesis . inventory . model . Order ");
22 aop$classAdvisor$WithoutAdvisement = AspectManager . instance (). getAdvisor (
23 aop$class$WithoutAdvisement );
24 }
25

26 private long id ;
27 private List reservations ;
28 private boolean invoiceCreated ;
29 private Date date ;
30 private Customer customer ;
31 protected transient ClassInstanceAdvisor _instanceAdvisor ;
32

33 public Order () {
34 _instanceAdvisor = new ClassInstanceAdvisor ( this );
35 reservations_w_$WithoutAdvisement( this , new ArrayList ());
36 date_w_$WithoutAdvisement ( this , new Date ());
37 }
38

39 public long jboss$thesis$inventory$model$Order$setId$WithoutAdvisement() {


40 id_w_$WithoutAdvisement ( this , IdUtil . getNextId (1));
41

42 return id_r_$WithoutAdvisement ( this );


43 }
44

45 public Iterator
46 jboss$thesis$inventory$model$Order$getReservationIterator$WithoutAdvisement() {
47 return reservations_r_$WithoutAdvisement( this ). iterator ();
48 }
49

50 public void
51 jboss$thesis$inventory$model$Order$addReservation$WithoutAdvisement(
52 Reservation reservation ) {
53 reservations_r_$WithoutAdvisement( this ). add ( reservation );
54 }
55

56 public void
57 jboss$thesis$inventory$model$Order$removeReservation$WithoutAdvisement(
58 Reservation reservation ) {
59 reservations_r_$WithoutAdvisement( this ). remove ( reservation );
60 }
61

62 public void
63 jboss$thesis$inventory$model$Order$removeReservation$WithoutAdvisement(
64 int index ) {
65 reservations_r_$WithoutAdvisement( this ). remove ( index );
66 }
67

68 public void
69 jboss$thesis$inventory$model$Order$clearReservations$WithoutAdvisement() {
70 reservations_r_$WithoutAdvisement( this ). clear ();
APPENDIX S. INSTRUMENTED DECOMPILED CLASSES 170

71 }
72

73 public Reservation
74 jboss$thesis$inventory$model$Order$getReservation$WithoutAdvisement(
75 int index ) {
76 Reservation reservation = null ;
77

78 try {
79 reservation = ( Reservation ) reservations_r_$WithoutAdvisement( this ). get (
80 index );
81 }
82 catch ( IndexOutOfBoundsException ignored ) {}
83

84 return reservation ;
85 }
86

87 public Reservation
88 jboss$thesis$inventory$model$Order$getReservationByProduct$WithoutAdvisement(
89 Product product ) {
90 for (
91 Iterator i = reservations_r_$WithoutAdvisement( this ). iterator ();
92 i. hasNext ();) {
93 Reservation current = ( Reservation ) i. next ();
94

95 if ( current . getProduct (). equals ( product )) {


96 return current ;
97 }
98 }
99

100 return null ;


101 }
102

103 public boolean


104 jboss$thesis$inventory$model$Order$containsReservation$WithoutAdvisement(
105 Reservation reservation ) {
106 for (
107 Iterator i = reservations_r_$WithoutAdvisement( this ). iterator ();
108 i. hasNext ();) {
109 if ((( Reservation ) i. next ()). getProduct (). equals (
110 reservation . getProduct ())) {
111 return true ;
112 }
113 }
114

115 return false ;


116 }
117

118 public int


119 jboss$thesis$inventory$model$Order$sizeOfReservationList$WithoutAdvisement() {
120 return reservations_r_$WithoutAdvisement( this ). size ();
121 }
APPENDIX S. INSTRUMENTED DECOMPILED CLASSES 171

122

123 public void


124 jboss$thesis$inventory$model$Order$createInvoice$WithoutAdvisement() {
125 Reservation current ;
126 Product product ;
127

128 for (
129 Iterator i = reservations_r_$WithoutAdvisement( this ). iterator ();
130 i. hasNext (); product . decreaseStockBy ( current . getQuantity ())) {
131 current = ( Reservation ) i. next ();
132 product = current . getProduct ();
133 }
134

135 invoiceCreated_w_$WithoutAdvisement( this , true );


136 }
137

138 public double


139 jboss$thesis$inventory$model$Order$getFullPrice$WithoutAdvisement() {
140 double price = 0.0 D;
141

142 for (
143 Iterator i = reservations_r_$WithoutAdvisement( this ). iterator ();
144 i. hasNext ();) {
145 price += (( Reservation ) i. next ()). getPrice ();
146 }
147

148 return price ;


149 }
150

151 public Customer


152 jboss$thesis$inventory$model$Order$getCustomer$WithoutAdvisement() {
153 return customer_r_$WithoutAdvisement( this );
154 }
155

156 public void


157 jboss$thesis$inventory$model$Order$setCustomer$WithoutAdvisement(
158 Customer customer ) {
159 customer_w_$WithoutAdvisement( this , customer );
160 }
161

162 public long jboss$thesis$inventory$model$Order$getId$WithoutAdvisement() {


163 return id_r_$WithoutAdvisement ( this );
164 }
165

166 public Date jboss$thesis$inventory$model$Order$getDate$WithoutAdvisement() {


167 return date_r_$WithoutAdvisement ( this );
168 }
169

170 public boolean


171 jboss$thesis$inventory$model$Order$invoiceCreated$WithoutAdvisement() {
172 return invoiceCreated_r_$WithoutAdvisement( this );
APPENDIX S. INSTRUMENTED DECOMPILED CLASSES 172

173 }
174

175 public boolean jboss$thesis$inventory$model$Order$equals$WithoutAdvisement(


176 Object obj ) {
177 boolean classesAreCompatible = getClass (). isAssignableFrom ( obj . getClass ());
178

179 if (! classesAreCompatible ) {
180 return false ;
181 }
182

183 return (( Order ) obj ). getId () == id_r_$WithoutAdvisement ( this );


184 }
185

186 public Advisor _getAdvisor () {


187 return aop$classAdvisor$WithoutAdvisement;
188 }
189

190 public InstanceAdvisor _getInstanceAdvisor () {


191 return _instanceAdvisor ;
192 }
193

194 public void _setInstanceAdvisor ( InstanceAdvisor instanceadvisor ) {


195 _instanceAdvisor = ( ClassInstanceAdvisor ) instanceadvisor ;
196 }
197

198 private Object _added_m$0 ( Object [] aobj , long l ) throws Throwable {


199 return (( ClassAdvisor ) _getAdvisor ()). invokeMethod ( this , l , aobj );
200 }
201

202 public long setId () {


203 if (! _instanceAdvisor . hasAspects ()) {
204 return jboss$thesis$inventory$model$Order$setId$WithoutAdvisement();
205 }
206 else {
207 return (( Long ) _added_m$0 ( new Object [0] ,
208 0 x517537c0a8c246d9L )). longValue ();
209 }
210 }
211

212 public Iterator getReservationIterator () {


213 if (! _instanceAdvisor . hasAspects ()) {
214 return
215 jboss$thesis$inventory$model$Order$getReservationIterator$WithoutAdvisement();
216 }
217 else {
218 return ( Iterator ) _added_m$0 ( new Object [0] , 0 xd938627954174fd7L );
219 }
220 }
221

222 public void addReservation ( Reservation reservation ) {


223 if (! _instanceAdvisor . hasAspects ()) {
APPENDIX S. INSTRUMENTED DECOMPILED CLASSES 173

224 jboss$thesis$inventory$model$Order$addReservation$WithoutAdvisement(
225 reservation );
226

227 return ;
228 }
229

230 _added_m$0 ( new Object [] { reservation } , 0 x84e44468b85bba08L );


231 }
232

233 public void removeReservation ( Reservation reservation ) {


234 if (! _instanceAdvisor . hasAspects ()) {
235 jboss$thesis$inventory$model$Order$removeReservation$WithoutAdvisement(
236 reservation );
237

238 return ;
239 }
240

241 _added_m$0 ( new Object [] { reservation } , 0 x82fac8f90afa4ebcL );


242 }
243

244 public void removeReservation ( int i ) {


245 if (! _instanceAdvisor . hasAspects ()) {
246 jboss$thesis$inventory$model$Order$removeReservation$WithoutAdvisement(i );
247

248 return ;
249 }
250

251 _added_m$0 ( new Object [] { new Integer (i ) } , 0 xd67f3f71fa6612f2L );


252 }
253

254 public void clearReservations () {


255 if (! _instanceAdvisor . hasAspects ()) {
256 jboss$thesis$inventory$model$Order$clearReservations$WithoutAdvisement();
257

258 return ;
259 }
260

261 _added_m$0 ( new Object [0] , 0 xf3b9ba45bae1700eL );


262 }
263

264 public Reservation getReservation ( int i ) {


265 if (! _instanceAdvisor . hasAspects ()) {
266 return
267 jboss$thesis$inventory$model$Order$getReservation$WithoutAdvisement(i );
268 }
269 else {
270 return ( Reservation ) _added_m$0 (
271 new Object [] { new Integer (i ) } , 0 x19ac370cd6407db3L );
272 }
273 }
274
APPENDIX S. INSTRUMENTED DECOMPILED CLASSES 174

275 public Reservation getReservationByProduct ( Product product ) {


276 if (! _instanceAdvisor . hasAspects ()) {
277 return
278 jboss$thesis$inventory$model$Order$getReservationByProduct$WithoutAdvisement(
279 product );
280 }
281 else {
282 return ( Reservation ) _added_m$0 (
283 new Object [] { product } , 0 x8c2f98b40261512cL );
284 }
285 }
286

287 public boolean containsReservation ( Reservation reservation ) {


288 if (! _instanceAdvisor . hasAspects ()) {
289 return
290 jboss$thesis$inventory$model$Order$containsReservation$WithoutAdvisement(
291 reservation );
292 }
293 else {
294 return (( Boolean ) _added_m$0 (
295 new Object [] { reservation } , 0 x959a15e0391d1f78L )). booleanValue ();
296 }
297 }
298

299 public int sizeOfReservationList () {


300 if (! _instanceAdvisor . hasAspects ()) {
301 return
302 jboss$thesis$inventory$model$Order$sizeOfReservationList$WithoutAdvisement();
303 }
304 else {
305 return (( Integer ) _added_m$0 ( new Object [0] ,
306 0 x83a163788ec50a3cL )). intValue ();
307 }
308 }
309

310 public void createInvoice () {


311 if (! _instanceAdvisor . hasAspects ()) {
312 jboss$thesis$inventory$model$Order$createInvoice$WithoutAdvisement();
313

314 return ;
315 }
316

317 _added_m$0 ( new Object [0] , 0 x30e56d6b9490fab9L );


318 }
319

320 public double getFullPrice () {


321 if (! _instanceAdvisor . hasAspects ()) {
322 return
323 jboss$thesis$inventory$model$Order$getFullPrice$WithoutAdvisement();
324 }
325 else {
APPENDIX S. INSTRUMENTED DECOMPILED CLASSES 175

326 return (( Double ) _added_m$0 ( new Object [0] ,


327 0 xdd45f78621173e64L )). doubleValue ();
328 }
329 }
330

331 public Customer getCustomer () {


332 if (! _instanceAdvisor . hasAspects ()) {
333 return jboss$thesis$inventory$model$Order$getCustomer$WithoutAdvisement();
334 }
335 else {
336 return ( Customer ) _added_m$0 ( new Object [0] , 0 x3c6954ef8c320ec3L );
337 }
338 }
339

340 public void setCustomer ( Customer customer1 ) {


341 if (! _instanceAdvisor . hasAspects ()) {
342 jboss$thesis$inventory$model$Order$setCustomer$WithoutAdvisement(
343 customer1 );
344

345 return ;
346 }
347

348 _added_m$0 ( new Object [] { customer1 } , 0 xfd7fab9bf40ef489L );


349 }
350

351 public long getId () {


352 if (! _instanceAdvisor . hasAspects ()) {
353 return jboss$thesis$inventory$model$Order$getId$WithoutAdvisement();
354 }
355 else {
356 return (( Long ) _added_m$0 ( new Object [0] ,
357 0 xac2adf437a698318L )). longValue ();
358 }
359 }
360

361 public Date getDate () {


362 if (! _instanceAdvisor . hasAspects ()) {
363 return jboss$thesis$inventory$model$Order$getDate$WithoutAdvisement();
364 }
365 else {
366 return ( Date ) _added_m$0 ( new Object [0] , 0 xf1e1dff0bf5db304L );
367 }
368 }
369

370 public boolean invoiceCreated () {


371 if (! _instanceAdvisor . hasAspects ()) {
372 return
373 jboss$thesis$inventory$model$Order$invoiceCreated$WithoutAdvisement();
374 }
375 else {
376 return (( Boolean ) _added_m$0 ( new Object [0] ,
APPENDIX S. INSTRUMENTED DECOMPILED CLASSES 176

377 0 x35a42dff3a062956L )). booleanValue ();


378 }
379 }
380

381 public boolean equals ( Object obj ) {


382 if (! _instanceAdvisor . hasAspects ()) {
383 return jboss$thesis$inventory$model$Order$equals$WithoutAdvisement( obj );
384 }
385 else {
386 return (( Boolean ) _added_m$0 ( new Object [] { obj } ,
387 0 xd9a52e52b5f070c0L )). booleanValue ();
388 }
389 }
390

391 private static Object _added_m$1 ( Object [] aobj , int i ) {


392 return ClassAdvisor . trapRead (
393 aobj [0] , i , aop$classAdvisor$WithoutAdvisement);
394 }
395

396 private static Customer customer_r_$WithoutAdvisement( Object obj ) {


397 return ( Customer ) _added_m$1 ( new Object [] { obj } , 0);
398 }
399

400 private static Object _added_m$2 ( Object [] aobj , int i ) {


401 return ClassAdvisor . trapWrite (
402 aobj [0] , i , aobj [1] , aop$classAdvisor$WithoutAdvisement);
403 }
404

405 private static void customer_w_$WithoutAdvisement(


406 Object obj , Customer customer1 ) {
407 _added_m$2 ( new Object [] { obj , customer1 } , 0);
408 }
409

410 private static Date date_r_$WithoutAdvisement ( Object obj ) {


411 return ( Date ) _added_m$1 ( new Object [] { obj } , 1);
412 }
413

414 private static void date_w_$WithoutAdvisement ( Object obj , Date date1 ) {


415 _added_m$2 ( new Object [] { obj , date1 } , 1);
416 }
417

418 private static long id_r_$WithoutAdvisement ( Object obj ) {


419 return (( Long ) _added_m$1 ( new Object [] { obj } , 2)). longValue ();
420 }
421

422 private static void id_w_$WithoutAdvisement ( Object obj , long l ) {


423 _added_m$2 ( new Object [] { obj , new Long (l ) } , 2);
424 }
425

426 private static boolean invoiceCreated_r_$WithoutAdvisement( Object obj ) {


427 return (( Boolean ) _added_m$1 ( new Object [] { obj } , 3)). booleanValue ();
APPENDIX S. INSTRUMENTED DECOMPILED CLASSES 177

428 }
429

430 private static void invoiceCreated_w_$WithoutAdvisement(


431 Object obj , boolean flag ) {
432 _added_m$2 ( new Object [] { obj , new Boolean ( flag ) } , 3);
433 }
434

435 private static List reservations_r_$WithoutAdvisement( Object obj ) {


436 return ( List ) _added_m$1 ( new Object [] { obj } , 4);
437 }
438

439 private static void reservations_w_$WithoutAdvisement( Object obj , List list ) {


440 _added_m$2 ( new Object [] { obj , list } , 4);
441 }
442

443 private static Object _added_m$3 ( Object [] aobj , int i ) {


444 return ClassAdvisor . trapConstructor (
445 aobj , ( ClassAdvisor ) aop$classAdvisor$WithoutAdvisement , i );
446 }
447

448 public static Order Order_new_$WithoutAdvisement ()


449 throws InvocationTargetException {
450 return ( Order ) _added_m$3 ( new Object [0] , 0);
451 }
452 }
APPENDIX S. INSTRUMENTED DECOMPILED CLASSES 178

S.2 ProductComposite.java

Source of jboss.thesis.inventory.model.ProductComposite
1 package jboss . thesis . inventory . model ;
2

3 import jboss . thesis . inventory . service .*;


4

5 import org . jboss . aop .*;


6

7 import java . io . Serializable ;


8

9 import java . lang . reflect . InvocationTargetException ;


10

11 import java . rmi . Remote ;


12

13 import java . util . ArrayList ;


14 import java . util . Iterator ;
15

16

17 public class ProductComposite implements Product , Serializable , Remote , Advised ,


18 MinimumStock , ReservationCounter {
19 private static final long serialVersionUID = 0 x66f6f14335cd541cL ;
20 private static final Class aop$class$WithoutAdvisement ;
21 private static final Advisor aop$classAdvisor$WithoutAdvisement;
22

23 static {
24 aop$class$WithoutAdvisement = Class. forName (
25 " jboss . thesis . inventory . model . ProductComposite ");
26 aop$classAdvisor$WithoutAdvisement = AspectManager . instance (). getAdvisor (
27 aop$class$WithoutAdvisement );
28 }
29

30 private long id ;
31 private String name ;
32 private Type type ;
33 private String description ;
34 private String manufacturer ;
35 private double price ;
36 private ArrayList products ;
37 protected transient ClassInstanceAdvisor _instanceAdvisor ;
38 private transient ProductCompositeMixin
39 _jboss$thesis$inventory$service$ProductCompositeMixin$aop$mixin;
40

41 public ProductComposite () {
42 _instanceAdvisor = new ClassInstanceAdvisor ( this );
43 _jboss$thesis$inventory$service$ProductCompositeMixin$aop$mixin =
44 new ProductCompositeMixin ( this );
45 products_w_$WithoutAdvisement( this , new ArrayList ());
46 }
47
APPENDIX S. INSTRUMENTED DECOMPILED CLASSES 179

48 public ProductComposite ( String name ) {


49 _instanceAdvisor = new ClassInstanceAdvisor ( this );
50 _jboss$thesis$inventory$service$ProductCompositeMixin$aop$mixin =
51 new ProductCompositeMixin ( this );
52 products_w_$WithoutAdvisement( this , new ArrayList ());
53 name_w_$WithoutAdvisement ( this , name );
54 }
55

56 public long
57 jboss$thesis$inventory$model$ProductComposite$setId$WithoutAdvisement() {
58 id_w_$WithoutAdvisement ( this , IdUtil . getNextId (0));
59

60 return id_r_$WithoutAdvisement ( this );


61 }
62

63 public void
64 jboss$thesis$inventory$model$ProductComposite$add$WithoutAdvisement(
65 Product product ) {
66 products_r_$WithoutAdvisement( this ). add ( product );
67 }
68

69 public long
70 jboss$thesis$inventory$model$ProductComposite$getId$WithoutAdvisement() {
71 return id_r_$WithoutAdvisement ( this );
72 }
73

74 public Product
75 jboss$thesis$inventory$model$ProductComposite$get$WithoutAdvisement(
76 int index ) {
77 return ( Product ) products_r_$WithoutAdvisement( this ). get ( index );
78 }
79

80 public int
81 jboss$thesis$inventory$model$ProductComposite$numberOfProducts$WithoutAdvisement() {
82 return products_r_$WithoutAdvisement( this ). size ();
83 }
84

85 public void
86 jboss$thesis$inventory$model$ProductComposite$setName$WithoutAdvisement(
87 String name ) {
88 name_w_$WithoutAdvisement ( this , name );
89 }
90

91 public void
92 jboss$thesis$inventory$model$ProductComposite$setType$WithoutAdvisement(
93 Type type ) {
94 type_w_$WithoutAdvisement ( this , type );
95 }
96

97 public void
98 jboss$thesis$inventory$model$ProductComposite$setDescription$WithoutAdvisement(
APPENDIX S. INSTRUMENTED DECOMPILED CLASSES 180

99 String description ) {
100 description_w_$WithoutAdvisement( this , description );
101 }
102

103 public void


104 jboss$thesis$inventory$model$ProductComposite$setManufacturer$WithoutAdvisement(
105 String manufacturer ) {
106 manufacturer_w_$WithoutAdvisement( this , manufacturer );
107 }
108

109 public void


110 jboss$thesis$inventory$model$ProductComposite$setPrice$WithoutAdvisement(
111 double price ) {
112 price_w_$WithoutAdvisement ( this , price );
113 }
114

115 public String


116 jboss$thesis$inventory$model$ProductComposite$getName$WithoutAdvisement() {
117 return name_r_$WithoutAdvisement ( this );
118 }
119

120 public Type


121 jboss$thesis$inventory$model$ProductComposite$getType$WithoutAdvisement() {
122 return type_r_$WithoutAdvisement ( this );
123 }
124

125 public String


126 jboss$thesis$inventory$model$ProductComposite$getDescription$WithoutAdvisement() {
127 return description_r_$WithoutAdvisement( this );
128 }
129

130 public String


131 jboss$thesis$inventory$model$ProductComposite$getManufacturer$WithoutAdvisement() {
132 return manufacturer_r_$WithoutAdvisement( this );
133 }
134

135 public double


136 jboss$thesis$inventory$model$ProductComposite$getPrice$WithoutAdvisement() {
137 return price_r_$WithoutAdvisement ( this );
138 }
139

140 public int


141 jboss$thesis$inventory$model$ProductComposite$getStock$WithoutAdvisement() {
142 int minStock = -1;
143

144 for ( Iterator i = products_r_$WithoutAdvisement( this ). iterator ();


145 i. hasNext ();) {
146 if ( minStock != -1) {
147 minStock = Math . min ((( Product ) i. next ()). getStock () , minStock );
148 }
149 else {
APPENDIX S. INSTRUMENTED DECOMPILED CLASSES 181

150 minStock = (( Product ) i. next ()). getStock ();


151 }
152 }
153

154 return minStock ;


155 }
156

157 public String


158 jboss$thesis$inventory$model$ProductComposite$toString$WithoutAdvisement() {
159 return " ProductComposite ={" + products_r_$WithoutAdvisement( this ) + "}";
160 }
161

162 public void


163 jboss$thesis$inventory$model$ProductComposite$decreaseStockBy$WithoutAdvisement(
164 int number ) {
165 for (
166 Iterator i = products_r_$WithoutAdvisement( this ). iterator (); i. hasNext ();
167 (( Product ) i. next ()). decreaseStockBy ( number )) {
168 ;
169 }
170 }
171

172 public void


173 jboss$thesis$inventory$model$ProductComposite$increaseStockBy$WithoutAdvisement(
174 int number ) {
175 for (
176 Iterator i = products_r_$WithoutAdvisement( this ). iterator (); i. hasNext ();
177 (( Product ) i. next ()). increaseStockBy ( number )) {
178 ;
179 }
180 }
181

182 public boolean


183 jboss$thesis$inventory$model$ProductComposite$equals$WithoutAdvisement(
184 Object obj ) {
185 boolean classesAreCompatible = getClass (). isAssignableFrom ( obj . getClass ());
186

187 if (! classesAreCompatible ) {
188 return false ;
189 }
190

191 return (( Product ) obj ). getId () == id_r_$WithoutAdvisement ( this );


192 }
193

194 public int


195 jboss$thesis$inventory$model$ProductComposite$hashCode$WithoutAdvisement() {
196 return ( int ) id_r_$WithoutAdvisement ( this );
197 }
198

199 public Advisor _getAdvisor () {


200 return aop$classAdvisor$WithoutAdvisement;
APPENDIX S. INSTRUMENTED DECOMPILED CLASSES 182

201 }
202

203 public InstanceAdvisor _getInstanceAdvisor () {


204 return _instanceAdvisor ;
205 }
206

207 public void _setInstanceAdvisor ( InstanceAdvisor instanceadvisor ) {


208 _instanceAdvisor = ( ClassInstanceAdvisor ) instanceadvisor ;
209 }
210

211 private Object _added_m$0 ( Object [] aobj , long l ) throws Throwable {


212 return (( ClassAdvisor ) _getAdvisor ()). invokeMethod ( this , l , aobj );
213 }
214

215 public long setId () {


216 if (! _instanceAdvisor . hasAspects ()) {
217 return
218 jboss$thesis$inventory$model$ProductComposite$setId$WithoutAdvisement();
219 }
220 else {
221 return (( Long ) _added_m$0 ( new Object [0] ,
222 0 x517537c0a8c246d9L )). longValue ();
223 }
224 }
225

226 public void add ( Product product ) {


227 if (! _instanceAdvisor . hasAspects ()) {
228 jboss$thesis$inventory$model$ProductComposite$add$WithoutAdvisement(
229 product );
230

231 return ;
232 }
233

234 _added_m$0 ( new Object [] { product } , 0 x5e4206ca9e811724L );


235 }
236

237 public long getId () {


238 if (! _instanceAdvisor . hasAspects ()) {
239 return
240 jboss$thesis$inventory$model$ProductComposite$getId$WithoutAdvisement();
241 }
242 else {
243 return (( Long ) _added_m$0 ( new Object [0] ,
244 0 xac2adf437a698318L )). longValue ();
245 }
246 }
247

248 public Product get ( int i ) {


249 if (! _instanceAdvisor . hasAspects ()) {
250 return
251 jboss$thesis$inventory$model$ProductComposite$get$WithoutAdvisement(i );
APPENDIX S. INSTRUMENTED DECOMPILED CLASSES 183

252 }
253 else {
254 return ( Product ) _added_m$0 (
255 new Object [] { new Integer (i ) } , 0 xbd19d69d08df0e34L );
256 }
257 }
258

259 public int numberOfProducts () {


260 if (! _instanceAdvisor . hasAspects ()) {
261 return
262 jboss$thesis$inventory$model$ProductComposite$numberOfProducts$WithoutAdvisement();
263 }
264 else {
265 return (( Integer ) _added_m$0 ( new Object [0] ,
266 0 x8e0d71637ec444bcL )). intValue ();
267 }
268 }
269

270 public void setName ( String s ) {


271 if (! _instanceAdvisor . hasAspects ()) {
272 jboss$thesis$inventory$model$ProductComposite$setName$WithoutAdvisement(s );
273

274 return ;
275 }
276

277 _added_m$0 ( new Object [] { s } , 0 x12a7e75bde237f9fL );


278 }
279

280 public void setType ( Type type1 ) {


281 if (! _instanceAdvisor . hasAspects ()) {
282 jboss$thesis$inventory$model$ProductComposite$setType$WithoutAdvisement(
283 type1 );
284

285 return ;
286 }
287

288 _added_m$0 ( new Object [] { type1 } , 0 x45fbe79e790ae59cL );


289 }
290

291 public void setDescription ( String s ) {


292 if (! _instanceAdvisor . hasAspects ()) {
293 jboss$thesis$inventory$model$ProductComposite$setDescription$WithoutAdvisement(
294 s );
295

296 return ;
297 }
298

299 _added_m$0 ( new Object [] { s } , 0 x107aef86b9f74791L );


300 }
301

302 public void setManufacturer ( String s ) {


APPENDIX S. INSTRUMENTED DECOMPILED CLASSES 184

303 if (! _instanceAdvisor . hasAspects ()) {


304 jboss$thesis$inventory$model$ProductComposite$setManufacturer$WithoutAdvisement(
305 s );
306

307 return ;
308 }
309

310 _added_m$0 ( new Object [] { s } , 0 x3703edd8698d99acL );


311 }
312

313 public void setPrice ( double d ) {


314 if (! _instanceAdvisor . hasAspects ()) {
315 jboss$thesis$inventory$model$ProductComposite$setPrice$WithoutAdvisement(d );
316

317 return ;
318 }
319

320 _added_m$0 ( new Object [] { new Double (d ) } , 0 x4fe5b3747744f07eL );


321 }
322

323 public String getName () {


324 if (! _instanceAdvisor . hasAspects ()) {
325 return
326 jboss$thesis$inventory$model$ProductComposite$getName$WithoutAdvisement();
327 }
328 else {
329 return ( String ) _added_m$0 ( new Object [0] , 0 x57aafb80745d9046L );
330 }
331 }
332

333 public Type getType () {


334 if (! _instanceAdvisor . hasAspects ()) {
335 return
336 jboss$thesis$inventory$model$ProductComposite$getType$WithoutAdvisement();
337 }
338 else {
339 return ( Type ) _added_m$0 ( new Object [0] , 0 x5ef1f91b9af72137L );
340 }
341 }
342

343 public String getDescription () {


344 if (! _instanceAdvisor . hasAspects ()) {
345 return
346 jboss$thesis$inventory$model$ProductComposite$getDescription$WithoutAdvisement();
347 }
348 else {
349 return ( String ) _added_m$0 ( new Object [0] , 0 x5920661f221c08f4L );
350 }
351 }
352

353 public String getManufacturer () {


APPENDIX S. INSTRUMENTED DECOMPILED CLASSES 185

354 if (! _instanceAdvisor . hasAspects ()) {


355 return
356 jboss$thesis$inventory$model$ProductComposite$getManufacturer$WithoutAdvisement();
357 }
358 else {
359 return ( String ) _added_m$0 ( new Object [0] , 0 xafe29a8da7ee41e6L );
360 }
361 }
362

363 public double getPrice () {


364 if (! _instanceAdvisor . hasAspects ()) {
365 return
366 jboss$thesis$inventory$model$ProductComposite$getPrice$WithoutAdvisement();
367 }
368 else {
369 return (( Double ) _added_m$0 ( new Object [0] ,
370 0 xef2cd378b0c244a6L )). doubleValue ();
371 }
372 }
373

374 public int getStock () {


375 if (! _instanceAdvisor . hasAspects ()) {
376 return
377 jboss$thesis$inventory$model$ProductComposite$getStock$WithoutAdvisement();
378 }
379 else {
380 return (( Integer ) _added_m$0 ( new Object [0] ,
381 0 xfae8983fe6453c82L )). intValue ();
382 }
383 }
384

385 public String toString () {


386 if (! _instanceAdvisor . hasAspects ()) {
387 return
388 jboss$thesis$inventory$model$ProductComposite$toString$WithoutAdvisement();
389 }
390 else {
391 return ( String ) _added_m$0 ( new Object [0] , 0 x5f1e374c119d27bfL );
392 }
393 }
394

395 public void decreaseStockBy ( int i ) {


396 if (! _instanceAdvisor . hasAspects ()) {
397 jboss$thesis$inventory$model$ProductComposite$decreaseStockBy$WithoutAdvisement(
398 i );
399

400 return ;
401 }
402

403 _added_m$0 ( new Object [] { new Integer (i ) } , 0 xf8a556e321b9cf19L );


404 }
APPENDIX S. INSTRUMENTED DECOMPILED CLASSES 186

405

406 public void increaseStockBy ( int i ) {


407 if (! _instanceAdvisor . hasAspects ()) {
408 jboss$thesis$inventory$model$ProductComposite$increaseStockBy$WithoutAdvisement(
409 i );
410

411 return ;
412 }
413

414 _added_m$0 ( new Object [] { new Integer (i ) } , 0 xf997fe3d4d4a2a3fL );


415 }
416

417 public boolean equals ( Object obj ) {


418 if (! _instanceAdvisor . hasAspects ()) {
419 return
420 jboss$thesis$inventory$model$ProductComposite$equals$WithoutAdvisement( obj );
421 }
422 else {
423 return (( Boolean ) _added_m$0 ( new Object [] { obj } ,
424 0 xd9a52e52b5f070c0L )). booleanValue ();
425 }
426 }
427

428 public int hashCode () {


429 if (! _instanceAdvisor . hasAspects ()) {
430 return
431 jboss$thesis$inventory$model$ProductComposite$hashCode$WithoutAdvisement();
432 }
433 else {
434 return (( Integer ) _added_m$0 ( new Object [0] ,
435 0 x23ff0f30e995eeabL )). intValue ();
436 }
437 }
438

439 private static Object _added_m$1 ( Object [] aobj , int i ) {


440 return ClassAdvisor . trapRead (
441 aobj [0] , i , aop$classAdvisor$WithoutAdvisement);
442 }
443

444 private static String description_r_$WithoutAdvisement( Object obj ) {


445 return ( String ) _added_m$1 ( new Object [] { obj } , 0);
446 }
447

448 private static Object _added_m$2 ( Object [] aobj , int i ) {


449 return ClassAdvisor . trapWrite (
450 aobj [0] , i , aobj [1] , aop$classAdvisor$WithoutAdvisement);
451 }
452

453 private static void description_w_$WithoutAdvisement( Object obj , String s ) {


454 _added_m$2 ( new Object [] { obj , s } , 0);
455 }
APPENDIX S. INSTRUMENTED DECOMPILED CLASSES 187

456

457 private static long id_r_$WithoutAdvisement ( Object obj ) {


458 return (( Long ) _added_m$1 ( new Object [] { obj } , 1)). longValue ();
459 }
460

461 private static void id_w_$WithoutAdvisement ( Object obj , long l ) {


462 _added_m$2 ( new Object [] { obj , new Long (l ) } , 1);
463 }
464

465 private static String manufacturer_r_$WithoutAdvisement( Object obj ) {


466 return ( String ) _added_m$1 ( new Object [] { obj } , 2);
467 }
468

469 private static void manufacturer_w_$WithoutAdvisement( Object obj , String s ) {


470 _added_m$2 ( new Object [] { obj , s } , 2);
471 }
472

473 private static String name_r_$WithoutAdvisement ( Object obj ) {


474 return ( String ) _added_m$1 ( new Object [] { obj } , 3);
475 }
476

477 private static void name_w_$WithoutAdvisement ( Object obj , String s ) {


478 _added_m$2 ( new Object [] { obj , s } , 3);
479 }
480

481 private static double price_r_$WithoutAdvisement ( Object obj ) {


482 return (( Double ) _added_m$1 ( new Object [] { obj } , 4)). doubleValue ();
483 }
484

485 private static void price_w_$WithoutAdvisement ( Object obj , double d ) {


486 _added_m$2 ( new Object [] { obj , new Double (d ) } , 4);
487 }
488

489 private static ArrayList products_r_$WithoutAdvisement( Object obj ) {


490 return ( ArrayList ) _added_m$1 ( new Object [] { obj } , 5);
491 }
492

493 private static void products_w_$WithoutAdvisement(


494 Object obj , ArrayList arraylist ) {
495 _added_m$2 ( new Object [] { obj , arraylist } , 5);
496 }
497

498 private static Type type_r_$WithoutAdvisement ( Object obj ) {


499 return ( Type ) _added_m$1 ( new Object [] { obj } , 6);
500 }
501

502 private static void type_w_$WithoutAdvisement ( Object obj , Type type1 ) {


503 _added_m$2 ( new Object [] { obj , type1 } , 6);
504 }
505

506 private static Object _added_m$3 ( Object [] aobj , int i ) {


APPENDIX S. INSTRUMENTED DECOMPILED CLASSES 188

507 return ClassAdvisor . trapConstructor (


508 aobj , ( ClassAdvisor ) aop$classAdvisor$WithoutAdvisement , i );
509 }
510

511 public static ProductComposite ProductComposite_new_$WithoutAdvisement()


512 throws InvocationTargetException {
513 return ( ProductComposite ) _added_m$3 ( new Object [0] , 0);
514 }
515

516 public static ProductComposite ProductComposite_new_$WithoutAdvisement(


517 String s ) throws InvocationTargetException {
518 return ( ProductComposite ) _added_m$3 ( new Object [] { s } , 1);
519 }
520

521 private Object _added_m$4 ( Object [] aobj , long l ) throws Throwable {


522 return (( ClassAdvisor ) _getAdvisor ()). invokeMethod (
523 _getInstanceAdvisor () ,
524 _jboss$thesis$inventory$service$ProductCompositeMixin$aop$mixin , l , aobj );
525 }
526

527 public int getMinimumStock () {


528 return (( Integer ) _added_m$4 ( new Object [0] , 0 x91a734e41d3a147bL )). intValue ();
529 }
530

531 public void setMinimumStock ( int i ) {


532 _added_m$4 ( new Object [] { new Integer (i ) } , 0 xdb773c5ac4ef6981L );
533 }
534

535 public void incrementReservations ( int i ) {


536 _added_m$4 ( new Object [] { new Integer (i ) } , 0 x26ca754e21768ba1L );
537 }
538

539 public void decrementReservations ( int i ) {


540 _added_m$4 ( new Object [] { new Integer (i ) } , 0 x64a0eec490be6d1cL );
541 }
542

543 public int getNumberOfReservations () {


544 return (( Integer ) _added_m$4 ( new Object [0] , 0 x7455ecf09972e617L )). intValue ();
545 }
546 }
APPENDIX S. INSTRUMENTED DECOMPILED CLASSES 189

S.3 ProductImpl.java

Source of jboss.thesis.inventory.model.ProductImpl
1 package jboss . thesis . inventory . model ;
2

3 import jboss . thesis . inventory . service .*;


4

5 import org . jboss . aop .*;


6

7 import java . lang . reflect . InvocationTargetException ;


8

9 import java . rmi . Remote ;


10

11

12 public class ProductImpl implements Product , Remote , Advised , MinimumStock ,


13 ReservationCounter {
14 private static final long serialVersionUID = -0 x962aaf2c86a1ac0L ;
15 private static final Class aop$class$WithoutAdvisement ;
16 private static final Advisor aop$classAdvisor$WithoutAdvisement;
17

18 static {
19 aop$class$WithoutAdvisement = Class. forName (
20 " jboss . thesis . inventory . model . ProductImpl ");
21 aop$classAdvisor$WithoutAdvisement = AspectManager . instance (). getAdvisor (
22 aop$class$WithoutAdvisement );
23 }
24

25 private long id ;
26 private String name ;
27 private Type type ;
28 private String description ;
29 private String manufacturer ;
30 private double price ;
31 private int stock ;
32 protected transient ClassInstanceAdvisor _instanceAdvisor ;
33 private transient ProductMixin
34 _jboss$thesis$inventory$service$ProductMixin$aop$mixin;
35

36 public ProductImpl () {
37 _instanceAdvisor = new ClassInstanceAdvisor ( this );
38 _jboss$thesis$inventory$service$ProductMixin$aop$mixin = new ProductMixin (
39 this , 20 , 0);
40 }
41

42 public ProductImpl ( String name ) {


43 _instanceAdvisor = new ClassInstanceAdvisor ( this );
44 _jboss$thesis$inventory$service$ProductMixin$aop$mixin = new ProductMixin (
45 this , 20 , 0);
46 name_w_$WithoutAdvisement ( this , name );
47 }
APPENDIX S. INSTRUMENTED DECOMPILED CLASSES 190

48

49 public long
50 jboss$thesis$inventory$model$ProductImpl$setId$WithoutAdvisement() {
51 id_w_$WithoutAdvisement ( this , IdUtil . getNextId (0));
52

53 return id_r_$WithoutAdvisement ( this );


54 }
55

56 public void
57 jboss$thesis$inventory$model$ProductImpl$setName$WithoutAdvisement(
58 String name ) {
59 name_w_$WithoutAdvisement ( this , name );
60 }
61

62 public long
63 jboss$thesis$inventory$model$ProductImpl$getId$WithoutAdvisement() {
64 return id_r_$WithoutAdvisement ( this );
65 }
66

67 public void
68 jboss$thesis$inventory$model$ProductImpl$setType$WithoutAdvisement(
69 Type type ) {
70 type_w_$WithoutAdvisement ( this , type );
71 }
72

73 public void
74 jboss$thesis$inventory$model$ProductImpl$setDescription$WithoutAdvisement(
75 String description ) {
76 description_w_$WithoutAdvisement( this , description );
77 }
78

79 public void
80 jboss$thesis$inventory$model$ProductImpl$setManufacturer$WithoutAdvisement(
81 String manufacturer ) {
82 manufacturer_w_$WithoutAdvisement( this , manufacturer );
83 }
84

85 public void
86 jboss$thesis$inventory$model$ProductImpl$setPrice$WithoutAdvisement(
87 double price ) {
88 price_w_$WithoutAdvisement ( this , price );
89 }
90

91 public String
92 jboss$thesis$inventory$model$ProductImpl$getName$WithoutAdvisement() {
93 return name_r_$WithoutAdvisement ( this );
94 }
95

96 public Type
97 jboss$thesis$inventory$model$ProductImpl$getType$WithoutAdvisement() {
98 return type_r_$WithoutAdvisement ( this );
APPENDIX S. INSTRUMENTED DECOMPILED CLASSES 191

99 }
100

101 public String


102 jboss$thesis$inventory$model$ProductImpl$getDescription$WithoutAdvisement() {
103 return description_r_$WithoutAdvisement( this );
104 }
105

106 public String


107 jboss$thesis$inventory$model$ProductImpl$getManufacturer$WithoutAdvisement() {
108 return manufacturer_r_$WithoutAdvisement( this );
109 }
110

111 public double


112 jboss$thesis$inventory$model$ProductImpl$getPrice$WithoutAdvisement() {
113 return price_r_$WithoutAdvisement ( this );
114 }
115

116 public int


117 jboss$thesis$inventory$model$ProductImpl$getStock$WithoutAdvisement() {
118 return stock_r_$WithoutAdvisement ( this );
119 }
120

121 public void


122 jboss$thesis$inventory$model$ProductImpl$setStock$WithoutAdvisement(
123 int stock ) {
124 stock_w_$WithoutAdvisement ( this , stock );
125 }
126

127 public String


128 jboss$thesis$inventory$model$ProductImpl$toString$WithoutAdvisement() {
129 return " Product :" + getName ();
130 }
131

132 public void


133 jboss$thesis$inventory$model$ProductImpl$decreaseStockBy$WithoutAdvisement(
134 int number ) {
135 stock_w_$WithoutAdvisement ( this , stock_r_$WithoutAdvisement ( this ) - number );
136 }
137

138 public void


139 jboss$thesis$inventory$model$ProductImpl$increaseStockBy$WithoutAdvisement(
140 int number ) {
141 stock_w_$WithoutAdvisement ( this , stock_r_$WithoutAdvisement ( this ) + number );
142 }
143

144 public boolean


145 jboss$thesis$inventory$model$ProductImpl$equals$WithoutAdvisement(
146 Object obj ) {
147 boolean classesAreCompatible = getClass (). isAssignableFrom ( obj . getClass ());
148

149 if (! classesAreCompatible ) {
APPENDIX S. INSTRUMENTED DECOMPILED CLASSES 192

150 return false ;


151 }
152

153 return (( Product ) obj ). getId () == id_r_$WithoutAdvisement ( this );


154 }
155

156 public int


157 jboss$thesis$inventory$model$ProductImpl$hashCode$WithoutAdvisement() {
158 return ( int ) id_r_$WithoutAdvisement ( this );
159 }
160

161 public Advisor _getAdvisor () {


162 return aop$classAdvisor$WithoutAdvisement;
163 }
164

165 public InstanceAdvisor _getInstanceAdvisor () {


166 return _instanceAdvisor ;
167 }
168

169 public void _setInstanceAdvisor ( InstanceAdvisor instanceadvisor ) {


170 _instanceAdvisor = ( ClassInstanceAdvisor ) instanceadvisor ;
171 }
172

173 private Object _added_m$0 ( Object [] aobj , long l ) throws Throwable {


174 return (( ClassAdvisor ) _getAdvisor ()). invokeMethod ( this , l , aobj );
175 }
176

177 public long setId () {


178 if (! _instanceAdvisor . hasAspects ()) {
179 return
180 jboss$thesis$inventory$model$ProductImpl$setId$WithoutAdvisement();
181 }
182 else
183 {
184 return (( Long ) _added_m$0 ( new Object [0] ,
185 0 x517537c0a8c246d9L )). longValue ();
186 }
187 }
188

189 public void setName ( String s ) {


190 if (! _instanceAdvisor . hasAspects ()) {
191 jboss$thesis$inventory$model$ProductImpl$setName$WithoutAdvisement(s );
192

193 return ;
194 }
195

196 _added_m$0 ( new Object [] { s } , 0 x12a7e75bde237f9fL );


197 }
198

199 public long getId () {


200 if (! _instanceAdvisor . hasAspects ()) {
APPENDIX S. INSTRUMENTED DECOMPILED CLASSES 193

201 return
202 jboss$thesis$inventory$model$ProductImpl$getId$WithoutAdvisement();
203 }
204 else
205 {
206 return (( Long ) _added_m$0 ( new Object [0] ,
207 0 xac2adf437a698318L )). longValue ();
208 }
209 }
210

211 public void setType ( Type type1 ) {


212 if (! _instanceAdvisor . hasAspects ()) {
213 jboss$thesis$inventory$model$ProductImpl$setType$WithoutAdvisement( type1 );
214

215 return ;
216 }
217

218 _added_m$0 ( new Object [] { type1 } , 0 x45fbe79e790ae59cL );


219 }
220

221 public void setDescription ( String s ) {


222 if (! _instanceAdvisor . hasAspects ()) {
223 jboss$thesis$inventory$model$ProductImpl$setDescription$WithoutAdvisement(s );
224

225 return ;
226 }
227

228 _added_m$0 ( new Object [] { s } , 0 x107aef86b9f74791L );


229 }
230

231 public void setManufacturer ( String s ) {


232 if (! _instanceAdvisor . hasAspects ()) {
233 jboss$thesis$inventory$model$ProductImpl$setManufacturer$WithoutAdvisement(s );
234

235 return ;
236 }
237

238 _added_m$0 ( new Object [] { s } , 0 x3703edd8698d99acL );


239 }
240

241 public void setPrice ( double d ) {


242 if (! _instanceAdvisor . hasAspects ()) {
243 jboss$thesis$inventory$model$ProductImpl$setPrice$WithoutAdvisement(d );
244

245 return ;
246 }
247

248 _added_m$0 ( new Object [] { new Double (d ) } , 0 x4fe5b3747744f07eL );


249 }
250

251 public String getName () {


APPENDIX S. INSTRUMENTED DECOMPILED CLASSES 194

252 if (! _instanceAdvisor . hasAspects ()) {


253 return
254 jboss$thesis$inventory$model$ProductImpl$getName$WithoutAdvisement();
255 }
256 else
257 {
258 return ( String ) _added_m$0 ( new Object [0] , 0 x57aafb80745d9046L );
259 }
260 }
261

262 public Type getType () {


263 if (! _instanceAdvisor . hasAspects ()) {
264 return
265 jboss$thesis$inventory$model$ProductImpl$getType$WithoutAdvisement();
266 }
267 else
268 {
269 return ( Type ) _added_m$0 ( new Object [0] , 0 x5ef1f91b9af72137L );
270 }
271 }
272

273 public String getDescription () {


274 if (! _instanceAdvisor . hasAspects ()) {
275 return
276 jboss$thesis$inventory$model$ProductImpl$getDescription$WithoutAdvisement();
277 }
278 else
279 {
280 return ( String ) _added_m$0 ( new Object [0] , 0 x5920661f221c08f4L );
281 }
282 }
283

284 public String getManufacturer () {


285 if (! _instanceAdvisor . hasAspects ()) {
286 return
287 jboss$thesis$inventory$model$ProductImpl$getManufacturer$WithoutAdvisement();
288 }
289 else
290 {
291 return ( String ) _added_m$0 ( new Object [0] , 0 xafe29a8da7ee41e6L );
292 }
293 }
294

295 public double getPrice () {


296 if (! _instanceAdvisor . hasAspects ()) {
297 return
298 jboss$thesis$inventory$model$ProductImpl$getPrice$WithoutAdvisement();
299 }
300 else
301 {
302 return (( Double ) _added_m$0 ( new Object [0] ,
APPENDIX S. INSTRUMENTED DECOMPILED CLASSES 195

303 0 xef2cd378b0c244a6L )). doubleValue ();


304 }
305 }
306

307 public int getStock () {


308 if (! _instanceAdvisor . hasAspects ()) {
309 return
310 jboss$thesis$inventory$model$ProductImpl$getStock$WithoutAdvisement();
311 }
312 else
313 {
314 return (( Integer ) _added_m$0 ( new Object [0] ,
315 0 xfae8983fe6453c82L )). intValue ();
316 }
317 }
318

319 public void setStock ( int i ) {


320 if (! _instanceAdvisor . hasAspects ()) {
321 jboss$thesis$inventory$model$ProductImpl$setStock$WithoutAdvisement(i );
322

323 return ;
324 }
325

326 _added_m$0 ( new Object [] { new Integer (i ) } , 0 x3178a1603a1527b8L );


327 }
328

329 public String toString () {


330 if (! _instanceAdvisor . hasAspects ()) {
331 return
332 jboss$thesis$inventory$model$ProductImpl$toString$WithoutAdvisement();
333 }
334 else
335 {
336 return ( String ) _added_m$0 ( new Object [0] , 0 x5f1e374c119d27bfL );
337 }
338 }
339

340 public void decreaseStockBy ( int i ) {


341 if (! _instanceAdvisor . hasAspects ()) {
342 jboss$thesis$inventory$model$ProductImpl$decreaseStockBy$WithoutAdvisement(i );
343

344 return ;
345 }
346

347 _added_m$0 ( new Object [] { new Integer (i ) } , 0 xf8a556e321b9cf19L );


348 }
349

350 public void increaseStockBy ( int i ) {


351 if (! _instanceAdvisor . hasAspects ()) {
352 jboss$thesis$inventory$model$ProductImpl$increaseStockBy$WithoutAdvisement(i );
353
APPENDIX S. INSTRUMENTED DECOMPILED CLASSES 196

354 return ;
355 }
356

357 _added_m$0 ( new Object [] { new Integer (i ) } , 0 xf997fe3d4d4a2a3fL );


358 }
359

360 public boolean equals ( Object obj ) {


361 if (! _instanceAdvisor . hasAspects ()) {
362 return jboss$thesis$inventory$model$ProductImpl$equals$WithoutAdvisement( obj );
363 }
364 else
365 {
366 return (( Boolean ) _added_m$0 ( new Object [] { obj } ,
367 0 xd9a52e52b5f070c0L )). booleanValue ();
368 }
369 }
370

371 public int hashCode () {


372 if (! _instanceAdvisor . hasAspects ()) {
373 return
374 jboss$thesis$inventory$model$ProductImpl$hashCode$WithoutAdvisement();
375 }
376 else
377 {
378 return (( Integer ) _added_m$0 ( new Object [0] ,
379 0 x23ff0f30e995eeabL )). intValue ();
380 }
381 }
382

383 private static Object _added_m$1 ( Object [] aobj , int i ) {


384 return ClassAdvisor . trapRead (
385 aobj [0] , i , aop$classAdvisor$WithoutAdvisement);
386 }
387

388 private static String description_r_$WithoutAdvisement( Object obj ) {


389 return ( String ) _added_m$1 ( new Object [] { obj } , 0);
390 }
391

392 private static Object _added_m$2 ( Object [] aobj , int i ) {


393 return ClassAdvisor . trapWrite (
394 aobj [0] , i , aobj [1] , aop$classAdvisor$WithoutAdvisement);
395 }
396

397 private static void description_w_$WithoutAdvisement( Object obj , String s ) {


398 _added_m$2 ( new Object [] { obj , s } , 0);
399 }
400

401 private static long id_r_$WithoutAdvisement ( Object obj ) {


402 return (( Long ) _added_m$1 ( new Object [] { obj } , 1)). longValue ();
403 }
404
APPENDIX S. INSTRUMENTED DECOMPILED CLASSES 197

405 private static void id_w_$WithoutAdvisement ( Object obj , long l ) {


406 _added_m$2 ( new Object [] { obj , new Long (l ) } , 1);
407 }
408

409 private static String manufacturer_r_$WithoutAdvisement( Object obj ) {


410 return ( String ) _added_m$1 ( new Object [] { obj } , 2);
411 }
412

413 private static void manufacturer_w_$WithoutAdvisement( Object obj , String s ) {


414 _added_m$2 ( new Object [] { obj , s } , 2);
415 }
416

417 private static String name_r_$WithoutAdvisement ( Object obj ) {


418 return ( String ) _added_m$1 ( new Object [] { obj } , 3);
419 }
420

421 private static void name_w_$WithoutAdvisement ( Object obj , String s ) {


422 _added_m$2 ( new Object [] { obj , s } , 3);
423 }
424

425 private static double price_r_$WithoutAdvisement ( Object obj ) {


426 return (( Double ) _added_m$1 ( new Object [] { obj } , 4)). doubleValue ();
427 }
428

429 private static void price_w_$WithoutAdvisement ( Object obj , double d ) {


430 _added_m$2 ( new Object [] { obj , new Double (d ) } , 4);
431 }
432

433 private static int stock_r_$WithoutAdvisement ( Object obj ) {


434 return (( Integer ) _added_m$1 ( new Object [] { obj } , 5)). intValue ();
435 }
436

437 private static void stock_w_$WithoutAdvisement ( Object obj , int i ) {


438 _added_m$2 ( new Object [] { obj , new Integer (i ) } , 5);
439 }
440

441 private static Type type_r_$WithoutAdvisement ( Object obj ) {


442 return ( Type ) _added_m$1 ( new Object [] { obj } , 6);
443 }
444

445 private static void type_w_$WithoutAdvisement ( Object obj , Type type1 ) {


446 _added_m$2 ( new Object [] { obj , type1 } , 6);
447 }
448

449 private static Object _added_m$3 ( Object [] aobj , int i ) {


450 return ClassAdvisor . trapConstructor (
451 aobj , ( ClassAdvisor ) aop$classAdvisor$WithoutAdvisement , i );
452 }
453

454 public static ProductImpl ProductImpl_new_$WithoutAdvisement()


455 throws InvocationTargetException {
APPENDIX S. INSTRUMENTED DECOMPILED CLASSES 198

456 return ( ProductImpl ) _added_m$3 ( new Object [0] , 0);


457 }
458

459 public static ProductImpl ProductImpl_new_$WithoutAdvisement( String s)


460 throws InvocationTargetException {
461 return ( ProductImpl ) _added_m$3 ( new Object [] { s } , 1);
462 }
463

464 private Object _added_m$4 ( Object [] aobj , long l ) throws Throwable {


465 return (( ClassAdvisor ) _getAdvisor ()). invokeMethod (
466 _getInstanceAdvisor () ,
467 _jboss$thesis$inventory$service$ProductMixin$aop$mixin , l , aobj );
468 }
469

470 public int getMinimumStock () {


471 return (( Integer ) _added_m$4 ( new Object [0] , 0 x91a734e41d3a147bL )). intValue ();
472 }
473

474 public void setMinimumStock ( int i ) {


475 _added_m$4 ( new Object [] { new Integer (i ) } , 0 xdb773c5ac4ef6981L );
476 }
477

478 public void incrementReservations ( int i ) {


479 _added_m$4 ( new Object [] { new Integer (i ) } , 0 x26ca754e21768ba1L );
480 }
481

482 public void decrementReservations ( int i ) {


483 _added_m$4 ( new Object [] { new Integer (i ) } , 0 x64a0eec490be6d1cL );
484 }
485

486 public int getNumberOfReservations () {


487 return (( Integer ) _added_m$4 ( new Object [0] , 0 x7455ecf09972e617L )). intValue ();
488 }
489 }
APPENDIX S. INSTRUMENTED DECOMPILED CLASSES 199

S.4 Reservation.java

Source of jboss.thesis.inventory.model.Reservation
1 package jboss . thesis . inventory . model ;
2

3 import org . jboss . aop .*;


4

5 import java . lang . reflect . InvocationTargetException ;


6

7 import java . rmi . Remote ;


8

10 public class Reservation implements Remote , Advised {


11 private static final Class aop$class$WithoutAdvisement ;
12 private static final Advisor aop$classAdvisor$WithoutAdvisement;
13

14 static {
15 aop$class$WithoutAdvisement = Class. forName (
16 " jboss . thesis . inventory . model . Reservation ");
17 aop$classAdvisor$WithoutAdvisement = AspectManager . instance (). getAdvisor (
18 aop$class$WithoutAdvisement );
19 }
20

21 private long id ;
22 private int quantity ;
23 private Product product ;
24 protected transient ClassInstanceAdvisor _instanceAdvisor ;
25

26 public Reservation () {
27 _instanceAdvisor = new ClassInstanceAdvisor ( this );
28 }
29

30 public long jboss$thesis$inventory$model$Reservation$getId$WithoutAdvisement() {


31 return id_r_$WithoutAdvisement ( this );
32 }
33

34 public long jboss$thesis$inventory$model$Reservation$setId$WithoutAdvisement() {


35 id_w_$WithoutAdvisement ( this , IdUtil . getNextId (2));
36

37 return id_r_$WithoutAdvisement ( this );


38 }
39

40 public double
41 jboss$thesis$inventory$model$Reservation$getPrice$WithoutAdvisement() {
42 return product_r_$WithoutAdvisement ( this ). getPrice () *
43 ( double ) quantity_r_$WithoutAdvisement( this );
44 }
45

46 public Product
47 jboss$thesis$inventory$model$Reservation$getProduct$WithoutAdvisement() {
APPENDIX S. INSTRUMENTED DECOMPILED CLASSES 200

48 return product_r_$WithoutAdvisement ( this );


49 }
50

51 public void
52 jboss$thesis$inventory$model$Reservation$setProduct$WithoutAdvisement(
53 Product product ) {
54 product_w_$WithoutAdvisement ( this , product );
55 }
56

57 public int
58 jboss$thesis$inventory$model$Reservation$getQuantity$WithoutAdvisement() {
59 return quantity_r_$WithoutAdvisement( this );
60 }
61

62 public void
63 jboss$thesis$inventory$model$Reservation$setQuantity$WithoutAdvisement(
64 int quantity ) {
65 quantity_w_$WithoutAdvisement( this , quantity );
66 }
67

68 public boolean
69 jboss$thesis$inventory$model$Reservation$equals$WithoutAdvisement(
70 Object obj ) {
71 boolean classesAreCompatible = getClass (). isAssignableFrom ( obj . getClass ());
72

73 if (! classesAreCompatible ) {
74 return false ;
75 }
76

77 return (( Reservation ) obj ). getId () == id_r_$WithoutAdvisement ( this );


78 }
79

80 public Advisor _getAdvisor () {


81 return aop$classAdvisor$WithoutAdvisement;
82 }
83

84 public InstanceAdvisor _getInstanceAdvisor () {


85 return _instanceAdvisor ;
86 }
87

88 public void _setInstanceAdvisor ( InstanceAdvisor instanceadvisor ) {


89 _instanceAdvisor = ( ClassInstanceAdvisor ) instanceadvisor ;
90 }
91

92 private Object _added_m$0 ( Object [] aobj , long l ) throws Throwable {


93 return (( ClassAdvisor ) _getAdvisor ()). invokeMethod ( this , l , aobj );
94 }
95

96 public long getId () {


97 if (! _instanceAdvisor . hasAspects ()) {
98 return jboss$thesis$inventory$model$Reservation$getId$WithoutAdvisement();
APPENDIX S. INSTRUMENTED DECOMPILED CLASSES 201

99 }
100 else {
101 return (( Long ) _added_m$0 ( new Object [0] ,
102 0 xac2adf437a698318L )). longValue ();
103 }
104 }
105

106 public long setId () {


107 if (! _instanceAdvisor . hasAspects ()) {
108 return jboss$thesis$inventory$model$Reservation$setId$WithoutAdvisement();
109 }
110 else {
111 return (( Long ) _added_m$0 ( new Object [0] ,
112 0 x517537c0a8c246d9L )). longValue ();
113 }
114 }
115

116 public double getPrice () {


117 if (! _instanceAdvisor . hasAspects ()) {
118 return
119 jboss$thesis$inventory$model$Reservation$getPrice$WithoutAdvisement();
120 }
121 else {
122 return (( Double ) _added_m$0 ( new Object [0] ,
123 0 xef2cd378b0c244a6L )). doubleValue ();
124 }
125 }
126

127 public Product getProduct () {


128 if (! _instanceAdvisor . hasAspects ()) {
129 return
130 jboss$thesis$inventory$model$Reservation$getProduct$WithoutAdvisement();
131 }
132 else {
133 return ( Product ) _added_m$0 ( new Object [0] , 0 x5fe59ad1316a244aL );
134 }
135 }
136

137 public void setProduct ( Product product1 ) {


138 if (! _instanceAdvisor . hasAspects ()) {
139 jboss$thesis$inventory$model$Reservation$setProduct$WithoutAdvisement(
140 product1 );
141

142 return ;
143 }
144

145 _added_m$0 ( new Object [] { product1 } , 0 x2d3c76130c74207L );


146 }
147

148 public int getQuantity () {


149 if (! _instanceAdvisor . hasAspects ()) {
APPENDIX S. INSTRUMENTED DECOMPILED CLASSES 202

150 return
151 jboss$thesis$inventory$model$Reservation$getQuantity$WithoutAdvisement();
152 }
153 else {
154 return (( Integer ) _added_m$0 ( new Object [0] ,
155 0 x38e2a4bb703e541cL )). intValue ();
156 }
157 }
158

159 public void setQuantity ( int i ) {


160 if (! _instanceAdvisor . hasAspects ()) {
161 jboss$thesis$inventory$model$Reservation$setQuantity$WithoutAdvisement(i );
162 return ;
163 }
164

165 _added_m$0 ( new Object [] { new Integer (i ) } , 0 x39cf16c7579ce626L );


166 }
167

168 public boolean equals ( Object obj ) {


169 if (! _instanceAdvisor . hasAspects ()) {
170 return jboss$thesis$inventory$model$Reservation$equals$WithoutAdvisement(
171 obj );
172 }
173 else
174 {
175 return (( Boolean ) _added_m$0 ( new Object [] { obj } ,
176 0 xd9a52e52b5f070c0L )). booleanValue ();
177 }
178 }
179

180 private static Object _added_m$1 ( Object [] aobj , int i ) {


181 return ClassAdvisor . trapRead ( aobj [0] , i ,
182 aop$classAdvisor$WithoutAdvisement);
183 }
184

185 private static long id_r_$WithoutAdvisement ( Object obj ) {


186 return (( Long ) _added_m$1 ( new Object [] { obj } , 0)). longValue ();
187 }
188

189 private static Object _added_m$2 ( Object [] aobj , int i ) {


190 return ClassAdvisor . trapWrite ( aobj [0] , i , aobj [1] ,
191 aop$classAdvisor$WithoutAdvisement);
192 }
193

194 private static void id_w_$WithoutAdvisement ( Object obj , long l ) {


195 _added_m$2 ( new Object [] { obj , new Long (l ) } , 0);
196 }
197

198 private static Product product_r_$WithoutAdvisement ( Object obj ) {


199 return ( Product ) _added_m$1 ( new Object [] { obj } , 1);
200 }
APPENDIX S. INSTRUMENTED DECOMPILED CLASSES 203

201

202 private static void product_w_$WithoutAdvisement (


203 Object obj , Product product1 ) {
204 _added_m$2 ( new Object [] { obj , product1 } , 1);
205 }
206

207 private static int quantity_r_$WithoutAdvisement( Object obj ) {


208 return (( Integer ) _added_m$1 ( new Object [] { obj } , 2)). intValue ();
209 }
210

211 private static void quantity_w_$WithoutAdvisement( Object obj , int i ) {


212 _added_m$2 ( new Object [] { obj , new Integer (i ) } , 2);
213 }
214

215 private static Object _added_m$3 ( Object [] aobj , int i ) {


216 return ClassAdvisor . trapConstructor (
217 aobj , ( ClassAdvisor ) aop$classAdvisor$WithoutAdvisement , i );
218 }
219

220 public static Reservation Reservation_new_$WithoutAdvisement()


221 throws InvocationTargetException {
222 return ( Reservation ) _added_m$3 ( new Object [0] , 0);
223 }
224 }
Appendix T

Building and Deploying with Ant

Developing complex systems is not a simple matter. Using a build tool like Ant is
not just a good idea it is a necessity. As the construction and maintenance of build
scripts can be a major challenge we here supply the complete build script for our
Inventory Management system. It is here for inspiration note that it is not a
fine-tuned build script with production qualities and that it contains elements not
relevant for the code supplied in the appendices.

There is a build script (build.xml) and a property file (ant.properties).

T.1 Ant Properties File

Source of ant.properties
1 project . name = Inventory Management
2 version = 0.1
3 project = inventory - management
4 year = 2003
5

6 debug = on
7 optimize = on
8 deprecation = off
9

10 main . test . class = jboss . thesis . inventory . test . InventoryRemoteTestCase


11 main . class = jboss . thesis . inventory . client . MainWindow
12

13 # LIB SETTINGS
14 lib . dir = ${ basedir }/ lib
15 common . lib . dir = ${ basedir }/../ lib
16

17 # SRC SETTINGS
18 src . dir = ${ basedir }/ src

204
APPENDIX T. BUILDING AND DEPLOYING WITH ANT 205

19 src . main . dir = ${ src . dir }/ main


20 src . etc . dir = ${ src . dir }/ etc
21 src . client . dir = ${ src . main . dir }/ client
22 src . servlet . dir = ${ src . main . dir }/ servlet
23 src . ejb . dir = ${ src . main . dir }/ ejb
24 src . java . dir = ${ src . main . dir }/ java
25 src . aop . dir = ${ src . main . dir }/ aop
26 src . resources . dir = ${ basedir }/ ressources
27 src . web . dir = ${ src . dir }/ web
28 src . mbeans . dir = ${ src . main . dir }/ mbeans
29

30 src . metainf . dir = ${ src . etc . dir }/ META - INF


31 src . webinf . dir = ${ src . etc . dir }/ WEB - INF
32

33 # OTHER SETTINGS
34 jboss. home = ${ env . JBOSS_HOME }
35 jdk . home = ${ env . JAVA_HOME }
36 # java . home = ${ env . JAVA_HOME }
37 # ant . home = ${ env . ANT_HOME }
38 j2ee . jars = ${ lib . dir }/ j2ee . jar
39 servlet - lib . path = ${ jboss . home }/ server / default / lib / javax. servlet . jar
40 jboss. configuration = default
41 # print property info at every target invocation or not :
42 print - info = false
43

44

45 # DEPENDENCY DIRS
46

47 # BUILD SETTINGS
48 build. dir = ${ basedir }/ build
49 build. classes . dir = ${ build. dir }/ classes
50 build. tmp . dir = ${ build . dir }/ tmp
51 build. war . dir = ${ build . dir }/ war
52 build. aop . dir = ${ build . dir }/ aop
53 build. client . dir = ${ build . dir }/ client
54 build. generate . dir = ${ build . dir }/ generate
55 build. bin . dir = ${ build . dir }/ bin
56 build. javadocs . dir = ${ build . dir }/ docs / api
57 build. metainf . dir = ${ build. dir }/ META - INF
58 build. webinf . dir = ${ build . dir }/ WEB - INF
59 build. mbeans . dir = ${ build . dir }/ mbeans
60

61 # DISTRIBUTION / RELEASE SETTINGS


62 dist . dir = ${ build . dir }/ dist
63 release . dir = ${ build . dir }/ release
64 build. deploy . dir = ${ build . dir }/ deploy
65 # jboss . deploy = ${ env . JBOSS_HOME }/ server /${ jboss . configuration }/ deploy
66

67

68

69 # JUNIT SETTINGS
APPENDIX T. BUILDING AND DEPLOYING WITH ANT 206

70 junit. formatter . usefile = no


71 junit. printsummary = off
72 junit. haltonerror = yes
73 junit. haltonfailure = yes
74 junit. fork = true
75 junit. timeout = false
76 junit. jvm = java
APPENDIX T. BUILDING AND DEPLOYING WITH ANT 207

T.2 Ant Build File

Source of build.xml
1 <? xml version ="1.0"? >
2 < project name =" AOP - examples " default =" compile - all " basedir ="." >
3 <!--
4 Give user a chance to override without editing this file
5 ( and without typing -D each time they run it )
6 -->
7 < property file =" ${ basedir }/ ant . properties " / >
8 < property file =" ${ user . home }/ ant . properties " / >
9 < property environment =" env "/ >
10 < property name =" user " value =" ${ user . name }"/ >
11 < property name =" jboss . home " value =" ${ env . JBOSS_HOME }"/ >
12 < property name =" jdk . home " value =" ${ env . JAVA_HOME }"/ >
13 < property name =" junit . home " value =" ${ env . JUNIT_HOME }"/ >
14 < property name =" jboss . lib " value =" ${ jboss . home }/ lib " / >
15 < property name =" jboss . client " value =" ${ jboss . home }/ client " / >
16 < property name =" jboss . deploy "
17 value =" ${ env . JBOSS_HOME }/ server /${ jboss . configuration }/ deploy "/ >
18 < property name =" jboss . server . conf "
19 value =" ${ env . JBOSS_HOME }/ server /${ jboss . configuration }"/ >
20

21 < path id =" class . path ">


22 < path refid =" base . path "/ >
23 < fileset dir =" ${ lib . dir }" >
24 < include name ="**/*. jar "/ >
25 </ fileset >
26 < fileset dir =" ${ common . lib . dir }" >
27 < include name ="**/*. jar "/ >
28 </ fileset >
29 </ path >
30

31 < path id =" base . path ">


32 < pathelement location =" ${ build . classes . dir }" / >
33 < pathelement location =" ${ build . aop . dir }" / >
34 < pathelement location =" ${ junit . home }/ junit . jar " / >
35 < pathelement
36 location =" ${ env . JBOSS_HOME }/ server /${ jboss . configuration }/ lib / log4j . jar "
37 />
38 </ path >
39

40 <!-- Classpath to build and run the tests -->


41 < path id =" tests . classpath ">
42 < path refid =" mbean . classpath "/ >
43 </ path >
44

45 <!-- Classpath to build aop classpath -->


46 < path id =" jboss . aop . classpath ">
47 < path refid =" class . path "/ >
APPENDIX T. BUILDING AND DEPLOYING WITH ANT 208

48 < pathelement location =" ${ env . JBOSS_HOME }/ lib / jboss - system . jar " / >
49 < pathelement location =" ${ env . JBOSS_HOME }/ lib / jboss - common . jar " / >
50 < pathelement location =" ${ env . JBOSS_HOME }/ lib / javassist . jar " / >
51 < pathelement location =" ${ env . JBOSS_HOME }/ lib / jboss - jmx . jar " / >
52 < pathelement
53 location =" ${ env . JBOSS_HOME }/ server /${ jboss . configuration }/ lib / jboss . jar "
54 />
55

56 < pathelement
57 location =" ${ env . JBOSS_HOME }/ server /
58 ${ jboss . configuration }/ lib / jboss - aop . jar "
59 />
60

61 < pathelement
62 location =" ${ env . JBOSS_HOME }/ server /
63 ${ jboss . configuration }/ lib / javax . servlet . jar "
64 />
65

66 < pathelement
67 location =" ${ env . JBOSS_HOME }/ server /
68 ${ jboss . configuration }/ lib / jboss - j2ee . jar "
69 />
70 </ path >
71

72 <!-- Classpath to build aop services and MBeans -->


73 < path id =" mbean . classpath ">
74 < path refid =" jboss . aop . classpath "/ >
75 < pathelement
76 location =" ${ env . JBOSS_HOME }/ server /
77 ${ jboss . configuration }/ lib / jboss - aspects . jar "
78 />
79

80 < pathelement
81 location =" ${ env . JBOSS_HOME }/ server /
82 ${ jboss . configuration }/ lib / jboss - management . jar "
83 />
84

85 < pathelement
86 location =" ${ env . JBOSS_HOME }/ server /
87 ${ jboss . configuration }/ lib / jboss - remoting . jar "
88 />
89

90 < pathelement
91 location =" ${ env . JBOSS_HOME }/ server /
92 ${ jboss . configuration }/ lib / jmx - adaptor - plugin . jar "
93 />
94

95 < pathelement
96 location =" ${ env . JBOSS_HOME }/ server /
97 ${ jboss . configuration }/ lib / jnpserver . jar "
98 />
APPENDIX T. BUILDING AND DEPLOYING WITH ANT 209

99

100 <!-- include necessary jar files from jboss - client -->
101 < pathelement location =" ${ env . JBOSS_HOME }/ client / concurrent . jar " / >
102

103 <!-- special settings for DR3 -->


104 < pathelement
105 location =" ${ env . JBOSS_HOME }/ client / jmx -rmi - connector - client . jar " / >
106

107 <!-- include javassist -->


108 < pathelement
109 location =" ${ env . JBOSS_HOME }/ server /
110 ${ jboss . configuration }/ lib / javassist . jar "
111 />
112 </ path >
113

114 < path id =" client . classpath ">


115 < path refid =" class . path " / >
116 < pathelement location =" ${ build . client . dir }" / >
117 </ path >
118

119 < target name =" init ">


120 <!-- antcall target =" info " / - - >
121 </ target >
122

123 < target name =" info " if =" print - info ">
124 < echo message ="-------------- USER INFO -------------"/>
125 < echo message =" user = ${ user }"/ >
126 < echo message =" user . home = ${ user . home }"/ >
127 < echo message =" "/ >
128 < echo message ="-------------- HOME CONFIG -------------"/>
129 < echo message =" java . home = ${ java . home }"/ >
130 < echo message =" jdk . home = ${ jdk . home }"/ >
131 < echo message =" ant . home = ${ ant . home }"/ >
132 < echo message =" jboss . home = ${ jboss. home }"/ >
133 < echo message =" "/ >
134 < echo message ="-------------- DEPLOY DIRS -------------"/>
135 < echo message =" jboss . deploy = ${ jboss . deploy }"/ >
136 < echo message =" "/ >
137 < echo message ="-------------- JBOSS PATHS -------------"/>
138 < echo message =" jboss . configuration = ${ jboss . configuration }"/ >
139 < echo message =" jboss . lib = ${ jboss . lib }"/ >
140 < echo message =" jboss . client = ${ jboss . client }"/ >
141 < echo message =" jboss . lib = ${ jboss . lib }"/ >
142 < echo message =" "/ >
143 < echo message ="-------------- BUILD DIRS -------------"/>
144 < echo message =" build . classes . dir = ${ build . classes . dir }"/ >
145 < echo message =" build . war . dir = ${ build . war . dir }"/ >
146 < echo message =" build . deploy . dir = ${ build. deploy . dir }"/ >
147 < echo message =" build . dir = ${ build . dir }"/ >
148 < echo message =" lib . dir = ${ lib . dir }"/ >
149 < echo message =" "/ >
APPENDIX T. BUILDING AND DEPLOYING WITH ANT 210

150 < echo message ="-------------- SOURCE DIRS -------------"/>


151 < echo message =" src . dir = ${ src . dir }"/ >
152 < echo message =" src . ejb . dir = ${ src . ejb . dir }"/ >
153 < echo message =" src . etc . dir = ${ src . etc . dir }"/ >
154 < echo message =" src . web . dir = ${ src . web . dir }"/ >
155 < echo message =" src . java . dir = ${ src . java . dir }"/ >
156 < echo message =" src . metadata . dir = ${ src . metadata . dir }"/ >
157 < echo message =" "/ >
158 < echo message ="-------------- COMPILER OPTIONS -------------"/>
159 < echo message =" debug = ${ debug }"/ >
160 < echo message =" deprecation = ${ deprecation }"/ >
161 < echo message =" optimize = ${ optimize }"/ >
162 < echo message =" "/ >
163 < echo message ="-------------- JAVA CLASS PATH -------------"/>
164 < echo message =" java . class . path = ${ java . class . path }"/ >
165 </ target >
166

167 < target name =" compile - all " depends =" init ">
168 < antcall target =" compile "/ >
169 < antcall target =" compile - aop "/ >
170 < antcall target =" compile - mbeans "/ >
171 </ target >
172

173 < target name =" compile " depends =" init ">
174 < mkdir dir =" ${ build . classes . dir }"/ >
175

176 < javac destdir =" ${ build. classes . dir }" debug =" ${ debug }"
177 deprecation =" ${ deprecation }" optimize =" ${ optimize }"
178 classpathref =" mbean . classpath " >
179 < src path =" ${ src . java . dir }"/ >
180 </ javac >
181

182 <!-- set a property to true if the build . classes . dir is not empty -->
183 < available file =" ${ build . classes . dir }/ jboss " type =" dir "
184 property =" build . classes . dir -is -not - empty "/ >
185 </ target >
186

187 < target name =" compile - aop " depends =" init ">
188 < mkdir dir =" ${ build . aop . dir }"/ >
189 < antcall target =" deploy - util " / >
190

191 < javac destdir =" ${ build. aop . dir }" debug =" ${ debug }"
192 deprecation =" ${ deprecation }" optimize =" ${ optimize }"
193 classpathref =" mbean . classpath " >
194 < src path =" ${ src . aop . dir }"/ >
195 </ javac >
196

197 <!-- set a property to true if the build . aop . dir is not empty -->
198 < available file =" ${ build . aop . dir }/ jboss " type =" dir "
199 property =" build . aop .dir -is -not - empty "/ >
200 </ target >
APPENDIX T. BUILDING AND DEPLOYING WITH ANT 211

201

202 < target name =" compile - client " depends =" init ">
203 < mkdir dir =" ${ build . classes . dir }"/ >
204

205 < javac destdir =" ${ build. classes . dir }" debug =" ${ debug }"
206 deprecation =" ${ deprecation }" optimize =" ${ optimize }"
207 classpathref =" mbean. classpath ">
208 < src path =" ${ src . client . dir }"/ >
209 </ javac >
210

211 < copy todir =" ${ build . classes . dir }" >
212 < fileset dir =" ${ src . resources . dir }" includes =" jndi . properties , policy "/ >
213 </ copy >
214

215 <!-- set a property to true if the build . aop . dir is not empty -->
216 < available file =" ${ build . aop . dir }/ jboss " type =" dir "
217 property =" build . aop .dir -is -not - empty "/ >
218 </ target >
219

220 < target name =" compile - web " depends =" compile , compile - aop "
221 if =" servlet - lib . path ">
222 < mkdir dir =" ${ build . war . dir }"/ >
223

224 < path id =" web . path ">


225 < path refid =" class . path "/ >
226 </ path >
227

228 < javac destdir =" ${ build. war . dir }" debug =" ${ debug }"
229 deprecation =" ${ deprecation }" optimize =" ${ optimize }"
230 classpathref =" web . path " >
231 < src path =" ${ src . servlet . dir }"/ >
232 </ javac >
233

234 <!-- set a property to true if the build . war . dir is not empty -->
235 < available file =" ${ build . war . dir }/ jboss " type =" dir "
236 property =" build . war .dir -is -not - empty "/ >
237 </ target >
238

239 < target name =" compile - mbeans " depends =" compile - aop ">
240 < mkdir dir =" ${ build . mbeans . dir }"/ >
241

242 < javac destdir =" ${ build. mbeans . dir }" debug =" ${ debug }"
243 deprecation =" ${ deprecation }" optimize =" ${ optimize }"
244 classpathref =" mbean . classpath " >
245 < src path =" ${ src . mbeans . dir }"/ >
246 </ javac >
247

248 <!-- set a property to true if the build . mbeans . dir is not empty -->
249 < available file =" ${ build . mbeans . dir }/ jboss " type =" dir "
250 property =" build . mbeans . dir -is - not - empty "/ >
251 </ target >
APPENDIX T. BUILDING AND DEPLOYING WITH ANT 212

252

253 < target name =" sar " depends =" compile - mbeans , aop "
254 if =" build . mbeans .dir -is - not - empty ">
255 < mkdir dir =" ${ build . deploy . dir }"/ >
256 < mkdir dir =" ${ build . mbeans . dir }"/ >
257 < mkdir dir =" ${ build . metainf . dir }"/ >
258

259 <!-- rename ${ project }- service . xml to service . xml -->


260 < copy todir =" ${ build . metainf . dir }" >
261 < fileset dir =" ${ src . metainf . dir }" includes =" ${ project }- service . xml "/ >
262 </ copy >
263

264 < move file =" ${ build . metainf . dir }/ ${ project }- service . xml "
265 tofile =" ${ build . metainf . dir }/ jboss - service . xml "/ >
266

267 < copy file =" ${ src . resources . dir }/ policy " todir =" ${ build . metainf . dir }"/ >
268

269 <!-- create the sar file called ${ project }. sar -->
270 < jar jarfile =" ${ build . deploy . dir }/ ${ project }. sar ">
271 < metainf dir =" ${ build. metainf . dir }" >
272 < include name =" jboss - service . xml "/ >
273 < include name =" policy "/ >
274 </ metainf >
275 < fileset dir =" ${ build. mbeans . dir }"
276 excludes ="**/ Performance * ,**/ Experiment * " / >
277 < fileset dir =" ${ build. deploy . dir }" includes =" ${ project }- jar . aop "/ >
278 </ jar >
279

280 <!-- clean up a bit .. - - >


281 < delete dir =" ${ build . metainf . dir }"/ >
282 </ target >
283

284 < target name =" jar " depends =" compile " if =" build . classes .dir -is - not - empty ">
285 < mkdir dir =" ${ build . deploy . dir }"/ >
286 < mkdir dir =" ${ build . client . dir }"/ >
287

288 <!-- create the jar file called ${ project }- jar . jar -->
289 < jar jarfile =" ${ build . deploy . dir }/ ${ project }- jar . jar ">
290 < metainf dir =" ${ src . metainf . dir }" >
291 < include name =" ${ project }- jar . xml "/ >
292 </ metainf >
293 < fileset dir =" ${ build. classes . dir }" / >
294 </ jar >
295 </ target >
296

297 < target name =" util - jar " depends =" compile ">
298 < mkdir dir =" ${ build . deploy . dir }"/ >
299

300 <!-- create the jar file called thesis - util . jar -->
301 < jar jarfile =" ${ build . deploy . dir }/ thesis - util . jar ">
302 < fileset dir =" ${ build. classes . dir }" / >
APPENDIX T. BUILDING AND DEPLOYING WITH ANT 213

303 </ jar >


304 </ target >
305

306 < target name =" aop " depends =" compile - aop " if =" build . aop .dir -is - not - empty ">
307 < mkdir dir =" ${ build . deploy . dir }"/ >
308 < mkdir dir =" ${ build . metainf . dir }"/ >
309

310 <!-- rename ${ project }- aop . xml to jboss - aop . xml -->
311 < copy todir =" ${ build . metainf . dir }" >
312 < fileset dir =" ${ src . metainf . dir }" includes =" ${ project }- aop . xml "/ >
313 </ copy >
314

315 < move file =" ${ build . metainf . dir }/ ${ project }- aop . xml "
316 tofile =" ${ build . metainf . dir }/ jboss - aop . xml "/ >
317

318 <!-- create the jar file called ${ project }- jar . aop -->
319 < jar jarfile =" ${ build . deploy . dir }/ ${ project }- jar . aop ">
320 < metainf dir =" ${ build. metainf . dir }" >
321 < include name =" jboss - aop . xml "/ >
322 </ metainf >
323 < fileset dir =" ${ build. aop . dir }" >
324 < include name =" jboss / thesis / inventory / controller /**" / >
325 < include name =" jboss / thesis / inventory / model /**" / >
326 < include name =" jboss / thesis / inventory / service /**" / >
327 </ fileset >
328 </ jar >
329

330 <!-- clean up a bit .. - - >


331 < delete dir =" ${ build . metainf . dir }"/ >
332 </ target >
333

334 < target name =" war " depends =" compile - web " if =" build . war .dir -is - not - empty ">
335 < mkdir dir =" ${ build . deploy . dir }"/ >
336 < mkdir dir =" ${ build . classes . dir }"/ >
337

338 < war destfile =" ${ build . deploy . dir }/ ${ project }- web . war "
339 webxml =" ${ src . webinf . dir }/ ${ project }- web . xml " >
340 < fileset dir =" ${ src . web . dir }" excludes ="**/. donotremove "/ >
341 < classes dir =" ${ build. war . dir }"/ >
342 </ war >
343 </ target >
344

345 < target name =" ear " depends =" aop , jar ,war , sar ">
346 < ear appxml =" ${ src . metainf . dir }/ ${ project }- application . xml "
347 destfile =" ${ build . deploy . dir }/ ${ project }- app . ear ">
348 < fileset dir =" ${ build. deploy . dir }" includes ="*. war ,*. aop ,*. jar ,*. sar "
349 excludes ="*. ear "/ >
350 </ ear >
351 </ target >
352

353 < target name =" client - jar " depends =" compile , aop , compile - client ">
APPENDIX T. BUILDING AND DEPLOYING WITH ANT 214

354 < mkdir dir =" ${ build . deploy . dir }"/ >
355 < mkdir dir =" ${ build . client . dir }"/ >
356

357 < copy file =" ${ src . metainf . dir }/ log4j . xml " todir =" ${ build . deploy . dir }"/ >
358

359 <!-- create the jar file called ${ project }- client . jar -->
360 < jar jarfile =" ${ build . deploy . dir }/ ${ project }- client . jar ">
361 < fileset dir =" ${ build. classes . dir }" / >
362 < fileset dir =" ${ build. aop . dir }" / >
363 < manifest >
364 < attribute name =" Main - Class " value =" ${ main . class }"/ >
365 </ manifest >
366 </ jar >
367

368 <!-- Uncomment this the first time you run this target .
369 Comment out again after first run -->
370 <!--
371 < genkey alias =" inventory - management " storepass =" secret "
372 dname =" CN = Thesis Boyzz , OU = AOP Division , O= itu .dk , C= DK "/ >
373 -->
374

375 < copy file =" ${ env . JBOSS_HOME }/ client / concurrent . jar "
376 todir =" ${ build . deploy . dir }"/ >
377 < signjar jar =" ${ build . deploy . dir }/ concurrent . jar "
378 alias =" inventory - management " storepass =" secret "/ >
379

380 < copy


381 file =" ${ env . JBOSS_HOME }/ server /${ jboss . configuration }/ lib / jboss - aop . jar "
382 todir =" ${ build . deploy . dir }"/ >
383 < signjar jar =" ${ build . deploy . dir }/ jboss - aop . jar "
384 alias =" inventory - management " storepass =" secret "/ >
385

386 < copy file =" ${ env . JBOSS_HOME }/ client / jboss - common - client . jar "
387 todir =" ${ build . deploy . dir }"/ >
388 < signjar jar =" ${ build . deploy . dir }/ jboss - common - client . jar "
389 alias =" inventory - management " storepass =" secret "/ >
390

391 < copy


392 file =" ${ env . JBOSS_HOME }/ server /
393 ${ jboss . configuration }/ lib / jboss - remoting . jar "
394 todir =" ${ build . deploy . dir }"/ >
395 < signjar jar =" ${ build . deploy . dir }/ jboss - remoting . jar "
396 alias =" inventory - management " storepass =" secret "/ >
397

398 < copy


399 file =" ${ env . JBOSS_HOME }/ server /${ jboss . configuration }/ lib / jnpserver . jar "
400 todir =" ${ build . deploy . dir }"/ >
401 < signjar jar =" ${ build . deploy . dir }/ jnpserver . jar "
402 alias =" inventory - management " storepass =" secret "/ >
403

404 < signjar jar =" ${ build . deploy . dir }/ ${ project }- client . jar "
APPENDIX T. BUILDING AND DEPLOYING WITH ANT 215

405 alias =" inventory - management " storepass =" secret "/ >
406

407 < copy file =" ${ build . deploy . dir }/ concurrent . jar "
408 todir =" ${ build . deploy . dir }/ temp "/ >
409

410 < copy file =" ${ build . deploy . dir }/ jboss - aop . jar "
411 todir =" ${ build . deploy . dir }/ temp "/ >
412

413 < copy file =" ${ build . deploy . dir }/ ${ project }- client . jar "
414 todir =" ${ build . deploy . dir }/ temp "/ >
415

416 < copy file =" ${ build . deploy . dir }/ jboss - common - client . jar "
417 todir =" ${ build . deploy . dir }/ temp "/ >
418

419 < copy file =" ${ build . deploy . dir }/ jnpserver . jar "
420 todir =" ${ build . deploy . dir }/ temp "/ >
421

422 < copy file =" ${ build . deploy . dir }/ jboss - remoting . jar "
423 todir =" ${ build . deploy . dir }/ temp "/ >
424

425 < copy file =" ${ build . classes . dir }/ policy " todir =" ${ build . deploy . dir }/ temp "/ >
426

427 <!-- copy the jnlp DD to the deploy dir -->


428 < copy file =" ${ src . metainf . dir }/ ${ project }- client . jnlp "
429 todir =" ${ build . deploy . dir }"/ >
430 </ target >
431

432 < target name =" client - war " depends =" client - jar ">
433 < war destfile =" ${ build . deploy . dir }/ ${ project }- client . war "
434 webxml =" ${ src . webinf . dir }/ ${ project }- web . xml ">
435 < fileset dir =" ${ build. deploy . dir }/ temp " includes ="**/*. jar , **/ policy "/ >
436 < fileset dir =" ${ build. deploy . dir }" includes ="**/*. jnlp "/ >
437 </ war >
438 </ target >
439

440 < target name =" deploy " depends =" ear ">
441 < copy file =" ${ build . deploy . dir }/ ${ project }- app . ear "
442 todir =" ${ jboss . deploy }"/ >
443 </ target >
444

445 < target name =" deploy - aop " depends =" aop ">
446 < copy file =" ${ build . deploy . dir }/ ${ project }- jar . aop "
447 todir =" ${ jboss . deploy }"/ >
448 </ target >
449

450 < target name =" deploy - client " depends =" client - war ">
451 < copy file =" ${ build . deploy . dir }/ ${ project }- client . war "
452 todir =" ${ jboss . deploy }"/ >
453 </ target >
454

455 < target name =" undeploy - client " depends =" clean ">
APPENDIX T. BUILDING AND DEPLOYING WITH ANT 216

456 < delete file =" ${ jboss . deploy }/ ${ project }- client . war "/ >
457 </ target >
458

459 < target name =" deploy - sar " depends =" sar ">
460 < copy file =" ${ build . deploy . dir }/ ${ project }. sar " todir =" ${ jboss . deploy }"/ >
461 < copy file =" ${ src . resources . dir }/ minimumstock . properties "
462 todir =" ${ env . JBOSS_HOME }/ server /${ jboss . configuration }/ conf "/ >
463 </ target >
464

465 < target name =" undeploy - sar " depends =" clean ">
466 < delete file =" ${ jboss . deploy }/ ${ project }. sar "/ >
467 </ target >
468

469 < target name =" run - remote - client " depends =" compile , aop , compile - client ">
470 < java classname =" ${ main . class }" fork =" true " failonerror =" true "
471 maxmemory ="128 m " classpathref =" tests . classpath ">
472 < jvmarg
473 value =" - Djava . security . policy = file :/ ${ build . classes . dir }/ policy "/ >
474 < jvmarg
475 value =" - Dlog4j . configuration = file :/ ${ src . metainf . dir }/ log4j. xml "/ >
476 < jvmarg value =" - Dorg . jboss . logging . Logger . pluginClass =
477 org . jboss . logging . Log4jLoggerPlugin "/ >
478 </ java >
479 </ target >
480

481 < target name =" run - tests " depends =" compile - client ">
482 < junit dir =" ${ build . classes . dir }" printsummary =" ${ junit . printsummary }"
483 haltonerror =" ${ junit . haltonerror }" haltonfailure =" ${ junit. haltonfailure }"
484 fork =" ${ junit . fork }" jvm =" ${ junit. jvm }" >
485 < jvmarg value =" - Djava. security . policy = policy "/ >
486 < jvmarg value =" - Dlog4j . configuration = file :/ ${ src . metainf . dir }/ log4j . xml "
487 />
488 < jvmarg value =" - Dorg . jboss . logging . Logger . pluginClass =
489 org . jboss . logging . Log4jLoggerPlugin "/ >
490

491 < test name =" ${ main . test . class }" haltonfailure =" no " outfile =" result "/ >
492

493 < classpath >


494 < path refid =" tests . classpath "/ >
495 </ classpath >
496

497 < formatter type =" plain " usefile =" ${ junit . formatter . usefile }"/ >
498 </ junit >
499 </ target >
500

501 < target name =" clean ">


502 < delete dir =" ${ build . dir }"/ >
503 </ target >
504

505 < target name =" clean - deploy - sar " depends =" clean ">
506 < antcall target =" undeploy - sar "/ >
APPENDIX T. BUILDING AND DEPLOYING WITH ANT 217

507 </ target >


508

509 < target name =" deploy - util " depends =" util - jar ">
510 < copy file =" ${ build . deploy . dir }/ thesis - util . jar "
511 todir =" ${ env . JBOSS_HOME }/ server /${ jboss . configuration }/ lib "/ >
512

513 <!--
514 copy the src file instead of the comiled file . This will ensure
515 that the file will be included in a jboss jar file somewhere and thus
516 included on the class path and that it will be available at server boot .
517 -->
518 < copy file =" ${ src . metainf . dir }/ class - file - writer . properties "
519 todir =" ${ env . JBOSS_HOME }/ server /${ jboss. configuration }/ conf "/ >
520 </ target >
521

522 <! - -******************************************************************


523 * D E P L O Y - P E R F O R M A N C E T E S T
524 *
525 * This target packages and deploys the performancetest MBean and the
526 * required classes .
527 ****************************************************************** - - >
528 < target name =" deploy - performancetest " depends =" compile - mbeans , compile - aop "
529 if =" build . mbeans . dir -is - not - empty">
530 < mkdir dir =" ${ build . deploy . dir }"/ >
531 < mkdir dir =" ${ build . mbeans . dir }"/ >
532 < mkdir dir =" ${ build . metainf . dir }"/ >
533

534 <!-- rename ${ project }- aop . xml to jboss - aop . xml -->
535 < copy todir =" ${ build . metainf . dir }" >
536 < fileset dir =" ${ src . metainf . dir }" includes =" performancetest - aop . xml "/ >
537 </ copy >
538

539 < move file =" ${ build . metainf . dir }/ performancetest - aop . xml "
540 tofile =" ${ build . metainf . dir }/ jboss - aop . xml "/ >
541

542 <!-- create the jar file called performancetest - jar . aop -->
543 < jar jarfile =" ${ build . deploy . dir }/ performancetest - jar . aop ">
544 < metainf dir =" ${ build. metainf . dir }" >
545 < include name =" jboss - aop . xml "/ >
546 </ metainf >
547 < fileset dir =" ${ build. aop . dir }"
548 includes =" jboss / thesis / performancetest /**" / >
549 </ jar >
550

551 <!-- rename ${ project }- service . xml to service . xml -->


552 < copy todir =" ${ build . metainf . dir }" >
553 < fileset dir =" ${ src . metainf . dir }"
554 includes =" performancetest - service . xml "/ >
555 </ copy >
556

557 < move file =" ${ build . metainf . dir }/ performancetest - service . xml "
APPENDIX T. BUILDING AND DEPLOYING WITH ANT 218

558 tofile =" ${ build . metainf . dir }/ jboss - service . xml "/ >
559

560 <!-- create the sar file called ${ project }. sar -->
561 < jar jarfile =" ${ build . deploy . dir }/ performancetest . sar ">
562 < metainf dir =" ${ build. metainf . dir }" >
563 < include name =" jboss - service . xml "/ >
564 </ metainf >
565 < fileset dir =" ${ build. mbeans . dir }" includes ="**/ PerformanceT *" / >
566 < fileset dir =" ${ build. deploy . dir }" includes =" performancetest - jar . aop "/ >
567 < fileset dir =" ${ build. classes . dir }" includes ="**/ Timer . class "/ >
568 </ jar >
569

570 <!-- clean up a bit .. - - >


571 < delete dir =" ${ build . metainf . dir }"/ >
572

573 < copy file =" ${ build . deploy . dir }/ performancetest . sar "
574 todir =" ${ jboss . deploy }"/ >
575 </ target >
576

577 < target name =" undeploy - performancetest " depends =" clean ">
578 < delete file =" ${ jboss . deploy }/ performancetest . sar "/ >
579 </ target >
580

581 <! - -******************************************************************


582 * D E P L O Y - Experiments
583 *
584 * This target packages and deploys the Experiments mbean and the
585 * required classes .
586 ****************************************************************** - - >
587 < target name =" deploy - experiments " depends =" deploy - sar "
588 if =" build . mbeans . dir -is - not - empty">
589 < mkdir dir =" ${ build . deploy . dir }"/ >
590 < mkdir dir =" ${ build . mbeans . dir }"/ >
591 < mkdir dir =" ${ build . metainf . dir }"/ >
592

593 <!-- rename experiments - aop . xml to jboss - aop . xml -->
594 < copy todir =" ${ build . metainf . dir }" >
595 < fileset dir =" ${ src . metainf . dir }" includes =" experiments - aop . xml "/ >
596 </ copy >
597

598 < move file =" ${ build . metainf . dir }/ experiments - aop . xml "
599 tofile =" ${ build . metainf . dir }/ jboss - aop . xml "/ >
600

601 <!-- create the jar file called experiments - jar . aop -->
602 < jar jarfile =" ${ build . deploy . dir }/ experiments - jar . aop ">
603 < metainf dir =" ${ build. metainf . dir }" >
604 < include name =" jboss - aop . xml "/ >
605 </ metainf >
606 < fileset dir =" ${ build. aop . dir }" includes =" jboss / thesis / experiments /**" / >
607 </ jar >
608
APPENDIX T. BUILDING AND DEPLOYING WITH ANT 219

609 <!-- rename experiments - service . xml to service . xml -->


610 < copy todir =" ${ build . metainf . dir }" >
611 < fileset dir =" ${ src . metainf . dir }" includes =" experiments - service . xml "/ >
612 </ copy >
613

614 < move file =" ${ build . metainf . dir }/ experiments - service . xml "
615 tofile =" ${ build . metainf . dir }/ jboss - service . xml "/ >
616

617 <!-- create the sar file called experiments . sar -->
618 < jar jarfile =" ${ build . deploy . dir }/ experiments . sar ">
619 < metainf dir =" ${ build. metainf . dir }" >
620 < include name =" jboss - service . xml "/ >
621 <!-- include name =" policy "/ - - >
622 </ metainf >
623 < fileset dir =" ${ build. mbeans . dir }" includes ="**/ Experiment *" / >
624 < fileset dir =" ${ build. deploy . dir }" includes =" experiments - jar . aop "/ >
625 <!-- fileset dir =" ${ build . classes . dir }" includes =" Timer . class "/ - - >
626 </ jar >
627

628 <!-- clean up a bit .. - - >


629 < delete dir =" ${ build . metainf . dir }"/ >
630

631 < copy file =" ${ build . deploy . dir }/ experiments . sar " todir =" ${ jboss . deploy }"/ >
632 </ target >
633

634 < target name =" undeploy - experiments " depends =" undeploy - sar ">
635 < delete file =" ${ jboss . deploy }/ experiments . sar "/ >
636 </ target >
637 </ project >