Skip to main content

By clicking Submit, you agree to the developerWorks terms of use.

The first time you sign into developerWorks, a profile is created for you. Select information in your developerWorks profile is displayed to the public, but you may edit the information at any time. Your first name, last name (unless you choose to hide them), and display name will accompany the content that you post.

All information submitted is secure.

  • Close [x]

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerworks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

By clicking Submit, you agree to the developerWorks terms of use.

All information submitted is secure.

  • Close [x]

Developing a Service Management Framework bundle with WebSphere Studio Device Developer

Huang Chang (hchang@cn.ibm.com), Software Engineer, IBM SGL Lab
Huang Chang is a software engineer in IBM Shanghai Globalization Lab (SGL). His expertise includes tools evaluation and best practices for globalization. This article is the result of his technical study in a recent Globalization Interoperability Test (GIT) project using Workplace Client Technology, Micro Edition V5.7.1. You can reach him at hchang@cn.ibm.com

Summary:  This article is an in-depth guide to a better understanding of the Open Services Gateway Initiative (OSGi) programming framework and API with a focus on how to apply them to practical Service Management Framework bundle development.

Date:  26 Jan 2005
Level:  Intermediate
Also available in:   Chinese

Activity:  1897 views
Comments:  

Introduction

Service Management Framework is a key technology in IBM® Workplace Client Technology, Micro Edition V5.7.1, (Workplace Client Technology). The SMF development toolkit ships with the Workplace Client Technology offering to facilitate developing SMF bundles. Unfortunately, there is little documentation or tutorials which address the topic of how to develop SMF bundles in the WebSphere® Studio Device Developer (Device Developer) environment.

This article is intended as an in-depth guide to help you gain a basic understanding of the SMF programming framework and bundle development process. For this purpose, this article will give a step-by-step case study to illustrate how to develop SMF bundle with Device Developer V5.7.1. This case study will go beyond the WebSphere Studio Device Developer InfoCenter general development guide in exploring these key areas of concern:

  • The code architecture of a typical SMF bundle
  • Developing a bundle skeleton
  • Registering a custom service with SMF Runtime
  • Consumption of external services registered to SMF Runtime by other bundles

The article assumes you have a basic knowledge of SMF, with SMF runtime/server management and Device Developer experience.


SMF bundle code architecture

In the Open Service Gateway initiative on which SMF is based, everything is represented as a bundle. For purpose of loosely-coupling and reusability, a typical SMF application is normally designed to have a toy-trick like structure. This structure may have an arbitrary number of bundles. Dependency between two different bundles generally falls into two categories, static sharing or dynamic services. In general, a typical SMF bundle that involves both of these two kinds of interactions can be divided into the following parts:

  • Bundle manifest file

    A descriptor used to declare bundle native features, such as name, version, manufacture information, and the static and dynamic interaction relationship with other bundles.

  • Bundle activator implementation

    Each bundle must implement the OSGi BundleActivator interface so that it can be controlled by the SMF runtime throughout its life cycle. The control events include install, update, start, and stop.

  • Custom service interface

    Besides those OSGi defined services, bundle vendors can develop custom services. To do that, you should define a Java™ interface for each custom service.

  • Custom service implementation

    Classes that implement the methods declared in custom service interfaces.

  • Custom Service Factory implementation

    Invoke Custom Service Factory during runtime to initialize a service object. For each custom service, there should be a corresponding custom service factory class. The custom service factory class should implement the OSGi ServiceFactory interface.

  • Business logics

    Business logics are referred to the remaining blackbox of a bundle other than the components above. They can be Java class files or other resource files.

In Figure 1 below, arrowed lines stand for interactions between SMF Runtime, service consumer bundle, and the service provider bundle.


Figure 1. Constructs of Bundle
Figure 1 diagram. Constructs of Bundle

A case study

Bundle description

In this case study, we will develop a SMF bundle named HttpLog using Device Developer V5.7.1. The HttpLog bundle provides a logging facility for upper-level bundles to record runtime log messages, which can be tracked by visiting a specified HttpServlet.

Step 1. Create a bundle skeleton

The bundle skeleton starts with a Java project, where we can do basic coding work. At first we need to create a Java project named HttpLog in Device Developer.

