Search code examples
javaeclipse-pluginosgiosgi-bundle

Link different providers and consumers to one consumer using OSGI


I am trying to build a weather app using the OSGI framewrok . I have created a country finder with a consumer and a provider , and a city finder with a consumer and provider, and finally the weather provider and the consumer.

  1. In the country consumer i allow the user to check whether a country is available to check weather.
  2. In the city consumer i allow the user to check whether a city is available to check weather in the city provider i have used a hashmap country as key and city as value.
  3. In the weather bundle once the consumer is executed i want the user to be able to enter a city and the the country should be checked using the above created country bundle and if there is a country, next the user shoule be asked to input a city, the city should be checked using the city bundle, and if such a city exists, finally the weather provider should use that city and provide the weather details.

I am unable to understand how to link the weather bundle to both country and city bundles


Solution

  • I think the key insight is cohesion. In your description, your mixing very different aspects of your application. I.e. you mix the user interaction (I want the user ..) with the low-level mechanical details of finding specific information.

    The base idea of OSGi is to separate these parts into services. The service provides a low-level function that is highly cohesive. I.e. it does one thing, and one thing only. If you look at the Event Admin service, you see it does publish & subscribe. The idea is that you end up with different services that do one thing well and have no relation (or coupling) to any other services. This strategy allows them to be reused in many different applications. The moment you let the cohesion go down, you'll find that they become harder to reuse in other applications. This sounds easier than it is, it often takes some iterations to get a really cohesive service.

    Components are the OSGi things that can provide services. Generally, components consume other services. In your example, you could have a database that holds the cities. To keep your component cohesive, it should not directly manipulate the database, but instead, use a service. Your component should be an expert only in cities but have no clue about database stuff. Whenever you write a component and you become aware that you're writing code not related to cities, delegate it to another service. Make sure also that your database service has no clue about cities, it only knows about the database. The city component has a nice easy way getting access to its cities from a component that has no knowledge of cities whatsoever.

    If you think like this, you'll end up with a lot of services that do nothing. You need somewhere where you coordinate these services. This is the application. The application is responsible for the overall functionality. Its purpose is to tie all the loose ends together. In your case, it would consume the city, weather, and other services. It would also interact with the user. To interact with the user, it needs to be able to search for a city. So a service interface like this would be useful:

     public interface Geo {
         List<String> countries();
         List<String>    cities(String country);
         Country         city(String country);
         City            city(String city);
     }
    

    I am combining your city & country finder because I find them extremely cohesive. Breaking them up increases complexity. This service allows me to create a popup on the user interface with the countries, and from a selected country, I can select a city.

    Next is the weather service:

     public interface Weather {
           boolean hasWeather( String country, String city);
           Report getShortReport(String country, String city);
     }
    

    After having selected a country & city I can ask the weather service for a report.

    The reason I am using String in these interfaces is to prevent coupling between the Geo service and the Weather service. This is one of the main rookie mistakes I often see. Create City & Country types that are then used all over the place (or worse, CityKey), effectively making the system one big ball of mud again, where everything is tied to everything else by some classes that just act as a String.

    So now the application component can pick a GUI (HTML, gogo, Swing, SWT, etc.) It can effectively concentrate on the GUI and the low-level details are taken care of by the service providers. The application should generally be the only component in your system that is not reusable by anybody. If it is, split it between a reusable part and a specific part. Since this component is not reusable, it is the only place in your software where you do not have to care about coupling.

    Summary. The idea is that if you look at the service diagram of an OGSi application it should be crystal clear where things are happening, and the application component (often not a service itself) ties it all together.

    Hope this helps.