Monday, July 20, 2015

Cannot use javahl nor command line svn client

I do not know since when the 3 idiots svnant.jar, svnClientAdapter.jar, svnjavahl.jar was placed inside ANT_ROOT/lib? I'm feeling so unhappy with this as it has caused me a nasty shit being thrown when <svn> tag was invoked!
    Trying to override old definition of task svn
    
    BUILD FAILED
    ...
    C:\TestWorkspace\base.xml:78: Cannot use javahl nor command line svn client
    
    Total time: 0 seconds
When I was about to throw them away, I notice the last modified date was at 2006 which is version 1.0.0 as according to the source repo. Surprise me! But I thought I had overridden the classpath in ANT script, why it isn’t working?
    <path id="classpath">
     <pathelement location="svnant.jar"/>
     <pathelement location="svnClientAdapter.jar"/>
     <pathelement location="svnjavahl.jar"/>
     <pathelement location="svnkit.jar"/>
     <pathelement location="ant-contrib-0.3.jar"/>
     <fileset dir= ".." >
      <include name= "*.jar" />
     </fileset>
    </path>
I rebuild again to see if the error still persists after I throw the 3 idiots far far far away. The error is gone but another one comes out:
    co:
          [svn] Missing 'javahl' dependencies on the classpath !
    
    BUILD FAILED
    ...
    C:\TestWorkspace\base.xml:80: Cannot find javahl, svnkit nor command line svn client
Surprise me again! Why this happens? Spent some time reading through the forums and articles then only I realize there are missing thing in the ANT script:
    <svnSetting svnkit="true" javahl="false" username="admin" password="admin" id="svn.settings" />
    <svn refid="svn.settings">
     ...
    </svn>
Frankly speaking, I heavily rely on the IDE. The <svn> tag wasn’t shown in editor, and I though this is a fault. Anyhow, one quick note, as of this writing, I’m using version 1.3.1. Thus svntask.properties is no longer working:

    <typedef classpathref="classpath" resource="svntask.properties"/>

That one was used in version 1.0.0. The correct way is this:

    <typedef resource="org/tigris/subversion/svnant/svnantlib.xml" classpathref="classpath"/>

Sunday, July 19, 2015

Infinite loop in Filter after sendRedirect()

My intention is to redirect to another site whenever the User-Agent has detected the mobile keyword. I have a solution for this approach where I have the file name for mobile version start with m and reside at the location same as desktop version. I try not to branch out another path for mobile version to keep maintenance easy.

Unfortunately the Filter call was unintentionally looping on itself. This seems to me that for every new redirection Filter call, the mobile keyword validation will get invoked and the new redirection is sent again. And this process will go on endlessly. This is so not good, I was trapped!

