My favorites | Sign in
Project Home Downloads Wiki Issues Source
Search
for
iPOJOExampleApplications  

Featured
Updated Feb 16, 2009 by clement....@gmail.com

Introduction

ModuleFusion currently contains 5 example applications using iPOJO. Each of these examples shows how to use iPOJO with Module fusion technical services such as JPA and web applications. The example build is based on Maven.

Download: http://modulefusion.googlecode.com/files/modulefusion-iPOJO_examples-1.1.0.zip and http://modulefusion.googlecode.com/files/modulefusion-featurepack-iPOJO-1.1.0.zip

To build the example, launch the following command from where you unpack the example: mvn clean install

iPOJO Simple Example: org.modulefusion.example.ipojo.simple

This bundle shows how to use the iPOJO framework within the OSGi framework. The following code snippets shows an iPOJO Component using an OSGi service:

@Component
public class UsingAService {
    
    @Requires
    private PackageAdmin packageAdmin;
	
	public UsingAService() {
		ExportedPackage[] packages = packageAdmin.getExportedPackages((Bundle) null);
		System.out.println("------------" +
				"----------");
		System.out.println("Simple iPOJO Examples");
		System.out.println("----------------------");
		System.out.println("Number of exported packages in the framework: " + packages.length);
		System.out.println("----------------------");
	}
	
}

The @Component annotation says that you’re defining an iPOJO component. The used service is the PackageAdmin (provided by the OSGi framework). The service in injected by iPOJO in the packageAdmin field (thanks to the @Requires annotation).

Once declared, you need to say to iPOJO to create an instance of your component. This is done in the metadata.xml file:

<ipojo>
	<instance component="org.modulefusion.example.ipojo.simple.UsingAService"/>
</ipojo>

To register a service, just use the @Provides annotation such as in:

@Component
@Provides
public class ExportedAsAService implements Runnable {
	public void run() {
		System.out.println("Running...");
	}
}

The component type will exposed the Runnable interface as a service. You don’t need to specify the exposed interface, iPOJO introspects the class to find implemented interfaces. As for the previous example, you need to declare an instance of your component:

<ipojo>
	<instance component="org.modulefusion.example.ipojo.simple.ExportedAsAService"/>
	<instance component="org.modulefusion.example.ipojo.simple.UsingAService"/>
</ipojo>

Hello World Example: org.modulefusion.example.servlet.ipojo.helloworld

This bundle creates a simple "Hello World" servlet and exposes it at http://server:port/ALIAS. The servlet code is:

@Component
@Provides
public class HelloWorldServlet extends HttpServlet {
    
    @ServiceProperty
    private String alias; // In the instance configuration
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException,
			IOException {
		ServletOutputStream out = resp.getOutputStream();
		out.println("Hello World!");
		out.close();
	}

}

The @Component annotation says that you’re creating an iPOJO component. This component provides a service. iPOJO will introspect the class to find wich service you provides. In this case, it will found Servlet (implemented by HttpServlet). The @ServiceProperty indicated a property published with the Servlet service. The service property value is contained in the instance configuration. So, several instance of the same servlet can be created and registered on different alias. Of course, you can register any Servlet you like and this also could be e.g. the Struts or "insert a random web framework here" servlet. The, you need to say to iPOJO to create an instance of your component. The instance is declared in the metadata.xml file:

<ipojo>
	<instance component="org.modulefusion.example.servlet.ipojo.helloworld.HelloWorldServlet">
		<property name="alias" value="/helloworld"/>
	</instance>
</ipojo>

Notice the alias property indicating where is published the servlet. So, this servlet will be accessible on http://server:port/helloworld

JPA Introduction

When building Java enterprise applications, programmers normally use an O/R mapper to persist their objects in the database and probably the one mostly used is Hibernate. Hibernate provides a JPA frontend to its API so that code is not coupled to Hibernate's proprietary API.

