Archive for 11월, 2017

Introduction to OSGi


Introduction to OSGi
// Baeldung

1. Introduction

Several Java mission-critical and middleware applications have some hard technological requirements.

Some have to support hot deploy, so as not to disrupt the running services – and others have to be able to work with different versions of the same package for the sake of supporting external legacy systems.

The OSGi platforms represent a viable solution to support this kind of requirements.

The Open Service Gateway Initiative is a specification defining a Java-based component system. It’s currently managed by the OSGi Alliance, and its first version dates back to 1999.

Since then, it has proved to be a great standard for component systems, and it’s widely used nowadays. The Eclipse IDE, for instance, is an OSGi-based application.

In this article, we’ll explore some basic features of OSGi leveraging the implementation provided by Apache.

2. OSGi Basics

In OSGi, a single component is called a bundle.

Logically, a bundle is a piece of functionality that has an independent lifecycle – which means itcan be started, stopped and removed independently.

Technically, a bundle is just a jar file with a MANIFEST.MF file containing some OSGi-specific headers.

The OSGi platform provides a way to receive notifications about bundles becoming available or when they’re removed from the platform. This will allow a properly designed client to keep working, maybe with degraded functionality, even when a service it depends on, is momentarily unavailable.

Because of that, a bundle has to explicitly declare what packages it needs to have access to and the OSGi platform will start it only if the dependencies are available in the bundle itself or in other bundles already installed in the platform.

3. Getting the Tools

We’ll start our journey in OSGi by downloading the latest version of Apache Karaf from this link. Apache Karaf is a platform that runs OSGi-based applications; it’s based on the Apache‘s implementation of OSGi specification called Apache Felix.

Karaf offers some handy features on top of Felix that will help us in getting acquainted with OSGi, for example, a command line interface that will allow us to interact with the platform.

To install Karaf, you can follow the installation instruction from the official documentation.

4. Bundle Entry Point

To execute an application in an OSGi environment, we have to pack it as an OSGi bundle and define the application entry point, and that’s not the usual public static void main(String[] args) method.

So, let’s start by building an OSGi- based “Hello World” application.

We start setting up a simple dependency on the core OSGi API:

<dependency> <groupId>org.osgi</groupId> <artifactId>org.osgi.core</artifactId> <version>6.0.0</version> <scope>provided</scope> </dependency>

The dependency is declared as provided because it will be available in the OSGi runtime, and the bundle doesn’t need to embed it.

Let’s now write the simple HelloWorld class:

public class HelloWorld implements BundleActivator { public void start(BundleContext ctx) { System.out.println("Hello world."); } public void stop(BundleContext bundleContext) { System.out.println("Goodbye world."); } }

BundleActivator is an interface provided by OSGi that has to be implemented by classes that are entry points for a bundle.

The start() method is invoked by the OSGi platform when the bundle containing this class is started. In the other hand stop() is invoked before just before the bundle is stopped.

Let’s keep in mind that each bundle can contain at most one BundleActivator. The BundleContext object provided to both methods allows interacting with the OSGi runtime. We’ll get back to it soon.

5. Building a Bundle

Let’s modify the pom.xml and make it an actual OSGi bundle.

First of all, we have to explicitly state that we’re going to build a bundle, not a jar:


Then we leverage the maven-bundle-plugin, courtesy of the Apache Felix community, to package the HelloWorld class as an OSGi bundle:

<plugin> <groupId>org.apache.felix</groupId> <artifactId>maven-bundle-plugin</artifactId> <version>3.3.0</version> <extensions>true</extensions> <configuration> <instructions> <Bundle-SymbolicName> ${pom.groupId}.${pom.artifactId} </Bundle-SymbolicName> <Bundle-Name>${}</Bundle-Name> <Bundle-Version>${pom.version}</Bundle-Version> <Bundle-Activator> com.baeldung.osgi.sample.activator.HelloWorld </Bundle-Activator> <Private-Package> com.baeldung.osgi.sample.activator </Private-Package> </instructions> </configuration> </plugin>

In the instructions section, we specify the values of the OSGi headers we want to include in the bundle’s MANIFEST file.

Bundle-Activator is the fully qualified name of the BundleActivator implementation that will be used to start and stop the bundle, and it refers to the class we’ve just written.

Private-Package is not an OSGi header, but it’s used to tell the plugin to include the package in the bundle but not make it available to other ones. We can now build the bundle with the usual command mvn clean install.

6. Installing and Running the Bundle

Let’s start Karaf by executing the command:

<KARAF_HOME>/bin/karaf start

where <KARAF_HOME> is the folder where Karaf is installed. When the prompt of the Karaf console appears we can execute the following command to install the bundle:

> bundle:install mvn:com.baeldung/osgi-intro-sample-activator/1.0-SNAPSHOT Bundle ID: 63

This instructs Karaf to load the bundle from the local Maven repository.

In return Karaf prints out the numeric ID assigned to the bundle that depends on the number of bundles already installed and may vary. The bundle is now just installed, we can now start it with the following command:

> bundle:start 63 Hello World

“Hello World” immediately appears as soon the bundle is started. We can now stop and uninstall the bundle with:

> bundle:stop 63 > bundle:uninstall 63

“Goodbye World” appears on the console, accordingly to the code in the stop() method.

7. An OSGi Service

Let’s go on writing a simple OSGi service, an interface that exposes a method for greeting people:

package com.baeldung.osgi.sample.service.definition; public interface Greeter { public String sayHiTo(String name); }

Let’s write an implementation of it that is a BundleActivator too, so we’ll be able to instantiate the service and register it on the platform when the bundle is started:

package com.baeldung.osgi.sample.service.implementation; public class GreeterImpl implements Greeter, BundleActivator { private ServiceReference<Greeter> reference; private ServiceRegistration<Greeter> registration; @Override public String sayHiTo(String name) { return "Hello " + name; } @Override public void start(BundleContext context) throws Exception { System.out.println("Registering service."); registration = context.registerService( Greeter.class, new GreeterImpl(), new Hashtable<String, String>()); reference = registration .getReference(); } @Override public void stop(BundleContext context) throws Exception { System.out.println("Unregistering service."); registration.unregister(); } }

We use the BundleContext as a mean of requesting the OSGi platform to register a new instance of the service.

We should also provide the type of the service and a map of the possible configuration parameters, which aren’t needed in our simple scenario. Let’s now proceed with the configuration of the maven-bundle-plugin:

<plugin> <groupId>org.apache.felix</groupId> <artifactId>maven-bundle-plugin</artifactId> <extensions>true</extensions> <configuration> <instructions> <Bundle-SymbolicName> ${project.groupId}.${project.artifactId} </Bundle-SymbolicName> <Bundle-Name> ${project.artifactId} </Bundle-Name> <Bundle-Version> ${project.version} </Bundle-Version> <Bundle-Activator> com.baeldung.osgi.sample.service.implementation.GreeterImpl </Bundle-Activator> <Private-Package> com.baeldung.osgi.sample.service.implementation </Private-Package> <Export-Package> com.baeldung.osgi.sample.service.definition </Export-Package> </instructions> </configuration> </plugin>

It’s worth noting that only the com.baeldung.osgi.sample.service.definition package has been exported this time, through the Export-Package header.

Thanks to this, OSGi will allow other bundles to invoke only the methods specified in the service interface. Package com.baeldung.osgi.sample.service.implementation is marked as private, so no other bundle will be able to access the members of the implementation directly.

8. An OSGi Client

Let’s now write the client. It simply looks up the service at startup and invokes it:

public class Client implements BundleActivator, ServiceListener { }

Let’s implement the BundleActivator start() method:

private BundleContext ctx; private ServiceReference serviceReference; public void start(BundleContext ctx) { this.ctx = ctx; try { ctx.addServiceListener( this, "(objectclass=" + Greeter.class.getName() + ")"); } catch (InvalidSyntaxException ise) { ise.printStackTrace(); } }

The addServiceListener() method allows the client to ask the platform to send notifications about the service that complies with the provided expression.

The expression uses a syntax similar to the LDAP’s one, and in our case, we’re requesting notifications about a Greeter service.

Let’s go on to the callback method:

public void serviceChanged(ServiceEvent serviceEvent) { int type = serviceEvent.getType(); switch (type){ case(ServiceEvent.REGISTERED): System.out.println("Notification of service registered."); serviceReference = serviceEvent .getServiceReference(); Greeter service = (Greeter)(ctx.getService(serviceReference)); System.out.println( service.sayHiTo("John") ); break; case(ServiceEvent.UNREGISTERING): System.out.println("Notification of service unregistered."); ctx.ungetService(serviceEvent.getServiceReference()); break; default: break; } }

When some modification involving the Greeter service happens, the method is notified.

When the service is registered to the platform, we get a reference to it, we store it locally, and we then use it to acquire the service object and invoke it.

When the server is later unregistered, we use the previously stored reference to unget it, meaning that we tell the platform that we are not going to use it anymore.

We now just need to write the stop() method:

public void stop(BundleContext bundleContext) { if(serviceReference != null) { ctx.ungetService(serviceReference); } }