This is what happened on my code:
 @Override
 public void doFilter(ServletRequest request, ServletResponse response,
   FilterChain chain) throws IOException, ServletException {

  HttpServletRequest httpServletRequest = (HttpServletRequest) request;
  HttpServletResponse httpServletResponse = (HttpServletResponse) response;

  if( httpServletRequest.getHeader("User-Agent").indexOf("Mobile") != -1 ) {
   
   httpServletResponse.sendRedirect(httpServletRequest.getContextPath() + "/m" + httpServletRequest.getRequestURI().substring(httpServletRequest.getRequestURI().lastIndexOf("/")+1, httpServletRequest.getRequestURI().length()));
  }
  else {  
   chain.doFilter(request, response);
  }
According to the advice from expert. I'm going to need additional validation to stop the process after I reach to that URI. Thus, what I need to do is to put additional validation as below:
 @Override
 public void doFilter(ServletRequest request, ServletResponse response,
   FilterChain chain) throws IOException, ServletException {

  HttpServletRequest httpServletRequest = (HttpServletRequest) request;
  HttpServletResponse httpServletResponse = (HttpServletResponse) response;

  if( httpServletRequest.getHeader("User-Agent").indexOf("Mobile") != -1 ) {

   // stop redirect if the site has reach
   if( httpServletRequest.getRequestURI().equalsIgnoreCase(httpServletRequest.getContextPath() + "/" + httpServletRequest.getRequestURI().substring(httpServletRequest.getRequestURI().lastIndexOf("/")+1, httpServletRequest.getRequestURI().length()))) {
    chain.doFilter(request, response);
   }
   else {
    httpServletResponse.sendRedirect(httpServletRequest.getContextPath() + "/m" + httpServletRequest.getRequestURI().substring(httpServletRequest.getRequestURI().lastIndexOf("/")+1, httpServletRequest.getRequestURI().length()));
   }
  }
  else {  
   chain.doFilter(request, response);
  }
Tested and worked as expected. I did also tried to forward the request as shown below:
 @Override
 public void doFilter(ServletRequest request, ServletResponse response,
   FilterChain chain) throws IOException, ServletException {

  HttpServletRequest httpServletRequest = (HttpServletRequest) request;
  HttpServletResponse httpServletResponse = (HttpServletResponse) response;

  if( httpServletRequest.getHeader("User-Agent").indexOf("Mobile") != -1 ) {
   
   request.getRequestDispatcher("m" + httpServletRequest.getRequestURI().substring(httpServletRequest.getRequestURI().lastIndexOf("/")+1, httpServletRequest.getRequestURI().length())).forward(request, response);
  }
  else {  
   chain.doFilter(request, response);
  }
I find this working as well but for subsequent call on doFilter, the httpServletRequest.getRequestURI() will always stuck on the old URI. I think this is due to the reason URL is forward on server site, but not reflected on client site.

Saturday, July 18, 2015

Service service jboss.ejb.default-resource-adapter-name-service not found

The default JBoss configuration in standalone.xml doesn't support messaging service. Following changes are needed in order to enable messaging service.

1. Add messaging extension.
    <extensions>
        ...
        <extension module="org.jboss.as.messaging"/>
    </extensions>

2. Add messaging subsystem.
        <subsystem xmlns="urn:jboss:domain:messaging:1.1">
            <hornetq-server>
                <persistence-enabled>true</persistence-enabled>
                <journal-file-size>102400</journal-file-size>
                <journal-min-files>2</journal-min-files>

                <connectors>
                    <netty-connector name="netty" socket-binding="messaging"/>
                    <netty-connector name="netty-throughput" socket-binding="messaging-throughput">
                        <param key="batch-delay" value="50"/>
                    </netty-connector>
                    <in-vm-connector name="in-vm" server-id="0"/>
                </connectors>

                <acceptors>
                    <netty-acceptor name="netty" socket-binding="messaging"/>
                    <netty-acceptor name="netty-throughput" socket-binding="messaging-throughput">
                        <param key="batch-delay" value="50"/>
                        <param key="direct-deliver" value="false"/>
                    </netty-acceptor>
                    <in-vm-acceptor name="in-vm" server-id="0"/>
                </acceptors>

                <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>

                <address-settings>
                    <address-setting match="#">
                        <dead-letter-address>jms.queue.DLQ</dead-letter-address>
                        <expiry-address>jms.queue.ExpiryQueue</expiry-address>
                        <redelivery-delay>0</redelivery-delay>
                        <max-size-bytes>10485760</max-size-bytes>
                        <address-full-policy>BLOCK</address-full-policy>
                        <message-counter-history-day-limit>10</message-counter-history-day-limit>
                    </address-setting>
                </address-settings>

                <jms-connection-factories>
                    <connection-factory name="InVmConnectionFactory">
                        <connectors>
                            <connector-ref connector-name="in-vm"/>
                        </connectors>
                        <entries>
                            <entry name="java:/ConnectionFactory"/>
                        </entries>
                    </connection-factory>
                    <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>
                    <pooled-connection-factory name="hornetq-ra">
                        <transaction mode="xa"/>
                        <connectors>
                            <connector-ref connector-name="in-vm"/>
                        </connectors>
                        <entries>
                            <entry name="java:/JmsXA"/>
                        </entries>
                    </pooled-connection-factory>
                </jms-connection-factories>

                <jms-destinations>
                    <jms-queue name="testQueue">
                        <entry name="queue/test"/>
                        <entry name="java:jboss/exported/jms/queue/test"/>
                    </jms-queue>
                    <jms-topic name="testTopic">
                        <entry name="topic/test"/>
                        <entry name="java:jboss/exported/jms/topic/test"/>
                    </jms-topic>
                </jms-destinations>
            </hornetq-server>
        </subsystem>

3. Bind the socket.
    <socket-binding-group name="standard-sockets" default-interface="public" port-offset="${jboss.socket.binding.port-offset:0}">
        ...

        <socket-binding name="messaging" port="5445"/>
        <socket-binding name="messaging-throughput" port="5455"/>
    </socket-binding-group>

4. Get ready the MDB.
@MessageDriven(name="MessageMDBSample", activationConfig ={
  @ActivationConfigProperty(propertyName="destination", propertyValue="queue/test"),
  @ActivationConfigProperty(propertyName="destinationType", propertyValue="javax.jms.Queue"),
  @ActivationConfigProperty(propertyName="acknowledgeMode", propertyValue="Auto-acknowledge")
})
public class MDBSample implements MessageListener {

 @Override
 public void onMessage(Message msg) {
  ...
  ...
 }
}
OK, I'm done with all the setup. But when I startup the server, I hit following error. Why?
19:36:34,742 ERROR [org.jboss.msc.service.fail] (MSC service thread 1-5) MSC000001: Failed to start service jboss.deployment.unit."web2.war".PARSE: org.jboss.msc.service.StartException in service jboss.deployment.unit."web2.war".PARSE: JBAS018733: Failed to process phase PARSE of deployment "web2.war"
 at org.jboss.as.server.deployment.DeploymentUnitPhaseService.start(DeploymentUnitPhaseService.java:166) [jboss-as-server-7.4.0.Final-redhat-19.jar:7.4.0.Final-redhat-19]
 at org.jboss.msc.service.ServiceControllerImpl$StartTask.startService(ServiceControllerImpl.java:1980) [jboss-msc-1.1.5.Final-redhat-1.jar:1.1.5.Final-redhat-1]
 at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1913) [jboss-msc-1.1.5.Final-redhat-1.jar:1.1.5.Final-redhat-1]
 at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110) [rt.jar:1.7.0]
 at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603) [rt.jar:1.7.0]
 at java.lang.Thread.run(Thread.java:722) [rt.jar:1.7.0]
