Monday, August 31, 2015

WebSphere MQ Explorer requires root access

WebSphere MQ Explorer is my favorite tool as its ease of use compared to command line. This tool is a separate installation apart from the MQv8 installation, the component name would have this file name pattern MQSeriesExplorer_<suffix>-8.0.0-2.x86_64.rpm. Unfortunately, it requires root user which has mqm group granted in order to create a queue. Otherwise a prompt showing following error stopping me to proceed further.
****************************************
* Command: /opt/mqm/bin/crtmqm  Q1
****************************************
Access not permitted. You are not authorized to perform this operation. (AMQ4036)
Since this tool is installed in Ubuntu 14.04, and it was launched in Unity Launcher. Unlike command prompt, sudo would be my best friend handling root access control. Unfortunately, this is a graphical environment, I would need graphical sudo to help me. Here is the clue, open this file: /usr/share/applications/IBM_WebSphere_MQ_Explorer-Installation1.desktop (this file requires root access as well), and modify the line:
...
Exec=/opt/mqm/bin/MQExplorer
...
with this:
...
Exec=gksudo -k -u root /opt/mqm/bin/MQExplorer
...

Saturday, August 29, 2015

Permission denied on crtmqm

This is so not good. I'm not able to create a queue after the WebSphere MQ installation. Following error was seen when I issue the command:
$ crtmqm Q1
bash: /usr/bin/crtmqm: Permission denied
$ sudo crtmqm Q1
AMQ7077: You are not authorized to perform the requested operation.
It has been so struggling with me at first, but later I have conquered the fear. As mention from this reference guide, I got a strong sense that I have not assigned my user ID to mqm group. Below is the text extract from the reference guide:
In WebSphere MQ, user id "mqm" and any ID which is a part of "mqm" group are the WebSphere MQ administrative users. WebSphere MQ queue manager resources are protected by authenticating against this user. Since the queue manager processes use and modify these queue manager resources, the queue manager processes will require "mqm" authority to access the resources. Hence, WebSphere MQ queue manager support processes are designed to run with the effective user-id of "mqm".
Since crtmqm is referring to /usr/bin/crtmqm, and it requires root access to it, thus it is wise to grand mqm group to the root user account instead of my user account.

Wednesday, August 26, 2015

MQv8 installation hit user limit error

Sigh~ There is another error while the MQv8 installation is undergoing. This time, the error was logged into a file, part of content causing the installation fails were shown here:
...

Current User Limits (root)
  nofile       (-Hn)  4096 files                         IBM>=10240        FAIL
  nofile       (-Sn)  1024 files                         IBM>=10240        FAIL
This has reminded me somewhere in the documentation did mention about the limit thing. Thus in my case, just append following configuration into /etc/security/limits.conf. This file may require root access in order to edit it.
...

mqm             hard    nofile          10240
mqm             soft    nofile          10240
# End of file
This should be the last error I face during the installation.

Tuesday, August 25, 2015

Cannot open Packages database during MQ installation

Continuing from the journey of previous installation on WebSphere MQ. This time, IBM has offered WebSphere MQ free of charge, the link of the site is here. As of this writing, I'm getting the MQv8 for Linux. No more waiting! This is a damn real great news for a poor guy like ME!

While I was about to install MQ after the step ./crtmqpkg suffix, something "abnormal" was blocking my way.
kokhoe@KOKHOE:/var/tmp/mq_rpms/LKH/x86_64$ sudo rpm -ivh --force-debian MQSeriesRuntime_LKH-8.0.0-2.x86_64.rpm 
error: db5 error(-30969) from dbenv->open: BDB0091 DB_VERSION_MISMATCH: Database environment version mismatch
error: cannot open Packages index using db5 -  (-30969)
error: cannot open Packages database in /home/kokhoe/.rpmdb
error: db5 error(-30969) from dbenv->open: BDB0091 DB_VERSION_MISMATCH: Database environment version mismatch
error: cannot open Packages database in /home/kokhoe/.rpmdb
I think this error doesn't belong to MQ specific because it happened on another package installer too. The clue I found was there is a hidden folder, .rpmdb is having some conflict since previous installation. By just removing that folder will make the rpm program smiling.

Friday, August 21, 2015

log4cpp::Category::xxx() do accept c_str()

Just got to know that in order to log a value of boost::filesystem::path with log4cpp, it is just as simple as follows:
   Category *pRoot = NULL;
   PropertyConfigurator::configure("log4c.properties");
   pRoot = &(Category::getRoot());

   path targetPath("./the_path");
   pRoot->info("%s", targetPath.c_str());
Assuming I have the following content in log4c.properties:
   log4cpp.rootCategory=DEBUG, rootAppender

   log4cpp.appender.rootAppender=ConsoleAppender
   log4cpp.appender.rootAppender.layout=PatternLayout
   log4cpp.appender.rootAppender.layout.ConversionPattern=%d [%p] %m%n

   ...
