created by Dirk Fauth and Peter Kirschner Know-How inside Powerpoint Presentation
EclipseCon Europe 2016
Schubartsaal
October 25, 2016 - 09:00 to 12:00
File -> New -> Plug-in Project
examples.pde.service.api
copy the following snippet and paste it into src folder
package examples.service.api;
public interface StringModifier {
String modify(String input);
}
Inside the Manifest Editor on the Runtime Tab
export the package with version 1.0.0
You successfully created the Service API Bundle if your MANIFEST.MF look like this.
File -> New -> Plug-in Project
examples.pde.impl.inverter
examples.service.api
2.0.0
org.osgi.service.component.annotations
optional
package examples.pde.impl.inverter;
import org.osgi.service.component.annotations.Component;
import examples.service.api.StringModifier;
@Component
public class StringInverterImpl implements StringModifier {
@Override
public String modify(String input) {
return new StringBuilder(input).reverse().toString();
}
}
You successfully created the Impl Bundle if look like this.
File -> New -> Plug-in Project
examples.pde.command
examples.service.api
2.0.0
org.osgi.service.component.annotations
optional
copy the following snippet and paste it into src folder
package examples.pde.command;
import org.osgi.service.component.annotations.*;
import examples.service.api.StringModifier;
@Component(
property = {
"osgi.command.scope" + "=zExampleModifier",
"osgi.command.function" + "=modify" },
service = StringModifierCommand.class
)
public class StringModifierCommand {
private StringModifier modifier;
@Reference
void bindStringModifier(StringModifier modifier) {
this.modifier = modifier;
}
public void modify(String message) {
System.out.println(modifier.modify(message));
}
}
update the StringModifierCommand
@Reference
void bindStringModifier(StringModifier modifier) {
this.modifier = modifier;
}
void updatedStringModifier(StringModifier modifier, Map<String, ?> properties) {
properties.forEach((k,v) -> {System.out.println(k + " : " + v);} );
}
void unbindStringModifier(StringModifier modifier) {
this.modifier = null;
}
public void modify(String message) {
System.out.println(modifier.modify(message));
}
Run -> Run configurations ...
simple_runtime
bundle | purpose |
---|---|
examples.pde.command | application service consumer |
examples.pde.impl.inverter | application service implementation |
examples.pde.service.api | application service api |
org.apache.felix.gogo.command | OSGi console commands |
org.apache.felix.gogo.runtime | OSGi console runtime |
org.apache.felix.gogo.shell | OSGi console shell |
bundle | purpose |
---|---|
org.eclipse.equinox.console | Equinox OSGi console |
org.eclipse.equinox.ds | Equinox Declarative Services |
org.eclipse.equinox.util | Equinox Util bundle |
org.eclipse.osgi | Equinox OSGi runtime |
org.eclipse.osgi.services | Equinox OSGi service interfaces |
simple_runtime
modify example
File -> Export ... -> Plug-in Development -> Deployable plug-ins and fragments
examples.pde.*
C:\ece2016\equinox_oxygen_runtime
C:\ece2016\equinox_oxygen_runtime
modify example
select from menu:
File -> New -> Bnd OSGi Workspace
GitHub -> bndtools/workspace
The Repositories view contains entries, as shown below.
File -> New -> Bnd OSGi Project
Select API Project 3.3.0
examples.bndtools.service.api
examples.service.api
package examples.service.api;
public interface StringModifier {
String modify(String input);
}
Bundle-Name: Example Service API
<prj>/generated
folderFile -> New -> Bnd OSGi Project
Select Component Development 3.3.0
examples.bndtools.impl.inverter
examples.bndtools.service.api
package examples.bndtools.impl.inverter;
import org.osgi.service.component.annotations.*;
import examples.service.api.StringModifier;
@Component
public class StringInverterImpl implements StringModifier {
@Override
public String modify(String input) {
return new StringBuilder(input).reverse().toString();
}
}
File -> New -> Bnd OSGi Project
Select Component Development 3.3.0
examples.bndtools.command
examples.bndtools.service.api
package examples.bndtools.command;
import org.osgi.service.component.annotations.*;
import examples.service.api.StringModifier;
@Component(
property = {
"osgi.command.scope" + "=zExampleModifier",
"osgi.command.function" + "=modify" },
service = StringModifierCommand.class
)
public class StringModifierCommand {
@Reference
private StringModifier modifier;
public void modify(String message) {
System.out.println(modifier.modify(message));
}
}
launch.bndrun
from project examples.bndtools.commands
org.apache.felix.framework;version='[5.4.0,5.4.0]'
JavaSE-1.8
bundle | purpose |
---|---|
examples.pde.command | application service consumer |
examples.pde.impl.inverter | application service implementation |
examples.pde.service.api | application service api |
org.apache.felix.configadmin | Apache Configuration Admin only required due to bug in Apache Felix SCR 2.0.6 |
org.apache.felix.metatype | Apache OSGi Metatype Service only required due to bug in Apache Felix SCR 2.0.6 |
"Run OSGi"
modify example
Export
on the top-rightC:\ece2016\inverter.jar
C:\ece2016
java -jar inverter.jar
modify example
@Activate
and @Deactivate
methods to StringInverterImpl
and StringModifierCommand
@Activate
void activate() {
System.out.println(this.getClass() + " activated");
}
@Deactivate
void deactivate() {
System.out.println(this.getClass() + " deactivated");
}
Description | Equinox in PDE | Felix in bndtools |
---|---|---|
List all components to see state and component id | list |
scr:list |
Execute the modify command to activate the components and check the console output | modify test |
modify test |
List all components again to verify the state change | list |
scr:list |
Disable StringInverterImpl and check the console output | dis <compID> |
scr:disable examples.bndtools. |
List all components again to verify the state change | list |
scr:list |
Enable StringInverterImpl and check the console output | en <compID> |
scr:enable examples.bndtools. |
List all components again to verify the state change | list |
scr:list |
File -> New -> Plug-in Project
examples.pde.impl.configurable
examples.service.api
2.0.0
org.osgi.service.component.annotations
optional
copy the following snippet and paste it into src folder
package examples.pde.impl.configurable;
public interface Constants {
String PREFIX = "prefix";
String SUFFIX = "suffix";
String ITERATION = "iteration";
String UPPER_CASE = "uppercase";
}
if you did not implemented it yourself, copy the following snippet and paste it into src folder
package examples.pde.impl.configurable;
import java.util.Map;
import org.osgi.service.component.annotations.*;
import examples.service.api.StringModifier;
@Component(
configurationPid="manipulator",
configurationPolicy=ConfigurationPolicy.REQUIRE
)
public class StringManipulator implements StringModifier {
Map<String, Object> config;
@Activate
void activate(Map<String, Object> config) {
System.out.println(this.getClass() + " activated");
this.config = config;
}
@Modified
void modified(Map<String, Object> config) {
this.config = config;
}
public void deactivate() {
System.out.println(this.getClass() + " de-activated");
}
@Override
public String modify(String input) {
String prefix = (String) config.getOrDefault(Constants.PREFIX, "");
String suffix = (String) config.getOrDefault(Constants.SUFFIX, "");
Integer iteration = (Integer) config.getOrDefault(Constants.ITERATION, Integer.valueOf(1));
Boolean upperCase = (Boolean) config.getOrDefault(Constants.UPPER_CASE, Boolean.FALSE);
StringBuilder builder = new StringBuilder();
builder.append(prefix);
for (int i = 0; i < iteration; i++) {
builder.append(upperCase ? input.toUpperCase() : input);
}
builder.append(suffix);
return builder.toString();
}
}
if you did not implemented it yourself, copy the following snippet and paste it into src folder
package examples.pde.impl.configurable;
import java.io.IOException;
import java.util.Dictionary;
import java.util.Hashtable;
import org.osgi.service.cm.Configuration;
import org.osgi.service.cm.ConfigurationAdmin;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
@Component(
property = {
"osgi.command.scope:String=zExamplesModifier",
"osgi.command.function:String=config"
},
service = ConfigCommand.class)
public class ConfigCommand {
ConfigurationAdmin cm;
@Reference
void setConfigAdmin(ConfigurationAdmin cm) {
this.cm = cm;
}
public void config(String key, String value) throws IOException {
if (Constants.PREFIX.equals(key) || Constants.SUFFIX.equals(key)) {
Configuration config = cm.getConfiguration("manipulator");
Dictionary<String, Object> props = null;
if (config != null && config.getProperties() != null) {
props = config.getProperties();
} else {
props = new Hashtable<>();
}
props.put(key, value);
config.update(props);
} else {
System.err.println("invalid key to value mapping");
}
}
public void config(String key, Integer value) throws IOException {
if (Constants.ITERATION.equals(key)) {
Configuration config = cm.getConfiguration("manipulator");
Dictionary<String, Object> props = null;
if (config != null && config.getProperties() != null) {
props = config.getProperties();
} else {
props = new Hashtable<>();
}
props.put(key, value);
config.update(props);
} else {
System.err.println("invalid key to value mapping");
}
}
public void config(String key, Boolean value) throws IOException {
if (Constants.UPPER_CASE.equals(key)) {
Configuration config = cm.getConfiguration("manipulator");
Dictionary<String, Object> props = null;
if (config != null && config.getProperties() != null) {
props = config.getProperties();
} else {
props = new Hashtable<>();
}
props.put(key, value);
config.update(props);
} else {
System.err.println("invalid key to value mapping");
}
}
}
if you did not implemented it yourself, copy the following snippet and paste it into src folder
package examples.pde.command;
import java.util.*;
import org.osgi.service.component.annotations.*;
import examples.service.api.StringModifier;
@Component(
property = {
"osgi.command.scope:String=zExampleModifier",
"osgi.command.function:String=modify"
},
service = StringModifierCommand.class
)
public class StringModifierCommand {
private List<StringModifier> modifier = new ArrayList<>();
@Activate
void activate() {
System.out.println(this.getClass() + " activated");
}
@Deactivate
void deactivate() {
System.out.println(this.getClass() + " deactivated");
}
@Reference(
cardinality=ReferenceCardinality.AT_LEAST_ONE
)
void bindStringModifier(StringModifier modifier) {
this.modifier.add(modifier);
}
void unbindStringModifier(StringModifier modifier) {
this.modifier.remove(modifier);
}
void updatedStringModifier(StringModifier modifier, Map<String, Object> properties) {
System.out.println(modifier.getClass() + " configuration updated");
properties.forEach((key, value) -> System.out.println(key + " = " + value));
}
public void modify(String input) {
modifier.forEach(m -> System.out.println(m.modify(input)));
}
}
configurable_runtime
bundle | purpose |
---|---|
examples.pde.impl.configurable | Application Bundle |
org.eclipse.equinox.cm | Equinox Configuration Admin Service |
org.eclipse.equinox.metatype | Equinox Metatype Service |
config uppercase true
modify test
examples.pde.impl.configurable
bundleStringModifierCommand
gets deactivatedexamples.pde.impl.configurable
bundleStringModifier
reference to dynamic
@Reference(
cardinality=ReferenceCardinality.AT_LEAST_ONE,
policy=ReferencePolicy.DYNAMIC
)
void bindStringModifier(StringModifier modifier) {
this.modifier.add(modifier);
}
examples.pde.impl.configurable
bundleStringModifierCommand
is not deactivatedFile -> New -> Bnd OSGi Project
Select API Project 3.3.0
examples.bndtools.impl.configurable
examples.bndtools.service.api
package examples.bndtools.impl.configurable;
import org.osgi.service.component.annotations.*;
import org.osgi.service.metatype.annotations.Designate;
import org.osgi.service.metatype.annotations.ObjectClassDefinition;
import examples.service.api.StringModifier;
@ObjectClassDefinition(name = "StringManipulator Configuration")
@interface StringManipulatorConfig {
String prefix() default "";
String suffix() default "";
int repeat() default 1;
boolean uppercase() default false;
}
@Component(
configurationPid = "manipulator",
configurationPolicy = ConfigurationPolicy.REQUIRE
)
@Designate(ocd = StringManipulatorConfig.class)
public class StringManipulator implements StringModifier {
StringManipulatorConfig config;
@Activate
void activate(StringManipulatorConfig config) {
System.out.println(this.getClass() + " activated");
this.config = config;
}
@Modified
void modified(StringManipulatorConfig config) {
this.config = config;
}
public void deactivate() {
System.out.println(this.getClass() + " de-activated");
}
@Override
public String modify(String input) {
String prefix = config.prefix();
String suffix = config.suffix();
Integer iteration = config.repeat();
Boolean upperCase = config.uppercase();
StringBuilder builder = new StringBuilder();
builder.append(prefix);
for (int i = 0; i < iteration; i++) {
builder.append(upperCase ? input.toUpperCase() : input);
}
builder.append(suffix);
return builder.toString();
}
}
if you did not implemented it yourself, copy the following snippet and paste it into src folder
package examples.bndtools.command;
import java.util.*;
import org.osgi.service.component.annotations.*;
import examples.service.api.StringModifier;
@Component(
property = {
"osgi.command.scope:String=zExampleModifier",
"osgi.command.function:String=modify"
},
service = StringModifierCommand.class
)
public class StringModifierCommand {
private List<StringModifier> modifier = new ArrayList<>();
@Activate
void activate() {
System.out.println(this.getClass() + " activated");
}
@Deactivate
void deactivate() {
System.out.println(this.getClass() + " deactivated");
}
@Reference(
cardinality=ReferenceCardinality.AT_LEAST_ONE
)
void bindStringModifier(StringModifier modifier) {
this.modifier.add(modifier);
}
void unbindStringModifier(StringModifier modifier) {
this.modifier.remove(modifier);
}
void updatedStringModifier(StringModifier modifier, Map<String, Object> properties) {
System.out.println(modifier.getClass() + " configuration updated");
properties.forEach((key, value) -> System.out.println(key + " = " + value));
}
public void modify(String input) {
modifier.forEach(m -> System.out.println(m.modify(input)));
}
}
launch.bndrun
from project examples.bndtools.impl.configurable
org.apache.felix.framework;version='[5.4.0,5.4.0]'
JavaSE-1.8
bundle | purpose |
---|---|
examples.bndtools.service.commdn | application service consumer |
examples.bndtools.impl.inverter | application service implementation |
examples.bndtools.impl.configurable | application service configurable implementation |
examples.bndtools.service.api | application service api |
bundle | purpose |
---|---|
org.apache.felix.gogo.shell | Gogo OSGi shell |
org.apache.felix.gogo.command | Gogo OSGi commands |
org.apache.felix.webconsole | Webconsole |
org.apache.felix.webconsole.plugins.ds | Webconsole Plugin |
Run OSGi
* open a Webbrowser on URL: http://localhost:8080/system/console
* enter Webconsole credentials (user and password: admin)
* navigate to OSGi -> Configuration
* provide a StringManipulator Configuration
* enter in the console modify example
Export
on the top-rightC:\ece2016\webconsole.jar
C:\ece2016
java -jar webconsole.jar
OSGi -> Configuration
StringManipulator Configuration
modify example
webconsole
bundle | purpose |
---|---|
javax.servlet | Servlet API |
org.apache.felix.webconsole | Apache Felix Webconsole (all) |
org.eclipse.equinox.http.jetty | Equinox OSGi Http Service |
org.eclipse.equinox.http.servlet | Equinox OSGi Http Service |
org.eclipse.jetty.continuation | Eclipse Jetty |
org.eclipse.jetty.http | Eclipse Jetty |
org.eclipse.jetty.io | Eclipse Jetty |
org.eclipse.jetty.security | Eclipse Jetty |
org.eclipse.jetty.server | Eclipse Jetty |
org.eclipse.jetty.servlet | Eclipse Jetty |
org.eclipse.jetty.util | Eclipse Jetty |
http_jetty_webconsole_bundles.zip
into e.g. *C:\ece2016\equinox_oxygen_runtime*
* start the application with the start_jetty.[bat|sh] script
* open a Webbrowser on URL: http://localhost:8888/system/console
* enter Webconsole credentials
* user: admin
* password: admin
* **Not working? - see next slide**
Modify the StringManipulator and add the necessary Remote Service Admin properties
@Component(
configurationPid="manipulator",
configurationPolicy=ConfigurationPolicy.REQUIRE,
property= { "service.exported.interfaces=*",
"service.exported.configs=ecf.generic.server" }
)
public class StringManipulator implements StringModifier {
configurable_runtime
and name it ecf_host_config
bundle | purpose |
---|---|
javax.servlet | Servlet API |
org.eclipse.core.jobs | Eclipse / Equinox Concurrency |
org.eclipse.equinox.common | Eclipse / Equinox Concurrency |
org.eclipse.equinox.concurrent | Eclipse / Equinox Concurrency |
org.eclipse.equinox.event | Eclipse / Equinox Event Admin |
ecf_rsa_bundles.zip
to the plugins directory of the created runtime e.g. C:\ece2016\equinox_oxygen_runtimeFile -> Export… -> Plug-in Development -> Deployable plug-ins and fragments
Next
examples.pde.*
Finish
start the application with the start script:
start_jetty.[bat|sh]
File -> Export… -> Plug-in Development -> Deployable plug-ins and fragments
Next
examples.pde.*
Finish
start the application with the start script:
start_jetty.[bat|sh]