This document discusses migrating to OSGi and modularity through a services-first approach. It presents a five stage modularity maturity model moving from ad hoc to optimized modularity. It discusses how popular instantiation patterns like Class.forName cause tight couplings that prevent modularity. Microservices primitives like a broker are presented as an alternative to break dependencies. An example is provided of extending Ant tasks using this approach to demonstrate migrating existing applications without fences by exploiting OSGi concepts. The conclusion is that a services-first approach enables modularity without fences, making a future migration to OSGi bundles easier.
5. 1. Ad Hoc
• Flat, manual class path
• Single name space
• Full visibility and normal
accessibility
• Monolithic
• Highly coupled
• Split Packages
• Add/Shuffle JARs until it works
6. 1. Ad Hoc
• Flat, manual class path
• Single name space
e l l
H
• Full visibility and normal
accessibility
• Monolithic
AR
•
•
Highly coupled
Split Packages J
• Add/Shuffle JARs until it works
7. 2. Managed
• Treat JARs as a module
• JAR Identity
• Naming
• Versioning
• Dependencies
• Repositories
8. 2. Managed
a d
• Treat JARs as a module
n l o
w he t
• JAR Identity
• Naming
D o t
• Versioning
r n e
• Dependencies
n t e
• Repositories
i
9. 3. Contracts
• Interface based design,
POJOs
• Provide contracts for
each connection
between JARs
• Implementation details
inside the JAR
• Versioning on contracts
10. 3. Contracts
•
d e r
a
Interface based design,
o
POJOs
• Provide contracts for
l s
s k
s c
a a
each connection
l h
between JARs
• Implementation details
inside the JAR c
• Versioning on contracts
12. 4. Fences
• Explicitly Import/Export
packages
• Explicitly specify
requirements and capabilities
o d!
•
•
Enforce the module
boundaries
Semantic Versioning
Go
• Side-by-side versioning
supported
13. 5. Optimize
• Exploit concepts for
modules and contracts
• Delegated Control
• Optimize the code base to
leverage new patterns:
• Extender
• Whiteboard
• Repeat
14. 5. Optimize
• Exploit concepts for
modules and contracts
• Delegated Control
• Optimize the code base to
leverage new patterns:
• Extender
• Whiteboard
• Repeat
15. Today
1.
Ad Hoc
2. 3.
Managed Contracts
4.
Fences
5.
Optimize
16. Today
1.
Ad Hoc Enterprise
DI
vn ,C
m ice ing
2. 3.
Ivy Managed Contracts
gu r
saw sp
jig
4.
Fences
5.
Optimize
17. Today
1.
Ad Hoc Enterprise
DI
vn ,C
m ice ing
2. 3.
Ivy Managed Contracts
gu r OSGi
saw s p
jig
4.
Fences
5.
Optimize
18. Today
1.
Ad Hoc Enterprise
DI
vn ,C
m ice ing
2. 3.
Ivy Managed Contracts
gu r OSGi
saw s p
jig
4.
Fences
5.
Optimize
57. So we need a broker
that runs without
fences...
58. So we need a Broker
that runs without
Fences...SR
o j o
P
59. POJOSR
• Developed by Karl Pauls
• JavaOne presentation 24811
• http://pojosr.googlecode.com
• Based on Apache Felix
60. Gain
• Existing libraries and many bundles work without
modification
• Bundle (JAR) activation (have their own local main)
• µServices
• Dynamicity (in µServices)
• Extender pattern (react on JAR content)
• Migration path to Fences (OSGi)
• Existing OSGi and non-OSGi tooling can be used
61. Loss
• No dynamic install/uninstall/update
• No side-by-side versioning
• No module privacy
• No explicit dependencies
• No Lazy activation
• No Bundle classpath
• No Native Code support
62. Migrating
• Example: extend ant … the tool we all
(sometimes) love and (sometimes) hate
• We make different <helloXXX/> tasks
64. Ant Your Service
• Base ant pojosr
ant
• Activator
• Extender
ant
...
...
65. Ant Your Service
• Base ant pojosr
ant
• Activator
• Extender
ant
...
...
66. Ant Your Service
Class<Task>
• Base ant pojosr
ant
• Activator
• Extender
ant
...
...
67. Ant Your Service
Class<Task>
hello
activator
• Base ant pojosr
ant
• Activator
• Extender
ant
...
...
68. Ant Your Service
Class<Task>
hello
activator
• Base ant pojosr
ant
• Activator
• Extender
ant
...
...
69. Ant Your Service
<project name="master">
<path id="bundles">
<fileset dir="bundles">
<include name="*.jar" />
</fileset>
</path>
<taskdef name="auto"
classname="aQute.ant.connect.AutoTask" classpathref="bundles" />
<auto />
<helloActivator />
</project>
70. Ant Your Service
public class Activator implements BundleActivator {
public void start(BundleContext context) throws Exception {
Properties props = new Properties();
props.put("ant", "helloActivator");
context.registerService(Class.class.getName(),
HelloTask.class, props);
}
public void stop(BundleContext context) throws Exception {
}
}
public class HelloTask extends Task {
String message = "Hello Activator";
public void execute() { System.out.println(message); }
public void setMessage(String m) { this.message = m; }
}
71. Ant Your Service
public class Activator implements BundleActivator {
t
public void start(BundleContext context) throws Exception {
f
Properties props = new Properties();
u
props.put("ant", "helloActivator");
r
context.registerService(Class.class.getName(),
c
HelloTask.class, props);
}
public void stop(BundleContext context) throws Exception {
}
}
public class HelloTask extends Task {
String message = "Hello Activator";
public void execute() { System.out.println(message); }
public void setMessage(String m) { this.message = m; }
}
72. Ant Your Service
Class<Task>
hello
activator
• Base ant pojosr
pojo
ant
• Activator
• Extender
ant
...
...
73. Ant Your Service
Class<Task>
hello
activator
• Base ant pojosr
pojo
ant
hello
extendee
• Activator
• Extender
ant
...
...
74. Ant Your Service
Class<Task>
hello
activator
• Base ant pojosr
pojo
ant
hello
extendee
• Activator
Manifest-Version: 1.0
• ant Ant-Task: helloExtender=HelloTask
Extender
...
...
75. Ant Your Service
public class HelloTask extends Task {
String message = "Hello Extender";
public void execute() { System.out.println(message); }
public void setMessage(String m) { this.message = m; }
}
76. Ant Your Service
public class HelloTask extends Task {
String message = "Hello Extender";
public void execute() { System.out.println(message); }
public void setMessage(String m) { this.message = m; }
}
u ft
c r
N O
77. Conclusion
• Moving to Fences is hard because popular
instance creation patterns are
fundamentally not modular
• Services-First approach works without
Fences
• After completion, moving to Fences is
much easier