Q2 User Interface (aka ‘QI’)

I’m happy to share some new stuff we have in jPOS-EE that we call “QI” (short for Q2 UI).

TL;DR: go to jpos.org/jpos using user admin and password test in order to see what I’m talking about. If you like it, keep reading, otherwise please ignore this message.

QI uses the Vaadin framework that we found very useful for our company’s web development and graphics design skillset (basically no skills). It allows us to create nice reusable web/mobile-friendly applications from Java in a highly modular way.

If you monitor @jposcommits you might have noticed a few new jPOS-EE components, like:

  • qi-core
  • qi-eeuser
  • qi-sysconfig

(see jPOS-EE/modules)

The main goal of the project is to have a bunch of reusable little QI modules (for instance, qi-minigl is coming) that you can use to put together very easily to administrate your jPOS application.

As the rest of the Q2 system, it uses an XML configuration file that gives you a top level control of your particular application, including centralised role-based permissions to access the different parts of the system.

<xml-config name="QI" logger="Q2">
    <title>jPOS QI</title>
    <locale>en-US</locale>
    <menubar>
        <menu name="System" icon="COG" style="icon-cog" action="system" />
        <menu name="Accounting"  action="accounting" />
    </menubar>

    <sidebar id="info">
        <section name="Info"/>
        <option name="Info" action="info"/>
    </sidebar>

    <sidebar id="system">
        <section name="System"/>
        <option name="Info" action="info"/>
        <option name="Log" action="log"/>
        <option name="Exception log" action="exceptions"/>
        <option name="Users" action="users"/>
        <option name="Roles" action="roles"/>
        <option name="Permissions" action="permissions"/>
        <option name="SysConfig" action="sysconfig"/>
        <option name="Audit Log" action="syslog"/>
        <option name="Revision History" action="revision_history"/>
    </sidebar>
    ...
    ...
</xml-config>

There you can see the top level menu that triggers two different sidebars. When we hit for example ‘Log’ it brings us to the ‘log’ action that is defined like this:

<view route="log" class="org.jpos.qi.system.LogListenerView" perm="sysadmin" sidebar="system" >
    <property name="name" value="logger.Q2.buffered"/>
    <property name="entityName" value="log"/>
</view>

If you hit the ‘info’ action, you get a tabbed pane, the tabbed pane is defined like this:

<view route="info" class="org.jpos.qi.views.TabView" perm="login" sidebar="system">
    <view caption="About" class="org.jpos.qi.system.AboutView" perm="login"/>
    <view caption="Memory" route="memory" 
        class="org.jpos.qi.system.MemoryUsageView" perm="login"/>
    <view caption="Sysmon" route="sysmon" 
        class="org.jpos.qi.system.ObjectView" perm="sysadmin" repeat="1000"
         clearScreen="true">
     <object class="org.jpos.util.SystemMonitor"/>
    </view>
    <view caption="Uptime" route="uptime" class="org.jpos.qi.system.ProcessView" perm="sysadmin" repeat="1000"
      clearScreen="true">
      <script>uptime</script>
    </view>
    <view caption="Date" route="date" class="org.jpos.qi.system.ObjectView" 
        perm="login" repeat="1000"
          clearScreen="true">
      <object class="java.util.Date"/>
    </view>
</view>

I suggest you take a look at how a simple view is implemented, for example the About view:

public class AboutView extends VerticalLayout implements View {
    public AboutView() {
        super();
        Label html = new Label(Q2.getVersionString());
        html.setContentMode(ContentMode.PREFORMATTED);
        setMargin(true);
        addComponent(html);
    }
    public void enter(ViewChangeListener.ViewChangeEvent event) { }
}

Some others like ObjectView or ProcessView are interesting, ObjectView can view any object and refresh it regularly, that’s how the ‘Date’ tab is implemented with a very simple XML configuration:

 <view caption="Date" route="date" class="org.jpos.qi.system.ObjectView" 
        perm="login" repeat="1000"
       clearScreen="true">
     <object class="java.util.Date"/>
 </view>

The ObjectView implementation is very simple (see code here) but behind the scenes QI uses web sockets (courtesy of a pre-configured Atmosphere setup) to refresh it.

If you go see the log and you telnet to us.jpos.org on port 9000 (that has an open XMLChannel with an auto-responder) you can see how smooth it is.

If you like this stuff you can clone the qitest project that demonstrate how to use QI in your own application.