But before I got to know this, I heard there are people mention that the conversion from c_str() to const char* would not be straightforward. And it would require wcstombs() to do the conversion, thus I come out this:
   ...

   char pathName[50];
   memset(pathName, '\0', sizeof(pathName));
   wcstombs(pathName, targetPath.wstring().c_str(), sizeof(targetPath.native().length()));
   ...
Is this what they mean? Or I misunderstood something? No worry, log4cpp::Category::xxx() do accept c_str(). 

Monday, August 17, 2015

Setting up log4cpp with CMake

Remember last time when I was writing software application on C programming, this is what I did in diagnosing defects in the application.
#ifdef __DEBUG__
    // logging code here
#endif
This piece is everywhere, trapping malicious bugs. The usage of this piece is like this; If I want the log to show up, I turn on the __DEBUG__ switch like this: #define __DEBUG__, otherwise I'll remove the switch to turn it off.

Looking back my foolish happened in the pass, is a shame. Inspire from JAVA's log4j, I wish I could have something similar thing on C. Yup, there is one called log4cpp and it exists in the world for so long. It has very much similarity to log4j, just that some cautious to take attention during the initial setup.

As I'm using CMake in my project, the installation guide from the site don't have much detail on that. After some try and error, finally I need to have following piece in CMakeLists.txt:
...

include_directories(/usr/local/include/log4cpp)
link_directories(/usr/local/lib/)
find_package(Threads REQUIRED)

target_link_libraries(myprogram liblog4cpp.so ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})

...
The first line is to tell where the log4cpp's header files location, the second line tells where can I load the log4cpp's library. Never though of log4cpp has a dependency on threading library, it requires -pthread option in the build, otherwise following error would be seen:
...

/usr/local/lib/liblog4cpp.so: undefined reference to `pthread_key_create'
/usr/local/lib/liblog4cpp.so: undefined reference to `pthread_getspecific'
/usr/local/lib/liblog4cpp.so: undefined reference to `pthread_key_delete'
/usr/local/lib/liblog4cpp.so: undefined reference to `pthread_setspecific'
Thus, ${CMAKE_THREAD_LIBS_INIT} will do the trick. The last line will wrap up the build and log4cpp is ready to serve.

Goodbye to the ugly code.

Friday, August 14, 2015

When I move to Mars...

This is so not good, JBoss server was not functioning after I have upgraded my workspace to Eclipse Mars. I'm not even able to create new JBoss server as the server adapter was also gone missing.

There 2 requirements need to fulfill in order to get JBoss work under Eclipse Mars:

Requirement 1
Eclipse Mars must have JBoss Tools 4.3 installed. As of this writing, I'm using 4.3.0.Beta2 (the only version works on Eclipse Mars). It can be downloaded from Eclipse Marketplace or JBoss Tool's website.

Requirement 2
JBoss Tools 4.3 need to feed by JDK 8 as mention in this blog. I don't really want to disturb my global environment variable, JAVA_HOME, as she is serving for peoples too. Thus, what I'll do is to configure it in eclipse.ini.
-vm
/home/user/tool/jdk1.8.0_51/bin/java
-vmargs
-Dosgi.requiredJavaVersion=1.7
-XX:MaxPermSize=256m
-Xms256m
-Xmx1024m
Do take note that -vm must before -vamrgs, otherwise -vm will become argument of -vamrg.

Monday, August 10, 2015

JBoss Messaging doesn't have permission to create Queue?

I have a piece of JMS subscriber code that's going to connect to JBoss Messaging. However, it throws me an error when the subscriber was trying to load up the topic:
Exception in thread "main" javax.jms.JMSSecurityException: HQ119032: User: huahsin68 doesnt have permission=CREATE_NON_DURABLE_QUEUE on address {2}
 at org.hornetq.core.protocol.core.impl.ChannelImpl.sendBlocking(ChannelImpl.java:378)
 at org.hornetq.core.client.impl.ClientSessionImpl.internalCreateQueue(ClientSessionImpl.java:1987)
 at org.hornetq.core.client.impl.ClientSessionImpl.createTemporaryQueue(ClientSessionImpl.java:356)
 at org.hornetq.core.client.impl.DelegatingSession.createTemporaryQueue(DelegatingSession.java:304)
 at org.hornetq.jms.client.HornetQSession.createConsumer(HornetQSession.java:559)
 at org.hornetq.jms.client.HornetQSession.createConsumer(HornetQSession.java:378)
 at org.hornetq.jms.client.HornetQSession.createConsumer(HornetQSession.java:348)
 at org.hornetq.jms.client.HornetQSession.createSubscriber(HornetQSession.java:858)
 at org.huahsin.TopicSubscriber.subscribeTopic(TopicSubscriber.java:45)
 at org.huahsin.TopicSubscriber.main(TopicSubscriber.java:26)
Caused by: HornetQException[errorType=SECURITY_EXCEPTION message=HQ119032: User: huahsin68 doesnt have permission=CREATE_NON_DURABLE_QUEUE on address {2}]
 ... 10 more
