Tuesday, September 23, 2014

Netbeans 7.x and above - Linux issues

Recently, I posted about how much excited I am to see a good quality linux distro - Centos 7.

Here is another minor issue, which you could spend minutes together, and finally ditch Netbeans recommendation to your colleagues.

When you install JDK 1.7_x and follow netbeans installation, everything works fine.

Till you hit the menu options, where in your Menu tries to imitate the old Emacs style menu, where you have to hold to the dropdown with your life to make a selection.

Simple issues with Gnome-3 was the culprit. Simpler and a funny solution was found by the light souls of Linus mint contributors (forum).

http://forums.linuxmint.com/viewtopic.php?f=47&t=93011

So Netbeans rocks with 8.0 if you are into writing modular apps.

~peace.

Wednesday, July 23, 2014

OSGi Declarative Services with Karaf and SCR | Introduction and Hands on

Till the recent past, I was developing OSGi applications (bundles services) using either the blueprint way or the java DSL way.

I came across few articles about the power of DS (Declarative Services), introduced starting OSGi 4.0 spec release. Note that 4.2 specifications make DS more efficient and effective.

I wish to share my experience here that could help someone looking for a direction in this way and I would stick to my way of explaining with a hands on approach.

Prerequisites:

Assuming you are familiar with the following prerequisites before we jump into creating and using DS.
  • Understanding OSGi life cycle - Here I mean understanding roles of a container like karaf, a DI framework like the Aries (Refer here)
  • Understanding usage of BnD tools - A good pointer or a primer would be here (Courtesy Muruga)
  • Brief understanding of what an SCR  is (Service Component Runtime)
  • Understanding on OCD (Object Class Definitions)
  • Understanding on AD (Attribute Definitions)
  • Also the OSGi runtime configurations (typical persistence-IDs and the associated command usages)

Note: The BnD DS (Annotations) are a specification implementation defined to help assist OSGi component developers to reduce the pluming code and need not propagate to the deployable code.

The approach and structure of the example I want to explain here is to take a beginner simple complex example of  an API with more than one implementation (Providers) for same API interface and a consumer distinguishing between the kind of implementation it wants to invoke.

Approach

We will first build and deploy an API, Provider and Consumer, simply marking them with DS annotations.

API (BnD OSGi project)

package com.dix.osgi.api;

/**
 * 
 * @author Dixie.Sebastianappan
 * A simple API Service interface 
 */
public interface APIInterface {
 String callImplementer(String implementor);
}

Provider (BnD OSGi project)

package com.dix.osgi.impl;
import com.dix.osgi.api.APIInterface;
@Component
public class CarTypeImpl implements APIInterface {
 private static final Logger log = Logger.getLogger(CarTypeImpl.class.getName());
 public static final String IMPL_NAME = "CarTypeImpl";

 @Override
 public String callImplementer(String implementorText) {
  log.info("Car Implementor");
  return "CAR : " + implementorText;
 }

}
import com.dix.osgi.api.APIInterface;

@Component
public class CycleTypeImpl implements APIInterface {
 private static final Logger log = Logger.getLogger(CycleTypeImpl.class.getName());
 public static final String IMPL_NAME = "CycleTypeImpl";

 @Override
 public String callImplementer(String implementorText) {
  log.info("Cycle Implementor");
  return "CYCLE : " + implementorText;
 }

}

Consumer (BnD OSGi Project)

@Component
public class Consumer {

 private static final Logger log = Logger.getLogger(Consumer.class.getName());
 APIInterface car;
 APIInterface cycle;

 @Reference
 public void setCar(APIInterface car) {
  this.car = car;
  log.info(car.callImplementer("CarType"));
 }

 @Reference
 public void setCycle(APIInterface cycle) {
  this.cycle = cycle;
  log.info(cycle.callImplementer("CycleType"));
 }

}

If you try to deploy these as bundles and verify the SCR list, you would see

karaf@root > scr:list
   ID   State             Component Name
[5   ] [ACTIVE          ] CarTypeImpl
[6   ] [ACTIVE          ] CycleTypeImpl
[7   ] [ACTIVE          ] com.dix.osgi.consumer.Consumer
karaf@root >


Here the states of the components are ACTIVE.

But when you look at the logs, all the consumer APIInterface references point to the CarTypeImpl, since the consumer couldn't identify which instance of the implementer was injected to resolve.

To solve this ambiguity, DS provides a metatype mechanism to resolve the right version and service type binding.

The specification says that, a component can register itself using an unique identifier (component.name) and can host properties that can be used to resolve when a specific version or type of implementation is being looked up for. The specification also dictates policy modes to organize the way a component can register itself.

More information on @Component and @Reference metatype can be found here.

Hence rewriting the Provider classes' code with added meta information inside the @Component annotation would look like this.

@Component(name = CarTypeImpl.IMPL_NAME, configurationPolicy = ConfigurationPolicy.require, immediate = true)

Note: The immediate value is set to true, just for the testing purpose. Usually not adviced, since an instance will be created only when requested for.

After making a similar change to the other implementation (CycleTypeImpl) and a deployment will result with an unsatisfied state.