Your feedback and contributions are greatly appreciated. If you really want to use this stuff, we’ll be happy to walk you through the setup and help with questions for undocumented features (we’ll be adding documentation to the jPOS-EE manual as time permits). The easiest way to do that is here on the list, or better yet, in the jPOS Slack (we are usually around from 1600 to 2000 GMT – see http://jpos.org/resources to get an invite)

jPOS 2.0.8 has been released

jPOS 2.0.8 has been released, new development version is now 2.0.9-SNAPSHOT

see ChangeLog for details.

This release includes the former jPOS-EE SSH module that can be enabled by calling Q2 with the --ssh switch.

This requires a file cfg/authorized_keys and defaults to port 2222. After starting the SSH service, one can:

ssh -p 2222 admin@localhost

and get a Q2 CLI prompt.

See q2 --help for details.

SpaceLogListener

In 2.0.4 we’ve added a SpaceLogListener that can be used to write log output in an asynchronous way.

It works with a companion LoggerService that pull entries from the Space and actually log them.

The configuration is very simple, here is an example:

00_logger.xml

<logger name="Q2" class="org.jpos.q2.qbean.LoggerAdaptor">
  <log-listener class="org.jpos.util.SpaceLogListener">
    <property name="queue" value="logger.q2" />
    <property name="space" value="tspace:default" />
    <property name="frozen" value="true" />
  </log-listener>
</logger>

01_logger_daemon.xml

(this is basically your old 00_logger.xml, synchronously writing to disk)

<logger name="DAEMON" class="org.jpos.q2.qbean.LoggerAdaptor">
    <log-listener class="org.jpos.util.DailyLogListener">
        <property name="window" value="86400" />
        <property name="prefix" value="log/q2" />
        <property name="suffix" value=".log"/>
        <property name="date-format" value="-yyyy-MM-dd-HH"/>
        <property name="compression-format" value="gzip"/> 
    </log-listener>
</logger>

02_logger_service.xml

<logger-service class="org.jpos.q2.qbean.LoggerService" logger="DAEMON">
    <property name="queue" value="logger.q2" />
    <property name="space" value="tspace:default" />
</logger-service>

The logger service pulls entries from logger.q2 space queue and uses the second logger as its output (we arbitrarily called it DAEMON).

The SpaceLogListener can send to the Space the original “Live” (so to speak) LogEvent, or create a Frozen one (see the frozen property). When set to true, log filters (i.e. the ProtectedLogFilter) has to be applied before the SpaceLogListener, otherwise, it won’t work on the frozen LogEvent.

A FrozenLogEvent is Serializable, so we are not limited to TSpace, one can use the ReplicatedSpace in order to implement a very simple central logging.

ReplicatedSpace – 10 years later

/by apr/

10 years ago I add an experimental ReplicatedSpace implementation to the jPOS-EE project. While it was fun to develop and test, it didn’t get too much traction (or so I thought).

It turned out that I’ve started to hear about several high-end production systems using it, so I migrated it from the old GoogleCode repo to the new Github one.

Want to give it a quick try? Here are the very simple instructions:

Clone de jPOS-Template into a test directory

git clone git@github.com:jpos/jPOS-template.git rspace && cd rspace

Edit build.gradle

Add the dependency compile "org.jpos.ee:jposee-rspace:2.0.9-SNAPSHOT", your dependencies will look like this:

dependencies {
  compile ('org.jpos:jpos:2.0.+') {
    exclude(module: 'junit')
    exclude(module: 'hamcrest-core')
  }
  testCompile 'junit:junit:4.8.2'
  compile "org.jpos.ee:jposee-rspace:2.0.9-SNAPSHOT"
}

Install resources

Call gradle installResources

This will extract the ReplicatedSpace configuration from its jar and will place it in your src/dist directory

Remove the file src/dist/deploy/01_multi_instance_prevention.xml so that you can run multiple instances on the same machine

Build a distribution

gradle dist

This will create a build/distributions/rspace-2.0.0.tar.gz that you can extract in several boxes. For a quick local run, you can gradle installApp and cd build/install/rspace to have the same effect.

Run the system

Call bin/q2 and you’ll see something like this:

<log realm="org.jpos.space.ReplicatedSpaceAdaptor" at="Thu Jun 04 15:18:17.406 UYT 2015" lifespan="1ms">
  <info>
   view-accepted
   [apr-19136|0] (1) [apr-19136]
 </info>
</log>

If you run it again, or in a different box in the same LAN, you’ll see several view-accepted messages.

At this point, you can create a little script to perform some space operations, i.e:

import org.jpos.space.*;
Space sp = SpaceFactory.getSpace("rspace:rspace");
sp.out ("TEST", "REPLICATED MESSAGE");

A nice way to run a script is to deploy something like this:

Add a file called say 90_script.xml to your deploy directory:

<script> server(6666); </script>

Then telnet localhost 6667 (please note the server says ‘6666’ but you connect to 6666+1, this is BeanShell stuff.

At the bsh% prompt, you can type your space operations.

Message HEX dump

From time to time, we may ask for a message hex dump, and here is how a dump looks like:

0000  08 00 A0 20 00 00 00 80  00 00 04 00 00 00 00 00  ... ............
0010  00 00 00 00 00 00 00 01  32 39 31 31 30 30 30 31  ........29110001
0020  00 01                                             ..

See? It’s ASCII text that one can easily copy and paste in order to load it in a simulator or test program (please move your mouse over the hex digits, you can see they are selectable).

It is extremely simple, you can capture a message using NetCat and then you can use the hd Unix command, or just send us the binary image in raw format, but please PLEASE P L E A S E, don’t send us a screen capture in graphic format inside a Word document or inside a cell of an spreadsheet.

When you send a graphic capture of a dump, like this:

HexDump

We need to re-type the dump in a text editor, which is error-prone and a waste of time. This is a very small example, but with large messages, the chances of introducing an error are high.

Another very common problem when we ask for a dump is that we get a high level representation of the message, some times in ASCII, copy and pasted into a message, but the mailers usually wrap around lines, not preserve blanks, and don’t show unprintable characters, so it’s extremely naive to think that we can do something useful with those kind of “dumps”.

When we ask for a message dump, we don’t want a full wall of IP-packets either, we are not debugging the TCP/IP protocol, we believe it works, so we are not interested in the session establishing, ICMP packets and IP-level headers.

We just ask, actually we cry for, a simple hex dump. Is that difficult?

jPOS 1.9.8 released

  • jPOS 1.9.8 has been released, the new development version is 1.9.9-SNAPSHOT
  • jPOS-EE 2.0.6-SNAPSHOT has now upgraded dependencies, including support for Jetty 9
  • jPOS-template has a new genDocker task that installs a jpostemplate image

See ChangeLog for details.