This is the piece that does the job:
  try {
   ctx = new InitialContext(prop);
   TopicConnectionFactory topicFac = (TopicConnectionFactory) ctx.lookup("jms/RemoteConnectionFactory");
   topicConn = topicFac.createTopicConnection("huahsin68", "abcd");
   
   while(!receive) {
    TopicSession topicSess = topicConn.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
    Topic topic = (Topic) ctx.lookup("jms/topic/test");
    topicConn.start();
    
    javax.jms.TopicSubscriber subscriber = topicSess.createSubscriber(topic);
    TestMessageListener listener = new TestMessageListener();
    subscriber.setMessageListener(listener);
    
    Thread.sleep(5000);
    subscriber.close();
    topicSess.close();
   }
  }
  finally {
   if( topicConn != null ) {
    topicConn.close();
   }
  }
This sound like the security issue or permission configuration error. I'm sure everything have been configured properly, but I was not sure whether is there anything wrong with the security settings:
                ...

                <security-settings>
                    <security-setting match="#">
                        <permission type="send" roles="guest"/>
                        <permission type="consume" roles="guest"/>
                        <permission type="createNonDurableQueue" roles="guest"/>
                        <permission type="deleteNonDurableQueue" roles="guest"/>
                    </security-setting>
                </security-settings>
Wait a minute! This reminds me that the role assignment was missed out during the user creation. Did a quick check on application-roles.properties and found out the role was not assigned to user huahsin68.

This is what it shows on application-role.properties:
# The following illustrates how an admin user could be defined.
#
#admin=PowerUser,BillingAdmin,
#guest=guest
huahsin68=
Since the topic creation must have a guest role as configured in the security settings. Fill it up with a guest role to the user and then re-run the program, everything will be fine.

Thursday, August 6, 2015

Establishing remote connection to JBoss messaging service

Just done some test drive on establishing a remote connection to the JBoss messaging service. As of this writing, I'm working on JBoss EAP 6.3.0. Assume I have the connection factory configuration being done in following way:
   <jms-connection-factories>
      <connection-factory name="RemoteConnectionFactory">
         <connectors>
            <connector-ref connector-name="netty"/>
         </connectors>
         <entries>
            <entry name="RemoteConnectionFactory"/>
            <entry name="java:jboss/exported/jms/RemoteConnectionFactory"/>
         </entries>
      </connection-factory>
   <jms-connection-factories>

   ...
   ...

   <jms-destinations>
      <jms-topic name="testTopic">
         <entry name="topic/test"/>
         <entry name="java:jboss/exported/jms/topic/test"/>
      </jms-topic>

      ...
   </jms-destinations>
Then the following piece is the code trying to achieve the mission:
   ...

   Properties prop = new Properties();
   prop.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.naming.remote.client.InitialContextFactory");
   prop.put(Context.PROVIDER_URL, "remote://localhost:4447");
   prop.put(Context.SECURITY_PRINCIPAL, "huahsin68");
   prop.put(Context.SECURITY_CREDENTIALS, "abcdef.1");

   ctx = new InitialContext(prop);
   TopicConnectionFactory topicFac = (TopicConnectionFactory) ctx.lookup("/RemoteConnectionFactory");
   TopicConnection topicConn = topicFac.createTopicConnection();
   TopicSession topicSess = topicConn.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
   Topic topic = (Topic) ctx.lookup("/topic/test");
   topicConn.start();

   ...
There are a couple of mistakes here. First, the lookup(...) method will fail on connection factory initialization, RemoteConnectionFactory was unable to find. This error would be seen as:

Exception in thread "main" javax.naming.NameNotFoundException: RemoteConnectionFactory -- service jboss.naming.context.java.jboss.exported.RemoteConnectionFactory

Second is the authentication with SECURITY_PRINCIPAL and SECURITY_CREDENTIALS is not working during the context initialization. The authentication need to be done during the connection is first created, which is on createTopicConnection() method call.

Third mistake would be the /topic/test was unable to initialize too. The error is same as the first mistake. The fixes on the lookup(...) thing should prefix with jms. This following piece would be the complete set for the fixes:
   ...

   Properties prop = new Properties();
   prop.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.naming.remote.client.InitialContextFactory");
   prop.put(Context.PROVIDER_URL, "remote://localhost:4447");

   ctx = new InitialContext(prop);
   TopicConnectionFactory topicFac = (TopicConnectionFactory) ctx.lookup("jms/RemoteConnectionFactory");
   TopicConnection topicConn = topicFac.createTopicConnection("huahsin68", "abcdef.1");
   TopicSession topicSess = topicConn.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
   Topic topic = (Topic) ctx.lookup("jms/topic/test");
   topicConn.start();

   ...
Wonder why jms should put in the prefix? JBoss documentation did mention this:
Keep in mind that any jms-queue or jms-topic which needs to be accessed by a remote client needs to have an entry in the "java:jboss/exported" namespace. As with connection factories, if a jms-queue or jms-topic has an entry bound in the "java:jboss/exported" namespace a remote client would look it up using the text after "java:jboss/exported".