Meeting 2

Aus Java Student User Group Austria - Java + JVM in Wien Österreich / Vienna Austria
Wechseln zu: Navigation, Suche

When: Monday, June 16th, 2008 - 19:00

Where: Freihaus HS4

OSGi - The Next Generation Java Service Platform

OSGi Logo

Download the slides (pdf, 1.3MB).
You can also view the slides online.

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.

Content

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!!!
$

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.mf file, extending usual stored data with OSGi specific properties

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

Code Example

Register your service: <source lang="java"> public class MyBundleActivator implements BundleActivator {

 public void start(BundleContext context) {
   DbService service = new MyDbService();
   context.registerService(
   DbService.class.getName(), service);
 }

} </source>

Use a specific service: <source lang="java"> ServiceReference ref = context.getServiceReference(DbService.class.getName()); if (ref != null) {

 DbService service = context.lookup(ref);
 if (service != null) {
   service.callDbService();
 }

} </source>

Links

TechTips #1

Download the slides (pdf, 1.4MB).
You can also view the slides online.

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.

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.

Simple Approach

Following things have to be done:

  1. Create sourcecode (could have been created automatically by a generator)
  2. Retrieve a JavaCompiler instance via the ToolProvider
  3. Invoke its run method
  4. Check the return code (0 for successfull)
  5. 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.

<source lang="java"> 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!");
   }
 }

} </source>


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.

<source lang="java"> // 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(); </source>


If there were some errors, you could process them in the following way: <source lang="java"> // 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

  • /

</source>

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: <source lang="java"> 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());
 }

} </source>

Within that formatTo method you have to:

  1. Check flags (# alternate, - left justify and ^ for uppercase)
  2. Set the precision (cut off length)
  3. Check locale
  4. Setup output justification

<source lang="java"> // 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, ' ');
   }
 }

} </source>

The preceding class in use will produce following output when used with printf: <source lang="java"> 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< </source>

Links