Modify the project build path setting to include the OSGi framework library osgi.jar and other packages that we will use in the bundle code (servlet.jar in this case).


Figure 2. Java Build Path
Figure 2. Java Build Path

Step 2. Implement interface BundleActivator

In this step, we are going to create the Java class HttpLogBundleActivator, which implements the OSGi BundleActivator interface.

The interface BundleActivator declares two methods: start() and stop(). The start() method is invoked by the SMF runtime upon bundle activating. Therefore, add code to do some bundle specific initialization. The argument BundleContext is a delegation object to the runtime environment, which provides a rich set of operations that enable bundle code to invoke SMF Runtime’s facilities, such as registering custom service and acquiring service references to external services. Record it as a member variable for later use.

//HttpLogBundleActivator.java
public class HttpLogBundleActivator implements BundleActivator {
	…
	BundleContext bc;
	public void start(BundleContext context) throws Exception {
		bc=context;
		//to add initialization code here
		
	}
	public void stop(BundleContext context) throws Exception {
				
	}
	…
}

Step 3. Register custom service

In this step, we are going to develop one custom service named HttpLogService to implement the logging facility. There are three Java files to be created: HttpLogService.java, HttpLogServiceImpl.java, and HttpLogServiceFacotry.java.

Developer should provide an interface class and implementation class for each custom service. In this case, the service interface HttpLogService only declares one method called log(), which adds the passin message to a static message queue messageArray every time log() is invoked.

//HttpLogService.java
package httplog;

public interface HttpLogService {
	void log(String message);
}

//HttpLogServiceImpl.java
package httplog;
public class HttpLogServiceImpl implements HttpLogService{
	static public List messageArray = new ArrayList();
	
	public void log(String message) {
		HttpLogServiceImpl.messageArray.add(message);
	}
	
}

Registration of custom services normally occurs when its hosting bundle is activated. Add the following code to the start() method of the class HttpLogBundleActivator.

//HttpLogBundleActivator.java
public class HttpLogBundleActivator implements BundleActivator {	
static final String httpLogServiceName = HttpLogService.class.getName();
	…
public void start(BundleContext context) throws Exception {
		registerHttpLogService();
	}	
private void registerHttpLogService(){
		HttpLogServiceFactory sf = new HttpLogServiceFactory();
		ServiceRegistration sr=bc.registerService(httpLogServiceName,sf,null);
	}
}

While invoking registerService(), a bundle should provide the declared custom service name, a service object that implements the OSGi ServiceFactory interface and a Dictionary object that include the properties for this service. Each ServiceFactory subclass should implement two methods: getService() and ungetService(). In our case, HttpLogService is the service to be registered and sf is of the type HttpLogServiceFactory that can generate HttpLogServiceImpl instances. For simplicity, there are no properties set for this service. The code for HttpLogServiceFactory is shown below.

//HttpLogServiceFactory.java
package httplog;
import org.osgi.framework.Bundle;
import org.osgi.framework.ServiceFactory;
import org.osgi.framework.ServiceRegistration;

public class HttpLogServiceFactory implements ServiceFactory{
…
	public Object getService(Bundle bun, ServiceRegistration sr) {
		return new HttpLogServiceImpl();
	}

	public void ungetService(Bundle bun, ServiceRegistration sr, Object obj) {
	}
}

Step 4. Consume external service

The external service consumed by the HttpLog Bundle is HttpService. Users can track the log records of HttpLog bundle by visiting an HttpServlet resided in localhost. To implement this function, HttpLog Bundle should register a servlet object with the HttpService bundle through the interface of HttpService. This task is performed when HttpLog bundle is started. Supplement the HttpLogBundleActivator class with the attachToHttp() method.