Here again, we unget the service to cover the case in which the client is stopped before the service is being stopped. Let’s give a final look at the dependencies in the pom.xml:

<dependency> <groupId>com.baeldung</groupId> <artifactId>osgi-intro-sample-service</artifactId> <version>1.0-SNAPSHOT</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.osgi</groupId> <artifactId>org.osgi.core</artifactId> <version>6.0.0</version> </dependency>

9. Client and Service

Let’s now install the client and service bundles in Kafka by doing:

> install mvn:com.baeldung/osgi-intro-sample-service/1.0-SNAPSHOT Bundle ID: 64 > install mvn:com.baeldung/osgi-intro-sample-client/1.0-SNAPSHOT Bundle ID: 65

Always keep in mind that the identifier numbers assigned to each bundle may vary.

Let’s now start the client bundle:

> start 65

Therefore, nothing happens because the client is active and it’s waiting for the service, that we can start with:

> start 64 Registering service. Service registered. Hello John

What happens is that as soon as the service’s BundleActivator starts, the service is registered to the platform. That, in turn, notifies the client that the service it was waiting for is available.

The client then gets a reference to the service and uses it to invoke the implementation delivered through the service bundle.

10. Conclusion

In this article, we explored the essential features of OSGi with a straightforward example that it’s enough to understand the potential of OSGi.

In conclusion, whenever we have to guarantee that a single application has to be updated without any disservice, OSGi can be a viable solution.

The code for this post can be found over on GitHub.


Read in my feedly

나의 iPhone에서 보냄


한겨울 강추위 따위 한방에! ‘뜨끈뜨끈’ 국내여행코스 5선


한겨울 강추위 따위 한방에! ‘뜨끈뜨끈’ 국내여행코스 5선
// 네이버 여행+

올해도 이제 딱 한달 남았습니다. 본격적인 겨울의 시작인데요. 올 겨울시즌 강추위를 어떻게 하면 슬기롭고 즐겁게 보낼까…생각해보셨나요? 한국관광공사가 올 겨울 큰 시간과 비용을 들이지 않고도 즐길 수 있는 전국 ‘가장 따뜻한 여행코스’를 선별 했습니다. 1. 노천탕서 노을 보며 고구마 한입! ‘석모도미네랄온천’뜨끈한 노천에 몸을 담그고 감상하는 붉은 석양…그리고 강화 특산물 속노랑고구마 한입 베어물면 겨울철 이보다 더 달콤한 순간은 없답니다. 석모도는 강화도 외포항에서 서쪽으로 약 1.5km 떨어진 곳에 있습니다. 올해 석모대교가 개통하면서 섬으로 향하는 걸음이 한결 가벼워졌죠. 석모도미네랄온천은 지난 1월 개장한…….

Read in my feedly

나의 iPhone에서 보냄

Dockerizing Jenkins build logs with ELK stack (Filebeat, Elasticsearch, Logstash and Kibana) – Ifrit LTD


Dockerizing Jenkins build logs with ELK stack (Filebeat, Elasticsearch, Logstash and Kibana) – Ifrit LTD


Install SSH on Windows 10 as Optional Feature | Thomas Maurer


Install SSH on Windows 10 as Optional Feature | Thomas Maurer


Thursday, Nov. 23, 2017 – The Daily Docker


Thursday, Nov. 23, 2017 – The Daily Docker


Display All Time Zones With GMT And UTC in Java


Display All Time Zones With GMT And UTC in Java
// Baeldung

1. Overview

Whenever we deal with times and dates, we need a frame of reference. The standard for that is UTC, but we also see GMT in some applications.

In short, UTC is the standard, while GMT is a time zone.

This is what Wikipedia tells us regarding what to use:

For most purposes, UTC is considered interchangeable with Greenwich Mean Time (GMT), but GMT is no longer precisely defined by the scientific community.

In other words, once we compile a list with time zone offsets in UTC, we’ll have it for GMT as well.

First, we’ll have a look at the Java 8 way of achieving this and then we’ll see how we can get the same result in Java 7.

2. Getting a List Of Zones

To start with, we need to retrieve a list of all defined time zones.

For this purpose, the ZoneId class has a handy static method:

Set<String> availableZoneIds = ZoneId.getAvailableZoneIds();

Then, we can use the Set to generate a sorted list of time zones with their corresponding offsets:

public List<String> getTimeZoneList(OffsetBase base) { LocalDateTime now =; return ZoneId.getAvailableZoneIds().stream() .map(ZoneId::of) .sorted(new ZoneComparator()) .map(id -> String.format( "(%s%s) %s", base, getOffset(now, id), id.getId())) .collect(Collectors.toList()); }

The method above uses an enum parameter which represents the offset we want to see:

public enum OffsetBase { GMT, UTC }

Now let’s go over the code in more detail.

Once we’ve retrieved all available zone IDs, we need an actual time reference, represented by

After that, we use Java’s Stream API to iterate over each entry in our set of time zone String id’s and transform it into a list of formatted time zones with the corresponding offset.

For each of these entries, we generate a ZoneId instance with map(ZoneId::of).

3. Getting Offsets

We also need to find actual UTC offsets. For example, in the case of Central European Time, the offset would be +01:00.

To get the UTC offset for any given zone, we can use LocalDateTime’s getOffset() method.

Also note that Java represents +00:00 offsets as Z.

So, to have a consistent looking String for time zones with the zero offset, we’ll replace Z with +00:00:

private String getOffset(LocalDateTime dateTime, ZoneId id) { return dateTime .atZone(id) .getOffset() .getId() .replace("Z", "+00:00"); }

4. Making Zones Comparable

Optionally, we can also sort the time zones according to offset.

For this, we’ll use a ZoneComparator class:

private class ZoneComparator implements Comparator<ZoneId> { @Override public int compare(ZoneId zoneId1, ZoneId zoneId2) { LocalDateTime now =; ZoneOffset offset1 = now.atZone(zoneId1).getOffset(); ZoneOffset offset2 = now.atZone(zoneId2).getOffset(); return offset1.compareTo(offset2); } }

5. Displaying Time Zones

All that’s left to do is putting the above pieces together by calling the getTimeZoneList() method for each OffsetBase enum value and displaying the lists:

public class TimezoneDisplayApp { public static void main(String... args) { TimezoneDisplay display = new TimezoneDisplay(); System.out.println("Time zones in UTC:"); List<String> utc = display.getTimeZoneList( TimezoneDisplay.OffsetBase.UTC); utc.forEach(System.out::println); System.out.println("Time zones in GMT:"); List<String> gmt = display.getTimeZoneList( TimezoneDisplay.OffsetBase.GMT); gmt.forEach(System.out::println); } }

When we run the above code, it’ll print the time zones for UTC and GMT.

Here’s a snippet of how the output will look like:

Time zones in UTC: (UTC+14:00) Pacific/Apia (UTC+14:00) Pacific/Kiritimati (UTC+14:00) Pacific/Tongatapu (UTC+14:00) Etc/GMT-14

6. Java 7 and Before

Java 8 makes this task easier by using the Stream and Date and Time APIs.

However, if we have a Java 7 and before a project, we can still achieve the same result by relying on the java.util.TimeZone class with its getAvailableIDs() method:

public List<String> getTimeZoneList(OffsetBase base) { String[] availableZoneIds = TimeZone.getAvailableIDs(); List<String> result = new ArrayList<>(availableZoneIds.length); for (String zoneId : availableZoneIds) { TimeZone curTimeZone = TimeZone.getTimeZone(zoneId); String offset = calculateOffset(curTimeZone.getRawOffset()); result.add(String.format("(%s%s) %s", base, offset, zoneId)); } Collections.sort(result); return result; }

The main difference with the Java 8 code is the offset calculation.

The rawOffset we get from TimeZone()‘s getRawOffset() method expresses the time zone’s offset in milliseconds.

Therefore, we need to convert this to hours and minutes using the TimeUnit class:

private String calculateOffset(int rawOffset) { if (rawOffset == 0) { return "+00:00"; } long hours = TimeUnit.MILLISECONDS.toHours(rawOffset); long minutes = TimeUnit.MILLISECONDS.toMinutes(rawOffset); minutes = Math.abs(minutes - TimeUnit.HOURS.toMinutes(hours)); return String.format("%+03d:%02d", hours, Math.abs(minutes)); }

7. Conclusion

In this quick tutorial, we’ve seen how we can compile a list of all available time zones with their UTC and GMT offsets.

And, as always, the full source code for the examples is available over on GitHub, both the Java 8 version and Java 7 version.


Read in my feedly

나의 iPhone에서 보냄


동기 부여를 위한 구성원 면담의 5가지 포인트 | ㅍㅍㅅㅅ


동기 부여를 위한 구성원 면담의 5가지 포인트 | ㅍㅍㅅㅅ


Docker Admin – Google 프레젠테이션


Docker Admin – Google 프레젠테이션


마시멜로우 스파게티면 게임, 마시멜로우 챌린지(Marshmallow challenge) : 네이버 블로그


마시멜로우 스파게티면 게임, 마시멜로우 챌린지(Marshmallow challenge) : 네이버 블로그


마음챙김 : 같이가치 with kakao


마음챙김 : 같이가치 with kakao