Caused by: org.jboss.msc.service.ServiceNotFoundException: Service service jboss.ejb.default-resource-adapter-name-service not found
 at org.jboss.msc.service.ServiceContainerImpl.getRequiredService(ServiceContainerImpl.java:625) [jboss-msc-1.1.5.Final-redhat-1.jar:1.1.5.Final-redhat-1]
 at org.jboss.as.ejb3.deployment.processors.MessageDrivenComponentDescriptionFactory.getDefaultResourceAdapterName(MessageDrivenComponentDescriptionFactory.java:278)
 at org.jboss.as.ejb3.deployment.processors.MessageDrivenComponentDescriptionFactory.processMessageBeans(MessageDrivenComponentDescriptionFactory.java:155)
 at org.jboss.as.ejb3.deployment.processors.MessageDrivenComponentDescriptionFactory.processAnnotations(MessageDrivenComponentDescriptionFactory.java:82)
 at org.jboss.as.ejb3.deployment.processors.AnnotatedEJBComponentDescriptionDeploymentUnitProcessor.processAnnotations(AnnotatedEJBComponentDescriptionDeploymentUnitProcessor.java:58)
 at org.jboss.as.ejb3.deployment.processors.AbstractDeploymentUnitProcessor.deploy(AbstractDeploymentUnitProcessor.java:81)
 at org.jboss.as.server.deployment.DeploymentUnitPhaseService.start(DeploymentUnitPhaseService.java:159) [jboss-as-server-7.4.0.Final-redhat-19.jar:7.4.0.Final-redhat-19]
 ... 5 more