karaf@root > scr:list
   ID   State             Component Name
[5   ] [UNSTATISFIED          ] CarTypeImpl
[6   ] [UNSTATISFIED          ] CycleTypeImpl
[7   ] [UNSTATISFIED          ] com.dix.osgi.consumer.Consumer
karaf@root >

The reason is, the component information, indicates that the component should register only when a configuration policy is met. Which means a persistence id with the component name should exists, so that the components could register along with the configuration. In our case, configuration files with names CycleTypeImpl and CarTypeImpl and with extensions .cfg should exist under the etc folder.

Now, there are two ways to do this, 

1. Using the config commands
2. Directly creating the .cfg files under etc folder of the container

Once done, the configuration list should yield the following indicating the properties being set and the scr:list should show all the components with an ACTIVE status.

karaf@root > config:list | grep Impl
Pid:            CycleTypeImpl
   service.pid = CycleTypeImpl
   felix.fileinstall.filename = file:/D:/Installed/apache-karaf-2.3.5/etc/CycleTypeImpl.cfg
   ImplType = Cycle
Pid:            CarTypeImpl
   service.pid = CarTypeImpl
   felix.fileinstall.filename = file:/D:/Installed/apache-karaf-2.3.5/etc/CarTypeImpl.cfg
   ImplType = Car
karaf@root >

The next step is to update the consumer code to resolve the right Implementation instance of the API, by adding more properties to the @Reference annotation.

@Reference(target = "(ImplType=Car)")
 public void setCar(APIInterface car) {
  this.car = car;
  log.info(car.callImplementer("CarType"));
 }

 @Reference(target = "(ImplType=Cycle)")
 public void setCycle(APIInterface cycle) {
  this.cycle = cycle;
  log.info(cycle.callImplementer("CycleType"));
 }

Now building and deploying the applications, will have all the statuses active and working.

To ensure the properties were really being used to resolve the right type of Implementation instances, the Bundle activator methods (@Activate) can be used.

In this case for the CarTypeImpl provider, the following method can be added to verify if the CarTypeImpl is bound only to the CarTypleImpl instance reference.


 @Activate
 public void activate(final Map properties) {
  log.info("Car Implementor : Activating Car Implementor");

  if (properties.containsKey("ImplType")) {
   log.info("Car Implementor : " + (String) properties.get("ImplType"));
  } else {
   log.info("Car Implementor : Cannot read property ImplType");
  }
 }

Now that we have covered the basic of declarative services, I will create another post to use features to quickly deploy and test, instead of managing individual bundles.

~Peace.


Monday, July 21, 2014

Airtel (Huwai E3272) 4G LTE on CentOS-7

I'm happy that finally the official CentOS 7 is available for installation.

I had great experience and thoroughly enjoyed the seamless installation procedures.

Some precautions:

Try not to burn the ISO as a DVD and please refer to the CentOS page here, since
dd if=your.iso of=/path/to/your/USB will do the magic.

Also, please wait for the complete image copy - as the UEFI Dual BIO configurations are very sensitive and you might end up getting the

"Can't read kernel : /images/pxeboot/vmlinuz".

Also, disable secure boot before installation and you can enable after the installation is over.
Later you can enable only "UEFI boot option"  from "UEFI and Legacy" options.

Though the part, the RedHat provided preupg assistant wasted almost 2 hours of my Sunday time - when trying to upgrade from 6.5 and above.

Assuming you had great pleasure while installing CentOS 7 on your UEFI hardware, and also assuming you network is working fine, if you want to have your Airtel 4G LTE working on your 7 installation, you will need the following.

  • Setup of a clean EPEL repository
  • Setup Extras (not mandatory)
  • finally yum -y update with no transactions pending
Now, the Actual installation part.

If you have a 32bit installation (I doubt you could get hold of it officially yet), you are well off then.

For a 64bit installation, first copy the contents from the LTE, and make the install_linux as executable.

chmod +x install_linux

Executes, then if you get the compiler not found error, (I got since I did not install the development packages), please install dev packages.

Now, if you get ld-linux.so.2, ELF and cannot stat error,

then, you have to yumm it up for /lib/ld-linux.so.2 libX11.so.6 libpam.so.0 libstdc++.so.5

Then try to execute /usr/local/airtel/UninstallMobilePartner.

Mostly, it would not happen, but a try might save some time.

Now, that the 32 bit libraries are available and previous erroneous installation is gone, try the executing the install_linux again.

This time you should see an xterm, with NIOS module not installed and check your gcc version error might occur.

It is ok, since modem is anyways active. And you are happy to browse.

Another fact is on Fedora 20 you could see the Airtel application like you see on Windows.

With CentOS7 or RHEL 7 (I tried the beta, not sure how is the actual release vesion), you will see something like this.



All the required settings are already published by the installer, however, you can still configure authentications like username and password by selecting the network settings.

Note: On a KVM setup, I could see the Airtel Application window like the one on Windows, and on real metal it didn't show up.

So, finally a wireless data provider with good speed on Linux in India.

~Peace.