Meeting 2
Aus JSUG
When: Monday, June 16th, 2008 - 19:00
Where: Freihaus HS4
Inhaltsverzeichnis |
[Bearbeiten] OSGi - The Next Generation Java Service Platform
Download the slides (pdf, 1.3MB).
You can also view the slides online.
[Bearbeiten] Preface
The presentation could also have been titled "SOA - The Java Way" or "My classpath is killing me" :) Therefore, it started with a chapter explaining todays problems with our classpath and the solution OSGi provides. At the end, Michael Greifeneder demoed an OSGi implementation called knopflerfish.
[Bearbeiten] Content
[Bearbeiten] The Problem today
- The humble JAR file we are used to create today
- Typical java application uses a lot of these
- All this results in a JAR hell
- Mostly transitive dependencies result in multiple versions of the same class
- Solution would be a registry, where JARs can demand certain libraries (dependencies) with proper names and versions
If you are lucky such JAR hell problem will "only" lead to the following error:
$ java org.bar.foo.Flibble Exception in thread "main" java.lang.NoSuchMethodError: com.foo.bar.Wibble.start()V at org.bar.foo.Flibble.main(Flibble.java:7) $
Or it could also be the case that the class and the method is present, but in a completly different version:
$ java org.bar.foo.Flibble Now doing something completly different... HA!!! $
[Bearbeiten] OSGi Specification
- Originally OSGi was the abbreviation for "Open Service Gateway Initiative" for embedded systems
- Today its the dynamic module system for Java
- The most famous IDE Eclipse itself is based on OSGi 3.0 (using its own implementation Equinox)
- Of course many implementations of OSGi are available, eg: Equinox, Apache Felix, Knopflerfish, ...
- The framework is layered in L0 to L3 (execution environment, modules, life cycle management and service registry)
- Instead of common JARs, you deploy so called "Bundles" instead
- The metadata is stored in the
manifest.mffile, extending usual stored data with OSGi specific properties
[Bearbeiten] SOA for Java
- "SOA has something to do with webservices, doesnt it?!"
- With the OSGi service platform, you provide services within the JVM
- Instead of a Broker, you have an OSGi Service Registry; instead a Service, there is a simple Java Object; instead of a Client there is another Java Object; and the Contract is realized with common Java Interfaces
- Such services could be system services (logging, preferences, configuration), protocol services (HTTP or UPnP service) or other services the like (XML parser service, ...)
[Bearbeiten] Code Example
Register your service:
public class MyBundleActivator implements BundleActivator { public void start(BundleContext context) { DbService service = new MyDbService(); context.registerService( DbService.class.getName(), service); } }
Use a specific service:
ServiceReference ref = context.getServiceReference(DbService.class.getName()); if (ref != null) { DbService service = context.lookup(ref); if (service != null) { service.callDbService(); } }
[Bearbeiten] Links
- http://www.osgi.org ... Official OSGi Website
- http://www.knopflerfish.org ... OpenSource OSGi implementation
- http://www.springsource.org/osgi ... Spring Dynamic Modules for OSGi Service Platforms
- http://www.ops4j.org ... Offers some usefull projects (eg: Pax-Construct if you use Maven)
- http://neilbartlett.name/blog/osgibook/ ... A nice free eBook about OSGi
- http://www.aqute.biz/OSGi/Presentations ... Other presentations about OSGi
[Bearbeiten] TechTips #1
Download the slides (pdf, 1.4MB).
You can also view the slides online.
[Bearbeiten] Preface
Christoph Pickl briefly presented two of Sun's Tech Tips, which are generally divided into Enterprise Java Technologies Tech Tips, Core Java Technologies Tech Tips and Mobility Tech Tips. Todays tips were about the Compiler API introduced with Java6 and how to use the well known printf method with Java.
[Bearbeiten] Compiler API
With Java6 you can invoke the Java Compiler from within your code in a standardized way (JSR-199). There are two different approaches to invoke the compiler, both are covered in the presentation.
[Bearbeiten] Simple Approach
Following things have to be done:
- Create sourcecode (could have been created automatically by a generator)
- Retrieve a
JavaCompilerinstance via theToolProvider - Invoke its
runmethod - Check the return code (0 for successfull)
- Get class via reflection (create instance, invoke methods, get/set fields, ...)
The JavaCompiler.run(InputStream in, OutputStream out, OutputStream err, String... args) is the single method which you have to invoke with the simple approach. If passing null values for in/out/err, the default System.in/out/err streams will be used. So actually the single mandatory argument is the last vararg String, defining the files to be compiled.
import javax.tools.JavaCompiler; import javax.tools.ToolProvider; public class CompilerApi { public static void main(String[] args) { String path = "src/my/package/Hello.java"; JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); if(compiler.run(null, null, null, path) == 0) { // do something with fresh compiled class } else { System.err.println("Ups, something went wrong!"); } } }
[Bearbeiten] Advanced Approach
With this approach, you have access to the exact error messages and therefore could be useful if you opt to write your own IDE for example.
// prepare compilation JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); // diagnostics instance will be usefull for analyzing errors DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>(); StandardJavaFileManager manager = compiler.getStandardFileManager( diagnostics, Locale.ENGLISH, new ISO_8859_11()); // put files which should be compiled into the manager String file="src/my/package/Hello2.java"; Iterable<? extends JavaFileObject> compilationUnits = manager.getJavaFileObjects(new String[] {file}); // retrieve and execute the compilation task CompilationTask task = compiler.getTask(null, manager, diagnostics, null, null, compilationUnits); if(task.call() == false) { // put error handling in here } manager.close();
If there were some errors, you could process them in the following way:
// error handling: for (Diagnostic d : diagnostics.getDiagnostics()) System.out.printf( "Code: %s%n" + "Kind: %s%n" + "Position: %s (%s/%s)%n" + "Source: %s%n" + "Message: %s%n", d.getCode(), d.getKind(), d.getPosition(), d.getStartPosition(), d.getEndPosition(), d.getSource(), d.getMessage(null) ); } /* Code: compiler.err.cant.resolve.location Kind: ERROR Position: 123 (113/131) Source: src\my\package\Hello2.java Message: src\my\package\Hello2.java:5: cannot find symbol */
[Bearbeiten] Using printf
Format your classes with the usage of the printf method is available since Java5 and acts just like you know it from C. In Java you have the additional possibility to pass your own object types to the method and define how instances of these types should be formatted by using the Formattable interface.
Suppose you have an entity called Alfa defined as follows:
public class Alfa implements Formattable { private final String stamp12 = "ABCDEF123456"; // alternate private final String stamp24 = "ABCDEF123456GHIJKL123456"; // default public void formatTo(Formatter formatter, int flags, int width, int precision) { StringBuilder sb = new StringBuilder(); // ... formatter.format(sb.toString()); } }
Within that formatTo method you have to:
- Check flags (# alternate, - left justify and ^ for uppercase)
- Set the precision (cut off length)
- Check locale
- Setup output justification
// 1. check flags (alternate) boolean alternate = (flags & FormattableFlags.ALTERNATE) == FormattableFlags.ALTERNATE; alternate |= (precision >= 0 && precision <= 12); String stamp = (alternate ? stamp12 : stamp24); // 2. set precision (cut off length) if (precision == -1 || stamp.length() <= precision) sb.append(stamp); else sb.append(stamp.substring(0, precision - 1)).append('*'); // 3. check locale if (formatter.locale().equals(Locale.CHINESE)) sb.reverse(); // 4. setup output justification int n = sb.length(); if (n < width) { boolean left = (flags & FormattableFlags.LEFT_JUSTIFY) == FormattableFlags.LEFT_JUSTIFY; for (int i = 0; i < (width - n); i++) { if (left) { sb.append(' '); } else { sb.insert(0, ' '); } } }
The preceding class in use will produce following output when used with printf:
final Alfa alfa = new Alfa(); System.out.printf(">%s<%n", alfa); // >ABCDEF123456GHIJKL123456< System.out.printf(">%#s<%n", alfa); // >ABCDEF123456< System.out.printf(">%.5s<%n", alfa); // >ABCD*< System.out.printf(">%.8s<%n", alfa); // >ABCDEF1*< System.out.printf(">%-25s<%n", alfa); // >ABCDEF123456GHIJKL123456 < System.out.printf(">%15.10s<%n", alfa); // > ABCDEF123*< System.out.printf(Locale.CHINESE, ">%15.10s<%n", alfa); // > *321FEDCBA<
[Bearbeiten] Links
- http://java.sun.com/mailers/techtips/corejava/2007/tt0307.html#1 ... TechTip#1 - Java Compiler API
- http://java.sun.com/mailers/techtips/corejava/2007/tt0507.html#2 ... TechTip#2 - Using printf
- http://java.sun.com/developer/EJTechTips/ ... Enterprise Java Technologies Tech Tips
- http://java.sun.com/developer/JDCTechTips/ ... Core Java Technologies Tech Tips
- http://developers.sun.com/mobility/allttips/ ... Mobility Tech Tips