But later I found out that I was missing this:
        <subsystem xmlns="urn:jboss:domain:ejb3:1.4">
            <mdb>  
                <resource-adapter-ref resource-adapter-name="hornetq-ra"/>  
                <bean-instance-pool-ref pool-name="mdb-strict-max-pool"/>  
            </mdb>
        </subsystem>
Apologize on my silly mistake.

Tuesday, July 14, 2015

Continuous build on Message Flow with Jenkin 2

Not long ago, I’d done it once, but failed. That was happened on past 2 months ago. But now he is back again. Thanks to my colleague on his effort to discover this feature. This round ANT is used in the mission. First we try on this approach:
    < target name="create_bar">
     <mkdir dir="${dist.path}"/>
     <exec dir="." executable="C:/Program Files (x86)/IBM/WMBT800/mqsicreatebar.exe" failonerror="false" >
      <redirector output="error.log" alwayslog="true"/>     
      <arg line="-data . "/>
      <arg line="-b ProjectA/BARs/ProjectA.bar"/> 
      <arg line="-cleanBuild"/>
      <arg line="-l ProjectA"/> 
     </exec> 
    </target>
Pay attention on the argument –data and –b, the value might be different depends on the file structure. For my case, I put the build.xml inside the project folder. There is a con on this approach where it takes approximately 3 minutes to complete a build. Why does it take so long? The text below was extract from this document for easy reference.

3.2 Execution time It will be noted that when the BAR file is built from the command line, the time taken is often noticeably longer than time taken when built from the WMB ToolKit. This is because the mqsicreatebar command actually runs the Eclipse client itself in a 'headless' mode. The Eclipse front end probably keeps track of various file names, project references and lots of other parameters that speeds up the build time. As this does not happen from command line, the time taken is noticeably longer.
The second approach we did was this:
    < target name="package_bar">
     <mkdir dir="${dist.path}"/>
     <java classname="com.ibm.broker.config.appdev.FlowRendererBAR" failonerror="true" fork="true">
      <arg line="-a ${dist.path}/ProjectA.bar"/>
      <arg line="-w ../"/>
      <arg line="-y commonJava commonESQL ProjectA"/>
      <classpath>
       <fileset dir="C:/Program Files/IBM/MQSI/8.0.0.3/classes">
        <include name="*.jar"/>
       </fileset>
      </classpath>
     </java>
    </target>
With this approach, the execution time is damn fast. I’m feeling much better with this approach.

Reference resource

Friday, July 10, 2015

Detecting web's mobile version with Filter

What a boring day, while I was dreaming on my desk, something has caught my attention. I realize that in most of the time, my web application was run on desktop platform, and never know what would happen if I run the it on mobile platform? I was thinking this could be a disaster for user. But how? Could I do the validation checking in controller bean? Just like this:
If mobile device then render mobile site otherwise render desktop site.
But in reality, what I got from the Internet majority are done using JavaScript, some use CSS to accomplished the task. But this doesn't help because mine technology used was JSF and J2EE stuff. Thus I would use Filter for my case. See my action on following content:
package org.huahsin;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebFilter(filterName="MyFilter", urlPatterns={"/pages/*", "*.xhtml"})
public class MyFilter implements Filter {

 @Override
 public void init(FilterConfig filterConfig) throws ServletException {
  // TODO Auto-generated method stub

 }

