Shell: Simple bundle watch list

Creating a watchlist could be laboriously (what a word :-/). Therefore using shell scripting could help a lot.

The first sample shows how to grep a list of interesting bundles to watch. In my case it’s all mhu-lib bundles (add ‘–color never’ to avoid creation of violating escape sequences):

karaf@root()> bundle:list|grep --color never mhu-lib
 89 | Active |  80 | 3.3.0.SNAPSHOT     | mhu-lib-annotations
 90 | Active |  80 | 3.3.0.SNAPSHOT     | mhu-lib-core
 91 | Active |  80 | 3.3.0.SNAPSHOT     | mhu-lib-jms
 92 | Active |  80 | 3.3.0.SNAPSHOT     | mhu-lib-karaf
 93 | Active |  80 | 3.3.0.SNAPSHOT     | mhu-lib-persistence
karaf@root()>

I only need the bundle names, so cut the last column out of the result:

karaf@root()> bundle:list|grep --color never mhu-lib|cut -d '\|' -f 4 -t
mhu-lib-annotations
mhu-lib-core
mhu-lib-jms
mhu-lib-karaf
mhu-lib-persistence
karaf@root()>

Now we need to parse it line by line. A loop would help. The results are used to add the bundle to the bundle:watch list

bundle:list|grep --color never mhu-lib|cut -d '\|' -f 4 -t|run -c "for b in read *;bundle:watch \$b;done"

The ‘read *’ command reads everything from the pipe and the for loop will cut it into lines and run the loop for every entry. The line content is stored in ‘b’. To stop replacement of ‘$b’ by the shell itself (should be done later in the loop) you need to escape the ‘$’ character.

If you want to use a persistent bundle watch use the ‘mhu osgi tool’ called ‘bundle:persistentwatch’. You need to add the entries to the persistent list.

bundle:list|grep --color never mhu-lib|cut -d '\|' -f 4 -t|run -c "for b in read *;bundle:persistentwatch add \$b;done"

Print the list using ‘list’:

karaf@root()> bundle:persistentwatch list
Bundle             
-------------------
mhu-lib-annotations
mhu-lib-core       
mhu-lib-jms        
mhu-lib-karaf      
mhu-lib-persistence

 

Advertisements

Karaf: Scheduling GoGo Commands Via Blueprint

A new feature with mhu-lib 3.3 is the karaf scheduling service. The service is designed to be configured by blueprint and executes gogo-shell scripts. In this way you are able to execute every regular maintenance by automation.

Use this sample blueprint to print a hello world for every 2 minutes:

<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
    <bean id="cmd" 
          class="de.mhus.lib.karaf.services.ScheduleGogo" 
          init-method="init" destroy-method="destroy">
      <property name="name" value="cmd_hello"/>
      <property name="interval" value="*/2 * * * *"/>
      <property name="command" value="echo 'hello world!'"/>
      <property name="timerFactory" ref="TimerFactoryRef" />
    </bean>
    <reference
       id="TimerFactoryRef" 
       interface="de.mhus.lib.core.util.TimerFactory" />
    <service 
      interface="de.mhus.lib.karaf.services.SimpleServiceIfc" 
      ref="cmd">
        <service-properties>
            <entry key="osgi.jndi.service.name" value="cmd_hello"/>
        </service-properties>
    </service>
</blueprint>

Migrate shell commands from Karaf 3 to Karaf 4

Today the migration from Karaf 3 to version 4 brings some new interesting effects. One of them is a full yellow ‘blinking’ source code where shell commands are implemented.

It looks like all the shell interfaces from version 3 are deprecated now. The reason is that the developers want to define commands without using blueprint definition files in the OSGI INF folder any more. But to establish the new way a new interface is created and in focus.

To use the new interface you first  have to change the maven configuration of your project. Add the following parameters:

 <felix.plugin.version>3.0.1</felix.plugin.version>
 <maven.version>2.0.9</maven.version>

And the following parts inside your main pom.xml:

<dependencyManagement>
 <dependencies>
 <dependency>
 <groupId>org.apache.felix</groupId>
 <artifactId>maven-bundle-plugin</artifactId>
 <version>${felix.plugin.version}</version>
 </dependency>
 <dependency>
 <groupId>org.apache.maven</groupId>
 <artifactId>maven-plugin-api</artifactId>
 <version>${maven.version}</version>
 </dependency>
 </dependencies>
 </dependencyManagement>
 <pluginManagement>
 <plugins>
 <plugin>
 <groupId>org.apache.karaf.tooling</groupId>
 <artifactId>karaf-services-maven-plugin</artifactId>
 <version>${karaf.version}</version>
 <executions>
 <execution>
 <id>service-metadata-generate</id>
 <phase>process-classes</phase>
 <goals>
 <goal>service-metadata-generate</goal>
 </goals>
 </execution>
 </executions>
 </plugin>
 </plugins> 
 </pluginManagement>

Now you need to add the following build instruction to every sub project into the build/plugin part of the pom.xml:

 <plugin>
 <groupId>org.apache.karaf.tooling</groupId>
 <artifactId>karaf-services-maven-plugin</artifactId>
 </plugin>

This was the basic configuration to instruct maven to build everything right. Now you can remove the old blueprint.xml files because they are no more in use.

To create or update command add the following imports:

import org.apache.karaf.shell.api.action.Action;
import org.apache.karaf.shell.api.action.Argument;
import org.apache.karaf.shell.api.action.Command;
import org.apache.karaf.shell.api.action.Option;

Mark the class as component and service and enhance ‘Action’:

