JXSE and Equinox Tutorial, Part 2
http://java.dzone.com/articles/jxse-and-equinox-tutorial-part-0
——————————————————————————————————————————————————————
Abstract
In the first post of this series, we covered the quickest way to get JXSE 2.7x working in Equinox and, with some considerations, probably other OSGI frameworks as well. The approach aimed to get the same functionality as you would get by using the jar file in a regular JAVA setting, but as I demonstrated, Equinox does have the benefit of allowing multiple JXSE instances to run simultaneously, which is a great benefit when developing JXSE applications.
In this second tutorial, we will cover some ways of improving the functionality by severing the dependency on the 4.2x version of Jetty (which has just released it's 9.0 version!) and we will introduce some basic tools to visualize the properties and functions of JXSE. This will improve the development cycle of JXSE applications even more.
NOTE: This tutorial will use a modified JXSE jar, which currently has only been sparsely tested. If you want to develop in a fail-safe environment, I would recommend that you stick to approach of adding the 2.7x and org.mortbay.jetty 4.2x jars to your plugin structure. If you are more adventurous or, even better, want to help to improve the tooling, then this post is for you! |
Updating Jetty
The approach we covered earlier involves including a Jetty server for every JXSE bundle you want to deploy. The Jetty server is used for HTTP tunneling and basically starts a simple HTTP server with one servlet. If we want to optimize this approach when running multiple JXSE bundle projects, it would stand to reason that we run one server instance, which registers multiple servlets, which is basically the way that Jetty runs in most OSGI environments. Ideally we would utilize the http service for Equinox to register our servlets, but because every JXSE bundle needs to run on a different network port, registration of the servlets is a bit more involved.
The implication of breaking the dependency on the org.mortbay.jetty 4.2x jar (i.e. removing the jar-file from the lib directory and putting it in a separate bundle) is that the JXSE code has to be changed as well, and so we might just as well create a JXSE 2.7x bundle! This bundle will be a client for a declarative service that is offered by the Jetty plugin, and which allows registration of the specific servlets that JXSE uses. The necessary bundles can be found in the extended.zip, which offers functionality that extends the base porting of JXSE applications to Equinox. can be included in your target definition:
Download the zip-file and unpack it in the same target root as the other target plugins (e.g. C:\Projects\Target\Extended)
In the Eclipse IDE, select Window → Preferences → Plug-in Development → Target Platform, and select the active target we assembled in the previous posting
Press 'Edit' and 'Add' a new 'Directory' by selecting the appropriate controls. Browse to the folder where the unzipped files are located and add the folder to your target definition. Press 'Finish' to complete the Wizard
TIP: Extending a target definition with new directories can be a RSI-ridden chore. Luckily the 'Location' field stores previous entries, and so if you select one of these before pressing the 'Browse' button, you may win quite a few mouse-clicks |
The target definition has been extended with a number of bundles, three of which are important for this part of the tutorial:
net.jxse (2.7.x)
org.mortbay.jetty (4.2.x)
org.eclipse.jetty.jxse.bridge (1.x.y)
I try to follow the convention to use the version of a jar-file when
it is converted to OSGI, and from this it becomes evident that the first
two bundles are basically the original jar-files that were deployed in
part one of the tutorial. The only difference is that these bundles
share their dependencies through a declarative service.
NOTE: Internally, the necessary modifications |
With this, we can now modify the two JXSE Plugin project we developed
in the previous post to work with these bundles. We will also use a
different example from the book Practical JXTA II to make things more
interesting. We will try to connect Edge_Anna with Rendezvous_Jack.
Modify the two JXSE 2.7x Bundle Projects you made in the previous tutorial :
Remove the lib folder and the references to
lib/jxse-2.7.jar and
lib/org.mortbay.jetty.jar in the bundle classpath settings.
Solve the compiler errors by
importing
the necessary bundle dependencies in the 'imported packages' tab of the Manifest editor.
Include the
org.mortbay.jetty
bundle (
not
the bridge!)
The resulting Manifest.MF file should look something like this:
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Practical JXTA II: Anna the Edge Peer
Bundle-SymbolicName: net.practical.jxta.decoupled.anna
Bundle-Version: 1.0.0.v20130816
Bundle-Activator: net.practical.jxta.decoupled.anna.Activator
Bundle-Vendor: MyCompany
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
Bundle-ActivationPolicy: lazy
Bundle-ClassPath: .
Import-Package: net.jxta,
net.jxta.document,
net.jxta.endpoint,
net.jxta.exception,
net.jxta.id,
net.jxta.peer,
net.jxta.peergroup,
net.jxta.platform,
net.jxta.rendezvous,
org.osgi.framework;version="1.7.0"
We can now copy Edge_Anna.java and Rendezvous_Jack.javafrom the folder B_Exploring_Connectivity_Issuesfrom the examples that are covered by Practical JXTA II as replacement for the previous examples. Last we need to make a slight adjustment to the Activators in order to ensure concurrency:
import java.util.concurrent.Executors;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext; public class Activator implements BundleActivator, Runnable { private static Activator activator;
private ExecutorService executor; static Activator getDefault() {
return activator;
} public void start(BundleContext bundleContext) throws Exception {
activator = this;
executor = Executors.newSingleThreadExecutor();
executor.execute(this);
} public void stop(BundleContext bundleContext) throws Exception {
if( !executor.isShutdown() && !executor.isTerminated())
executor.shutdown();
Activator.context = null;
} @Override
public void run() {
Edge_Anna.main(null);
}
}
When the bundles are added to your run configuration, you will see that the various pop-up messages are spawned as the two bundles are activated. But hidden deep in the log messages, you will also find that a -if all went well:
INFO: Jetty Server for JXTA found!
And, a bit later:
INFO: Line 679 net.jxta.impl.peergroup.GenericPeerGroup.loadModule()
Loaded privileged module : Reference Implementation of the HTTP Message Transport
(net.jxta.impl.endpoint.servlethttp.ServletHttpTransport)
As Rendezvous_Jack is starting up HTTP transport. If
this doesn't seem to happen, then the most likely reason is that the
org.mortbay.jettybundle has not started (type 'ss' in the Eclipse
console for the status of the bundles). You can also check if the
declarative services that forge the connection between the two bundles
have started correctly by typing in the OSGI console:
'attendees': this should return (at least)
osgi> attendees
net.jxse.petitioner.ServerStarterPetitioner
org.mortbay.jetty.provider.ServerProvider'matched': this should return:
osgi> matched
net.jxse.petitioner.ServerStarterPetitioner is matched with:
org.mortbay.jetty.provider.ServerProvider
The bundles use a light-weight wrapper around OSGI's standard declarative services called a secure broker (org.eclipselabs.osgi.ds.broker)
to make the connection. This bundle is also provided by the target
addition that was downloaded .One of the added functions are three
console commands to check the connections (the third one is 'waiting').
The first command lists the (broker) services that are registered, the
second one which services are matched with one another. Above you can
see that the bunle net.jxseis connected with the bundle
org.mortbay.jetty. If these commands are not recognized, it means that
the broker plugin is not activated yet.
Integration with Jetty 6 to Jetty 8 (inclusive)
If you are a bit more adventurous, you may want to try the Jetty Bridge
that has also been included in the additions to the target. This bundle
requires the org.eclipse.jetty bundles from 6.0.0 to 8.9.9, which are
often shipped with certain Eclipse distributions. Simply deactivate the
org.mortbay.jettybundle and activate org.eclipse.jetty.jxse.bridge. (and
Jetty, of course). If all is well, you should see the same behavior as
previously, but now more recent versions of Jetty can be used.
NOTE: Please consider that I have only tested |
Enabling JXSE Tools for Eclipse
The previous examples probably have made clear that pop-up messages
and log messages are not going to be very helpful when developing
multiple JXSE Bundle projects simultaneously. Although this is work in
progress (and probably will always be so), a start has been made to
develop JXSE tools that can be used in an Eclipse IDE. I hope to add
more posts to this tutorial as functionality becomes available, but here
we can begin by demonstrating what needs to be done at minimum to make
your JXSE Bundle Projects visible to the tools.
In order to enable the Eclipse tooling, a new target is needed which
replaces equinox with an Eclipse version (which, of course, includes an
Equinox version). As we have ample experience with target definition
management by now, I will just list the three directories that are
needed to get things up and running
An Eclipse version. You can opt to copy the Kepler installation to the target environment (recommended), or use the
${eclipse-home} option as location (quickest)the core JXSE bundles that were downloaded for the previous post
The extended JXSE bundles that were downloaded for the first part of this tutorial
Next we need to create a new Eclipse application ( File → New →
Plugin Project). Select the option that the 'plug-in is targeted to run
with' an Eclipse version, and (in the second tab) that we will develop a
Rich Client application. Clicking 'Finish' will generate a bare-bones
Eclipse RCP. We will include one perspective to the RCP by hardcoding it
in the ApplicationWorkbenchAdvisor:
package org.{my-company}.jxse.ui; import org.eclipse.ui.application.IWorkbenchWindowConfigurer;
import org.eclipse.ui.application.WorkbenchAdvisor;
import org.eclipse.ui.application.WorkbenchWindowAdvisor; public class ApplicationWorkbenchAdvisor extends WorkbenchAdvisor { private static final String PERSPECTIVE_ID = "org.eclipse.jxse.perspective"; @Override
public WorkbenchWindowAdvisor createWorkbenchWindowAdvisor(
IWorkbenchWindowConfigurer configurer) {
return new ApplicationWorkbenchWindowAdvisor(configurer);
} @Override
public String getInitialWindowPerspectiveId() {
return PERSPECTIVE_ID;
}
}
Next, remove the Tools.java file from the JXSE bundles and rename the faulty imports in the JXSE bundles to 'net.osgi.jxse.compatibility.Tools'. We also need to make some changes to the code from Practical JXTA II:
Make the class that run the examples extend net.osgi.jxse.compatibility.AbstractExampleContext
Include addModule( MyNetworkManager) after it has been instantiated;
NOTE: The static method addModule registers JXTA modules |
Last, a new launch configuration is needed for an 'Eclipse
Application'. Select the 'Run an Application' option in the first tab,
and select the application you just created. The workspace plugins that
are needed should include the application, and the two JXSE Bundle
projects 'Jack the Rendezvous' and 'Anna the Edge'. Add the 'Required
Bundles', and ensure that the following bundles are included:
org.eclipse.equinox.console
The three org.apache.felix.gogobundles
org.eclipselabs.osgi.ds.broker
org.mortbay.jetty or org.eclipse.jetty.jxse.bridge
net.osgi.jxse.compatibility
org.eclipselabs.jxse.ui
Validate the configuration and 'add Required Bundles' if necessary.
If no problems have been detected, you can launch the application. If
all went well, you should see the two JXSE bundles start up as they did
previously, but instead of the somewhat outdated pop-up boxes from JAVA
Swing, the more flashy alternatives from Eclipse's SWT packages should
pop up. Also a basic Eclipse application should become visible with some
views which are currently empty. The more observant developers will
probably spot the
WARNING:
This bundle is not a valid JXSE Bundle. A JXSE-INF directory is required.
Ignore this warning for now. It will become more important in the next part of this series.
We are almost there! Stop the run configuration, and make the following modifications to the JXSE Bundle projects:
Create a new component definition (File → New→ …) and select as the parent folder <your.bundle.name>/OSGI-INF, and name jxse.xml (or another name of your choosing). This will create a folder OSGI-INFunder the root of your JXSE bundles and add the file.
When the component editor opens, fill in the details as follows:
1.
<?
xml
version
=
"1.0"
encoding
=
"UTF-8"
?>
2.
<
scr:component
xmlns:scr
=
"http://www.osgi.org/xmlns/scr/v1.1.0"
name="<your.bundle.name>.service">
3.
<
implementation
class="<your.bundle.name>.service.OsgiComponent"/>
4.
<
reference
bind
=
"setAttendeeService"
cardinality
=
"1..1"
interface
=
"org.eclipselabs.osgi.ds.broker.IAttendeeService"
name
=
"IAttendeeService"
policy
=
"static"
unbind
=
"unsetAttendeeService"
/>
5.
</
scr:component
>
After the component definition is completed, the required OsgiComponent.java needs to be present in the designated package. This class should look as follows:
1.
<?xml version=
"1.0"
encoding=
"UTF-8"
?>
2.
<scr:component xmlns:scr=
"http://www.osgi.org/xmlns/scr/v1.1.0"
name=
"<your.bundle.name>.service"
>
3.
<implementation
class
=
"<your.bundle.name>.service.OsgiComponent"
/>
4.
<reference bind=
"setAttendeeService"
cardinality=
"1..1"
interface
=
"org.eclipselabs.osgi.ds.broker.IAttendeeService"
name=
"IAttendeeService"
policy=
"static"
unbind=
"unsetAttendeeService"
/>
5.
</scr:component>
Include the following line in the Manifest-MF file:
Service-Component: OSGI-INF/jxse.xml
- The OsgiComponent is very simple:
01.
package
<your.bundle.name>;
02.
03.
import
net.osgi.jxse.service.core.JxseDSComponent;
04.
import
<your.bundle.name>.Activator;
05.
06.
public
class
OsgiComponent
extends
JxseDSComponent {
07.
08.
public
OsgiComponent() {
09.
super
( Activator.getDefault());
10.
}
11.
}
Modify the Activator as follows:
01. package <your.bundle.name>; 02. 03. import org.osgi.framework.BundleActivator; 04. import org.osgi.framework.BundleContext; 05. 06. public class Activator extends AbstractJxseBundleActivator{ 07. 08. private static Activator activator; 09. 10. static Activator getDefault() { 11. return activator; 12. } 13. 14. public void start(BundleContext bundleContext) throws Exception { 15. activator = this ; 16. } 17. 18. public void stop(BundleContext bundleContext) throws Exception { 19. activator = null ; 20. } 21. 22. @Override 23. public IJxseServiceContext<NetworkManager> createContext(){ 24. return new Edge_Anna(); 25. } 26. } |
As you can see, the Activator has become much simpler, as the
superclass it derives from does most of the work. All that needs to be
done is to tell the activator which IJxseServiceContextis required, and
these rest is taken care of. The OsgiComponentextracts the context from
the Activator and offers it as a declarative service.
If the changes compile without problems, you can launch the
application, and if all went well, you should now see both JXSE bundles
become visible in the navigator at the left-hand side of the GUI.
Clicking these should show you the NetworkManager,
NetworkConfiguratorand the NetPeerGroup, while their properties are
displayed in the properties editor.
NOTE: Currently not |
Securing your JXSE Bundle
When deploying your bundle in a production environment, you have to
consider that the declarative service opens up means for 'rogue bundles'
to listen to the creation and deployment of your JXSE bundle. As this
poses a security risk, it is advised to disable the declarative service
before deployment in real-world settings. You can either remove the
Service-Component entry in the manifest file in order to achieve this.
In the next tutorial I will cover a different way of securing the
declarative service.
Conclusion
This tutorial has demonstrated some improvements on the results of the previous posting,
and has opened up a way to view the content of the JXSE Bundles. So
far, the main focus has been to modify existing code in order to get it
working in Eclipse / Equinox. The next post will concentrate on building
a JXSE bundle from scratch, and mixed-method approaches.
JXSE and Equinox Tutorial, Part 2的更多相关文章
- JXSE and Equinox Tutorial, Part 1
http://java.dzone.com/articles/jxse-and-equinox-tutorial-part —————————————————————————————————————— ...
- 基于Equinox构建OSGi项目
几种OSGi框架 Several independently implemented OSGi frameworks exist today, including four that are avai ...
- [翻译+山寨]Hangfire Highlighter Tutorial
前言 Hangfire是一个开源且商业免费使用的工具函数库.可以让你非常容易地在ASP.NET应用(也可以不在ASP.NET应用)中执行多种类型的后台任务,而无需自行定制开发和管理基于Windows ...
- Django 1.7 Tutorial 学习笔记
官方教程在这里 : Here 写在前面的废话:)) 以前学习新东西,第一想到的是找本入门教程,按照书上做一遍.现在看了各种网上的入门教程后,我觉得还是看官方Tutorial靠谱.书的弊端一说一大推 本 ...
- thrift 服务端linux C ++ 与客户端 windows python 环境配置(thrift 自带tutorial为例)
关于Thrift文档化的确是做的不好.摸索了很久才终于把跨linux与windows跨C++与python语言的配置成功完成.以下是步骤: 1) Linux下环境配置 ...
- Hive Tutorial(上)(Hive 入门指导)
用户指导 Hive 指导 Hive指导 概念 Hive是什么 Hive不是什么 获得和开始 数据单元 类型系统 内置操作符和方法 语言性能 用法和例子(在<下>里面) 概念 Hive是什么 ...
- Home / Python MySQL Tutorial / Calling MySQL Stored Procedures in Python Calling MySQL Stored Procedures in Python
f you are not familiar with MySQL stored procedures or want to review it as a refresher, you can fol ...
- Using FreeMarker templates (FTL)- Tutorial
Lars Vogel, (c) 2012, 2016 vogella GmbHVersion 1.4,06.10.2016 Table of Contents 1. Introduction to F ...
- Oracle Forms 10g Tutorial Ebook Download - Oracle Forms Blog
A step by step tutorial for Oracle Forms 10g development. This guide is helpful for freshers in Orac ...
随机推荐
- Tomcat遇到”Error listenerStart”或”Error filterStart”问题且无详细日志时的log配置.
昨天部署web应用到Tomcat之后,无法成功启动,并且控制台没有详细的错误信息,顶多就两行提示信息,例如:严重: Error listenerStart严重: Context [/lizongbo] ...
- linux 多处理器概念
Linux 提出了 Multi-Processing 的概念,它的调度器可以将操作系统的线程均分到各个核(或硬件线程)上去执行,以此达到并行计算的目的,从而也可以极大地提高系统的性能. 实现计数器 1 ...
- win7防火墙开启ping
默认情况下,Windows7出于安全考虑是不允许外部主机对其进行Ping测试的. 但在局域网环境中,Ping是测试网络情况的常用手段,如何允许 Windows7的ping测试回显呢? 打开: 控制面板 ...
- 51nod1052 最大M子段和
dp优化我总是不太熟练.这一次首先我写了O(n4)->O(n3)->O(n2).一步步的优化过来.yyl好像用的是单调队列优化dp我看不懂他的代码... O(n4) #include< ...
- Python [Leetcode 344]Reverse String
题目描述: Write a function that takes a string as input and returns the string reversed. Example:Given s ...
- PHP实现站点pv,uv统计(三)
数据分析脚本如下: //error_reporting(0);date_default_timezone_set("PRC");$environment = get_cfg_var ...
- is_file和file_exists效率比较
目前在弄文件缓存的时候用到了判定文件存在与否,is_file()还是file_exists()呢?is_file和file_exists两者效率比较起来,谁的运行速度更快呢?还是做个测试吧: 1 2 ...
- 搭建XMPP协议,实现自主推送消息到手机
关于服务器端向Android客户端的推送,主要有三种方式: 1.客户端定时去服务端取或者保持一个长Socket,从本质讲这个不叫推送,这是去服务端拽数据.但是实现简单,主要缺点:耗电等 2.Googl ...
- duilib让不同的容器使用不同的滚动条样式
装载请说明原出处,谢谢~~:http://blog.csdn.net/zhuhongshu/article/details/42240569 以前在给一个容器设置横纵向的滚动条时,一直是通过设置xml ...
- MySQL中批量插入数据
不管怎么样, 你需要大量的数据, 那么问题来了, 怎么快速地插入呢? 1. 这是我创建的一个批量插入的存储过程… 当然, 你可以把参数去掉, 一次性插入1W, 10W… CREATE DEFINER= ...