 @Override
 public void doFilter(ServletRequest request, ServletResponse response,
   FilterChain chain) throws IOException, ServletException {
  // TODO Auto-generated method stub
  
  HttpServletRequest httpServletRequest = (HttpServletRequest) request;
  HttpServletResponse httpServletResponse = (HttpServletResponse) response;
  
  // redirect to mobile version
  if( httpServletRequest.getHeader("User-Agent").indexOf("Mobile") != -1 ) {
    ...
    ...
  }
  else {  
   chain.doFilter(request, response);  // forward to original request
  }
 }

 @Override
 public void destroy() {
  // TODO Auto-generated method stub

 }

}
This code will easily know where does the request come from. I'm so curious to know what is actually hiding in User-Agent? Did a quick diagnose on it and found the following string will be retrieve when the site was render on desktop browser:
Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:38.0) Gecko/20100101 Firefox/38.0
And this is the string I got if I render the site on iPad:
Mozilla/5.0 (iPad; CPU OS 8_3 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12F69 Safari/600.1.4

Wednesday, July 8, 2015

How to open access to public in JBoss?

Ever wonder why I can only access my web application from localhost in JBoss? Why I could not access it from other devices, such as mobile phone, tablet, and even other PC? I think this is due to the default configuration when JBoss was first setup:
    < interfaces>
        <interface name="management">
            <inet-address value="${jboss.bind.address.management:127.0.0.1}"/>
        </interface>
        <interface name="public">
            <inet-address value="${jboss.bind.address:127.0.0.1}"/>
        </interface>
        <interface name="unsecure">
            <inet-address value="${jboss.bind.address.unsecure:127.0.0.1}"/>
        </interface>
    </interfaces>
A minor change is require to open access from public. What I did was to replace the <inet-address ... /> with <any-ipv4-address> in <interface name="public">.
    <interfaces>
        <interface name="management">
            &lt inet-address value="${jboss.bind.address.management:127.0.0.1}"/>
        </interface>
        <interface name="public">
            <any-ipv4-address/>
        </interface>
        <interface name="unsecure">
            <inet-address value="${jboss.bind.address.unsecure:127.0.0.1}"/>
        </interface>
    </interfaces>
Hey! What is unsecure by the way? Feeling uncomfortable with the word.

Saturday, July 4, 2015

Reading Message Broker property value has cause memory leak

This is my first time encountering memory leak happened in Java code. I’m feeling so ridiculous about this because I always believe that Java is a language that I should not worry about memory leak. There is one web service I was working on have spotted an abnormal behaviour usage and eventually will force the Execution Group stop functioning. This abnormal behaviour is hard to spot on my own until I run a load test on it (the load test was execute with SOAP UI).

But later have found out the root cause was happened when reading the properties values from configurable service defined in Message Broker. As according to the documentation, whenever reading the properties values with BrokerProxy as shown in the following code, it is advisable to invoke brokerProxy.disconnect() to free up resources, otherwise the memory will keep piling up causing memory leaks.
    public class JavaNode extends MbJavaComputeNode {
    
     @Override
     public void evaluate(MbMessageAssembly inAssembly) throws MbException
     {
      BrokerProxy brokerProxy;
      try {
       brokerProxy = BrokerProxy.getLocalInstance();
       brokerProxy.getConfigurableService("USERDEFINED", "key");
      } catch (ConfigManagerProxyLoggedException e1) {
       // TODO Auto-generated catch block
       e1.printStackTrace();
      } catch (ConfigManagerProxyPropertyNotInitializedException e) {
       // TODO Auto-generated catch block
       e.printStackTrace();
      }
    
      ...
     }
    }

Thus what I did is to invoke the disconnect() in finally clause. But have to be aware that after the resources had been freed, brokerProxy will no longer usable and have to be renew. Below are some useful resources I have read in solving the issue:
  1. Important facts about garbage collection in WebSphere Message Broker
  2. Class BrokerProxy
  3. Connecting to a broker from a CMP application