@Command(scope = “test”, name = “cmd”, description = “Test Command”)
@Service
public class CmdTest implements Action {

The old interface had a method ‘execute(Session)’ but the new one is only ‘execute()’. The parameter is left. To have access to the session you need to add a reference variable like this:

@Reference
private Session session;

after building and deploying into karaf engine the command is available as usually.

POJO handling with mhu-lib

mhu-lib brings a full featured POJO handler. The framework is able to parse POJO objects uses the found attributes to get and set values. Also a toolset to transform JSON or XML structures directly into/from POJO objects. It’s al located in the package ‘de.mhus.lib.core.pojo’.

The base class is the POJO Parser. It’s not working a lot but it brings all together. First important choice is how to parse. Parse strategies are implemented by default looking for attributes (AttributesStrategy) or functions (FunctionsStrategy). The default strategy (DefaultStrategy) combines both but it’s possible to change the strategy object for the parser. Strategies are also looking for the @Embedded annotation and parse deeper inside this attributes. Important: The attribute based Strategy is also able to access ‘private’ declared values! Is no need to declare them all ‘public’.

The strategy creates a PojoModel which can be manipulated by filters. The default filter (DefaultFilter) remove @Hidden tagged attributes. The resulting model allows the coder to access the attributes.

POJO handling with mhu-lib

An example POJO:

public class MyPojo {
  private String name;
  private long id;
  private String displayName;

  public String getName() {
    return name;
  }
  public String getDisplayName() {
    return displayName;
  }
  public void getId() {
    return id;
  }
}

Now use the POJOParser to create the POJOModel:

model = new PojoParser().parse(MyPojo.class).getModel();

More complex, use only @Public tagged attributes and concat @Embedded with “_”.:

model = new PojoParser().parse(MyPojo.class, "_", new Class[] {Public.class}).filter(true,false,true,false,true).getModel();

To set the values get the model parameters. Identifiers will be lower case. To access ‘displayName’ the identifier is ‘displayname’:

model.getAttribute("displayname").set(instance, "this is a sample");

The framework is a fast, stable and flexible way to use POJO objects in a common way.

Tipp: Create the model once and use it for all POJOs of the same type.

Parameter Related Classes Tree

Parameter Related Classes Tree

In mhu-lib there is a general attention to properties or attribute related objects. The implementation follows the philosophy that most thirst are attribute related and that is should be handled as the same. Properties and attributes are handled as the same not because they are the same but they have the same behavior.

First of all the IProperties class (since mhu-lib 3.3 a real interface) define a the basic behavior to set and get different value types. All java primitives are supported and the ‘Object’ type. The default implementation (e.g. MProperties) uses the getObject() variant and cast the object to the asked primitive by using the ‘MCast’ utilities. This simple structure is a flat properties store.

The ‘ResourceNode’ and ‘WritableResourceNode’ extends the structure to be a tree. With ‘getNodes()’ or ‘getNode(key)’ or ‘getParent()’ it is possible to traverse thru the tree structure.

An interesting extension of ‘WritableResourceNode’ is ‘IConfig’ with a lot of implementations to load configuration information from different types of sources like XML, JSON and properties files or a memory only variant.

The ‘CaoNode’ from the Content Access Object implementation is also attribute based. The framework enables common access to different tree based content structures like filesystem. (It’s currently recreated and not stable in later versions (mhu-lib 2.x) an EMC Documentum and Adobe AEM/CQ5 driver where available also.)

What is mhus-lib for?

This article is about the need of mhus-lib and a short history to explain. It also describes the different sections shortly (First of all it’s a library for the java VM).

The lib is called by my name because originally it was designed as a tool to solve problems I have in every project in the same way. The first version (in this time called mhu-lib) was a small set of static classes to convert data or to load simple information like the current host name.

In the next years the library was growing also solving more complex problems like how to handle different configurations in a common way. Handle POJOs and database access. It learned to serialize object into a RMDB and how to define forms in a generally way.  Also a common logging framework I really love was implemented. That was version 2.

In version 3 all the things are becoming a more common and integrated touch. Package declarations changed and the library is now OSGi usable.

But why not using one of the common frameworks like apache-commons or spring? The answer is simple – for me – this library implements exactly what I need to develop and after some tries I know it’s more robust, faster and handier than the alternatives. This is really subjective but – for me – true. I have some basic rules to implement functions:

  • Keep it simple: I don’t want to use complex stuff
  • Keep it generic
  • Robustness: It’s most important to think about when/where to handle exceptions
  • Don’t reinvent the wheel

Currently there are the following sections:

Continue reading “What is mhus-lib for?”

Fresh command shell:cut

Just added the command ‘shell:cut’ to allow splitting of lines. The command is more flexible as the original shell command and allows spliting by regular expressions.

This is the option list:

  • -r Replace regex
  • -e Regular expression
  • -d Seperate parts by this regex
  • -t Trim every single part
  • -f Fields expression
  • -j Glue between fields
  • -p Positions

Field expressions are a comma separated list of fields or field ranges. The first field is zero ‘0’.

Examples:

bundle:list|cut -d \\\| -t -j ' ' -f 1,3,2
Active 80 0.0.0
...
bundle:list|cut -d \\\| -t -j ' ' -f 1-,0
Active 80 1.4 Commons DBCP 71
...
bundle:list|cut -d \\\| -t -j ' ' -f 1,abc,2
Active abc 80
...

The option -p followed by a list of ranges in the line.

Examples:

bundle:list|cut -j '&' -p 10-20,1-10,abc
ve |  80 |&69 | Acti&abc
...

Every positions definition can’t be out of boundls. In the worst case it will be ignored. An empty line – without written fields – will be ignored.

The options -e and -r must be defined together and change the line content before processing the split mechanism.