OSGi introduces a new deployment format (bundles) and brings a new application model with services and the dynamic life cycle of bundles. Unfortunately, it is not always straightforward to map JPA elements to the OSGi model. E.g. entity classes can be split accross several bundles. Therefore, ModuleFusion contains the necessary glue code to make the use of Hibernate JPA as simple as possible. In ModuleFusion, each bundle containing entity classes, simply lists those classes in a text file inside the bundle's jar file. ModuleFusion will read these files and the database configuration (section below), and combine them to provide a valid javax.persistence.EntityManager. This EntityManager is then available in the OSGi service registry. Important: The registered service is a proxy that delegates to a thread local EntityManager. Therefore, each thread will automatically have its own instance. Additionally, a javax.persistence.EntityManagerFactory gets registered. Clients can use this service directly if they need more control over the creation of the entity managers. Database Connection Configuration

The database and Hibernate configuration can be changed in the file "load/configs/org.modulefusion.hibernate.jpaservicehibernate.cfg":

hibernate.connection.driver_class=org.hsqldb.jdbcDriver hibernate.connection.url=jdbc:hsqldb:file:data/database hibernate.connection.username=sa hibernate.connection.password= hibernate.dialect=org.hibernate.dialect.HSQLDialect hibernate.current_session_context_class=thread hibernate.cache.provider_class=org.hibernate.cache.NoCacheProvider hibernate.show_sql=false hibernate.hbm2ddl.auto=update

The HSQLDB RDBMS is included in the ModuleFusion distribution. The default JPA configuration (listing above) of ModuleFusion uses HSQLDB in the embedded mode. You don't need to change the configuration to use JPA applications in ModuleFusion. The default one will do just fine. Later, you still can change to e.g. MySQL, PostgreSQL, etc. JPA Examples

ModuleFusion contains two bundles showing how to use JPA in iPOJO/OSGi:

  • The first bundle contains the entity Person and the PersonService service providing the CRUD operations (create, read, update, delete).
  • The second bundle simply uses the PersonService and does not depend on JPA directly.

JPA Example 1/2: org.modulefusion.example.jpa.personprovider

This bundle provides the entity class Person:

@Entity
public class Person implements Serializable {
  
    @Id
    @GeneratedValue(strategy = GenerationType.TABLE)
    private Long id;

    private String firstname;
    private String lastname;

    // getter/setter
    // for firstname and lastname
    // ...
}

As described above, the bundle has to inform ModuleFusion about this entity class. This is done by listing the class in the file OSGI-INF/jpa/classes. Each line consists of the fully-qualified class name (package name + class name):

org.modulefusion.example.jpa.personprovider.Person

This file and the configuration explained above is enough for ModuleFusion to create and register the entity manager. This bundle now uses the entity manager to implement a person service other bundles can use. The bundle uses iPOJO to reference the service. Within the PersonService class, the entity manager is injected in a field and can be used just like in a non-OSGi environment:

@Component
@Provides
public class PersonServiceImpl implements PersonService {
    final Logger logger = LoggerFactory.getLogger(PersonServiceImpl.class);
    @Requires
    private EntityManager entityManager; 
    public Person savePerson(Person person) {
        entityManager.getTransaction().begin();
        logger.info("save Person");
        Person newP = entityManager.merge(person);
        entityManager.getTransaction().commit();
        return newP;
    }
  //…
}

Again, this entity manager is a proxy delegating to a thread local instance and is therefore thread save. The next step is to declare an instance of our component type:

<ipojo >
	<instance component="org.modulefusion.example.jpa.personprovider.impl.PersonServiceImpl"/>
</ipojo>

JPA Example 2/2: org.modulefusion.example.jpa.personclient

The person client bundle simply uses the person service that was registered by the first bundle. It does not use the JPA API directly and is not specific to OSGi, etc. Please check the source code for more information.


Sign in to add a comment
Powered by Google Project Hosting