public class HttpLogBundleActivator implements BundleActivator {
	…
	static final String servletURI ="/httplog";
	private void initialize(){
		
		//Import HttpService
		attachToHttp();
		//register HttpLogService
		registerHttpLogService();

	}
	private void attachToHttp(){
		httpContext = new HttpContext(){

		   public boolean handleSecurity(HttpServletRequest request,
								HttpServletResponse response)
		   {
			   return true;
		   }

		   public URL getResource(final String name)
		   {
			   return (URL) AccessController.doPrivileged(new PrivilegedAction()
			   {
				   public Object run()
				   {
					   String resource = name;
					   if (resource.charAt(0) != '/')
						   resource = "/".concat(resource); //$NON-NLS-1$
					   return getClass().getResource(resource);
				   }
			   });
		   }

		   public String getMimeType(String name)
		   {
			   return null;
		   }
			
		};

		ServiceReference httpSR = bc.getServiceReference(HttpService.class.getName());
		HttpService http = (HttpService)bc.getService(httpSR);
	
		try {
			http.registerServlet(servletURI, new HttpLogServlet(), null, httpContext);
		
		} catch (ServletException e) {
			e.printStackTrace();
		} catch (NamespaceException e) {
			e.printStackTrace();
		}
	}
	…
}

//HttpLogServlet.java
package httplog;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.ServletException;

public class HttpLogServlet extends HttpServlet{

	protected void doGet(HttpServletRequest req, HttpServletResponse res)
		 throws ServletException, IOException
	 {
		 res.setContentType("text/html; charset=UTF-8");
		 PrintWriter out = res.getWriter();

		 out.print("<html><head><title>" + "Http Log Display" + "</title></head>"); 
		 out.print("<body text=\"#000000\" bgcolor=\"#C0C0C0\" 
			 link=\"#0000EE\" vlink=\"#551A8B\" alink=\"#FF0000\">");		
		 List msgArray = HttpLogServiceImpl.messageArray;
		 
		 int len=msgArray.size();
		 for (int i=0;i<len;i++){
		 	String msg= (String)msgArray.get(i);
		 	out.print(msg);
		 }
		 out.println("</body></html>"); 
	 }

}

The code above registers a custom HttpServlet object to the service HttpService during bundle initialization time. Before consuming an external service, we need to locate its instance from SMF runtime. This is done by sequentially invoking two methods:BundleContext: getServiceReference() and getService().

public ServiceReference getServiceReference(java.lang.String clazz) locates a service instance from the service registry according to the service name clazz and packages this instance in type of ServiceRefence. Note that getServiceReference() only returns one service reference to the declared service interface. Actually, there may be multiple implementations registered to one service interface at a time. To acquire all service implementations to that service, use getServiceRefrences() instead to get an array of ServiceReference objects.

public java.lang.Object getService(ServiceReference reference) returns a service implementation object. Use typecast to convert the returned object to the desired service interface type.

Step 5. Migrate to bundle format

After completing the steps above, we are now ready to package the HttpLog project into a real bundle. Prior to transformation, we need to save all modified files and compile all Java source files into classes.

Then, open File->New->SMF and choose to create a Bundle Folder. Click Next.


Figure 3. Creating a bundle folder
Figure 3 window. Creating a bundle folder

Choose HttpLog from available Java projects as the target bundle folder. Deselect generation options, as they are not necessary. Click Finish.


Figure 4. Choosing the bundle folder container
Figure 4. Choosing the bundle folder container

A folder named metainf containing a file MANIFEST.MF will be created in the project. MANIFEST.MF describes bundle metrics and its dependency with other bundles. Composing MANIFEST.MF needs to comply with the rules defined in OSGi specification. Device Developer provides a MANIFEST editor to help with composing.


Figure 5. The bundle developer screen
Figure 5. The bundle developer screen

Several fields are mandatory to fill in in our case.

In Bundle-Name, fill in HttpLog.

In Bundle-Version, fill in 1.0.0.

In Bundle-Activator, fill in httplog.HttpLogBundleActivator

In Import Services, fill in org.osgi.service.HttpService, as this is the only service HttpLog will visit in runtime.

In Import Packages, fill in with the following packages: javax.servle, javax.servlet.http, org.osgi.framework, org.osgi.service.http. Although SMF runtime uses one JVM, it will assign different classloaders for different bundles to avoid unauthorized package sharing. Therefore, bundle should declare in the MANIFEST file which packages it will reference to maintain its own classpath.

In Export Packages, fill in with httplog.

In Export Services, fill in httplog.HttpLogService.


Figure 6. The bundle developer screen
Figure 6. The bundle developer screen

Save the MANIFEST.MF file. The bundle is now completely ready for deploy.

Also, for reference by other bundles in later use, export the HttpLog project as a jar package httplog.jar. To perform this task, right click HttpLog project in the Project explorer view and choose Export.

Step 6. Deploy Bundle to SMF Server

Create a SMF server and start it.


Figure 7. Run window
Figure 7. Run window

In the Project Explorer, right click HttpLog project and choose SMF->Submit Bundle….


Figure 8. Menu dropdown
Figure 8. Menu dropdown

Figure 9. Target Submission window
Figure 9. Target Submission window

In the Target Submission dialog, choose the SMF server just created, labeled Admin@localhost:8080/smf. Select Submit Jar and click Finish.

Open the SMF perspective, in the SMF Bundle Servers view, the HttpLog has been successfully submitted to the SMF server.


Figure 10.
Figure 10 showing the HttpLog displayed

Step 7. Develop testing bundle

In this step, we are going to write a bundle named HttpLogTester to invoke HttpLogService for testing purpose. This is necessary as the Http log can display content only after the HttpLogService is invoked.

This bundle is so simple that we only need to repeat step 1 and 2 to create a similar bundle skeleton. Make sure to include httplog.jar in the project build path. Implement the start() method of HttpLogTesterBundleActivator as shown below.

//HttpLogTesterBundleActivator.java
class HttpLogTesterBundleActivator implements BundleContext{
…
	public void start(BundleContext context) throws Exception {
		bc=context;
		ServiceReference httpLogSR=bc.getServiceReference(httpLogServiceName);
		HttpLogService httpLog =(HttpLogService)bc.getService(httpLogSR);
		httpLog.log("Hello world!");
	}
…
}

Repeat step 2-6 to submit the HttpLogTester to the SMF server.

Step 8. Test HttpLog in SMF runtime

We need to download and start the HttpLogTester in a SMF runtime environment. Create a SMF Runtime and start it in Device Developer. Leave all settings as default.


Figure 11. SMF Bundle Server view
Figure 11. SMF Bundle Server view

Right click HttpLogTester in the SMF Bundle Server view and choose Install. The HttpLogTester Bundle along with its supporting bundles, such as HttpLog and HttpService, will be downloaded and started automatically.


Figure 12. Menu display
Figure 12. Menu display

To track the log message, open a browser window and type http://localhost/httplog. We can see one log record as shown below.


Figure 13. Log display
Figure 13 screenshot. Log display

Conclusion

Understanding the programming framework of OSGi is the basis for designing and implementing SMF-based applications. This article has introduced the major OSGi API and described how to develop a SMF bundle in Device Developer V5.7.1 from scratch.


Acknowledgements

The author would like to thank all team members involved in the GPIMM project at IBM Shanghai Globalization Lab for their help in developing this article.



Download

NameSizeDownload method
0501huangsample.zip6 KBHTTP

Information about download methods


Resources

About the author

Huang Chang is a software engineer in IBM Shanghai Globalization Lab (SGL). His expertise includes tools evaluation and best practices for globalization. This article is the result of his technical study in a recent Globalization Interoperability Test (GIT) project using Workplace Client Technology, Micro Edition V5.7.1. You can reach him at hchang@cn.ibm.com

Report abuse help

Report abuse

Thank you. This entry has been flagged for moderator attention.


Report abuse help

Report abuse

Report abuse submission failed. Please try again later.


developerWorks: Sign in


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Select information in your developerWorks profile is displayed to the public, but you may edit the information at any time. Your first name, last name (unless you choose to hide them), and display name will accompany the content that you post.

Choose your display name

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


Rate this article

Comments

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=WebSphere, Java technology
ArticleID=33352
ArticleTitle=Developing a Service Management Framework bundle with WebSphere Studio Device Developer
publish-date=01262005
author1-email=hchang@cn.ibm.com
author1-email-cc=

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

For articles in technology zones (such as Java technology, Linux, Open source, XML), Popular tags shows the top tags for all technology zones. For articles in product zones (such as Info Mgmt, Rational, WebSphere), Popular tags shows the top tags for just that product zone.

For articles in technology zones (such as Java technology, Linux, Open source, XML), My tags shows your tags for all technology zones. For articles in product zones (such as Info Mgmt, Rational, WebSphere), My tags shows your tags for just that product zone.

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Try IBM PureSystems. No charge.

Special offers