Monday, 15 September 2014

MULE FTP : Create Directory If Not Exist

FTP and SFTP endpoints of mule , does not create directory on the fly , if the directory does not exist at ftp location .
It throws error like this :
ERROR 2007-11-05 15:24:29,192 [connector.ftp.0.receiver.1] org.mule.impl.DefaultExceptionStrategy: Caught exception in Exception Strategy: Failed to change working directory to /IN. Ftp error: 550
java.io.IOException: Failed to change working directory to /IN. Ftp error: 550
        at org.mule.providers.ftp.FtpMessageReceiver.listFiles(FtpMessageReceiver.java:103)
        at org.mule.providers.ftp.FtpMessageReceiver.poll(FtpMessageReceiver.java:72)
        at org.mule.providers.PollingReceiverWorker.run(PollingReceiverWorker.java:47)
        at org.mule.impl.work.WorkerContext.run(WorkerContext.java:310)
        at edu.emory.mathcs.backport.java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:987)
        at edu.emory.mathcs.backport.java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:528)
        at java.lang.Thread.run(Thread.java:619) 
There is an Open Issue for this functionality .

To implement this functionality for FTP , we have to create a custom FTPDispatcher and integrate it in the mule ftp connector .


So first change mule ftp connector to have CustomFTPMessageDispatcher like this:
<ftp:connector name="ftp_con">
  <service-overrides dispatcherFactory="CustomFtpMessageDispatcherFactory"></service-overrides>
 </ftp:connector>
    <flow name="sftpExampleFlow1" doc:name="sftpExampleFlow1">
     
        <file:inbound-endpoint path="E:/ftp" responseTimeout="10000" doc:name="File"/>
        <ftp:outbound-endpoint host="localhost" port="21" responseTimeout="10000" doc:name="FTP" connector-ref="ftp_con"
        outputPattern="custom/path/myFile.txt" path="/home/ftp" 
        />
    </flow>
And here's the DispatcherFactory class .

import org.mule.api.MuleException;
import org.mule.api.endpoint.OutboundEndpoint;
import org.mule.api.transport.MessageDispatcher;
import org.mule.transport.ftp.FtpMessageDispatcherFactory;

public class CustomFtpMessageDispatcherFactory extends FtpMessageDispatcherFactory
{
 /** {@inheritDoc} */
    public MessageDispatcher create(OutboundEndpoint endpoint) throws MuleException
    {
        return new CustomFtpMessageDispatcher(endpoint);
    }
}


And here's the FTPMessageDispacther , which will first create a directory if the outputPattern has it .

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.net.ftp.FTPClient;
import org.mule.api.MuleEvent;
import org.mule.api.endpoint.OutboundEndpoint;
import org.mule.api.transport.DispatchException;
import org.mule.config.i18n.CoreMessages;
import org.mule.model.streaming.CallbackOutputStream;
import org.mule.transport.ConnectException;
import org.mule.transport.ftp.FtpConnector;
import org.mule.transport.ftp.FtpMessageDispatcher;

public class CustomFtpMessageDispatcher extends FtpMessageDispatcher
{

 Log logger = LogFactory.getLog(CustomFtpMessageDispatcher.class);

 public CustomFtpMessageDispatcher(OutboundEndpoint endpoint)
 {
  super(endpoint);

 }

 protected void doDispatch(MuleEvent event) throws Exception
 {
  Object data = event.getMessage().getPayload();
  String outputPattern = (String) endpoint.getProperty(FtpConnector.PROPERTY_OUTPUT_PATTERN);
  String basePath = endpoint.getEndpointURI().getPath();
  OutputStream out = null;
  if (basePath.endsWith("/"))
   basePath = basePath.substring(0, basePath.length() - 1);

  if (outputPattern != null && outputPattern.contains("/"))
  {
   try
   {
    if (outputPattern.startsWith("/"))
     outputPattern = outputPattern.substring(1, outputPattern.length());
    
    String dirs[] = outputPattern.split("/", -1);
    final FtpConnector connector = (FtpConnector) endpoint.getConnector();
    final FTPClient client = connector.getFtp(endpoint.getEndpointURI());
    for (int i = 0; i < dirs.length - 1; i++)
    {
     try
     {
      if (!dirs[i].isEmpty())
      {
       basePath = basePath + "/" + dirs[i];
       if (!client.changeWorkingDirectory(basePath))
        client.makeDirectory(basePath);
      }

     } catch (Exception e)
     {
      logger.error("Error Creating dir on ftp" + e.getMessage());
     }
    }
    
    String filename = dirs[dirs.length - 1];
    out = client.storeFileStream(filename);
    if (out == null)
    {
     throw new IOException("FTP operation failed: " + client.getReplyString());
    }

    out = new CallbackOutputStream(out, new CallbackOutputStream.Callback()
    {
     public void onClose() throws Exception
     {
      try
      {
       if (!client.completePendingCommand())
       {
        client.logout();
        client.disconnect();
        throw new IOException("FTP Stream failed to complete pending request");
       }
      } finally
      {
       connector.releaseFtp(endpoint.getEndpointURI(), client);
      }
     }
    });
   }
   catch (ConnectException ce)
         {
             // Don't wrap a ConnectException, otherwise the retry policy will not go into effect.
             throw ce;
         }
         catch (Exception e)
         {
             throw new DispatchException(CoreMessages.streamingFailedNoStream(), event, (OutboundEndpoint)endpoint, e);
         }

  } 
  else
  {
   out = connector.getOutputStream(getEndpoint(), event);
  }

  try
  {
   if (data instanceof InputStream)
   {
    InputStream is = ((InputStream) data);
    IOUtils.copy(is, out);
    is.close();
   } else
   {
    byte[] dataBytes;
    if (data instanceof byte[])
    {
     dataBytes = (byte[]) data;
    } else
    {
     dataBytes = data.toString().getBytes(event.getEncoding());
    }
    IOUtils.write(dataBytes, out);
   }
  } finally
  {
   out.close();
  }
 }

}


Post Comments And Suggestions !!!


Friday, 12 September 2014

COLOURIZED LOGGING IN RUBY(IRB) PROMPT

Wirble is a set of enhancements for ruby(irb). Wirble enables several items mentioned on the RubyGarden "Irb Tips and Tricks" page, including tab-completion, history, and a built-in ri command, as well as colorized results and a couple other goodies.

Wirble even works with rvm , lets hack the trick to do so:

Step 1:
When we start irb prompt it first checks for .irbrc file in home folder. ~/.irbrc.

Step 2 :
To enable wirble in irb prompt, Open the ~/.irbrc file (Create a new one if Not present.), and Paste the contents of the below code.
require 'irb/completion'
 require 'irb/ext/save-history'
 require 'rubygems'
 unless Gem::Specification.find_all_by_name('wirble').any?
   puts "Installing Wirble"
   %x{gem install 'wirble' --no-ri --no-rdoc}
 end
 Gem.refresh 
 require 'wirble'
# Initializing Wirble
Wirble.init
Wirble.colorize
# Customize according to your will.
colors = Wirble::Colorize.colors.merge({
  :object_class => :purple,
  :symbol => :purple,
  :symbol_prefix => :purple
})
Wirble::Colorize.colors = colors

Step 3:
Move out of the blog for a colourfull irb prompt and Njoy Coding in Ruby. Thanks to Santosh for writing this post .



Tuesday, 2 September 2014

Mule SFTP : Verify false Error

The following error might occur while using SFTP inbound or outbound endpoint in mule :
Error during login to x@192.168.2.18: verify: false
java.io.IOException: Error during login to x@192.168.2.18: verify: false
 at org.mule.transport.sftp.SftpClient.logAndThrowLoginError(SftpClient.java:200)
 at org.mule.transport.sftp.SftpClient.login(SftpClient.java:146)
 at org.mule.transport.sftp.SftpConnectionFactory.createClient(SftpConnectionFactory.java:98)
 at org.mule.transport.sftp.SftpConnector.createSftpClient(SftpConnector.java:191)
 at org.mule.transport.sftp.SftpConnector.createSftpClient(SftpConnector.java:174)
 at org.mule.transport.sftp.SftpReceiverRequesterUtil.getAvailableFiles(SftpReceiverRequesterUtil.java:75)
 at org.mule.transport.sftp.SftpMessageReceiver.poll(SftpMessageReceiver.java:62)
 at org.mule.transport.AbstractPollingMessageReceiver.performPoll(AbstractPollingMessageReceiver.java:219)
 at org.mule.transport.PollingReceiverWorker.poll(PollingReceiverWorker.java:84)
 at org.mule.transport.PollingReceiverWorker.run(PollingReceiverWorker.java:53)
 at org.mule.work.WorkerContext.run(WorkerContext.java:311)
 at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
 at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
 at java.lang.Thread.run(Thread.java:722)
Mule SFTP uses JSch to connect to SFTP location . This error occurs with particular Java JDK updates . You might get this error If you are using following versions of jdk :
java7u6
java7u7
java7u15
This error does not occur if we use JDK version < java7u6 .

For more information please read this link.

Post Comments And Suggestions !!


Wednesday, 20 August 2014

JAXB Error : FWK005 parse may not be called while parsing

org.xml.sax.SAXException: FWK005 parse may not be called while parsing.
Above Error occurs because you might have SchemaFactory instance , which is shared by multiple threads. Like declaring it at class level , and using it in methods .
private SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
The SchemaFactory is not thread safe . It should always be initialized and accessed in local scope. So whenever you need SchemaFactory instance , just create it locally instead of using it at instance level.


Post Comments And Suggestions !!


Tuesday, 19 August 2014

How To Link Git Tag with Rails app

I use Git tags to manage the version numbers of my Rails apps.

Every time a new version is ready, I tag the current commit like this :
git tag -a v1.10 -m "FIXED PC-43/67/78"
I have created a ruby file in initializers which defines a constant to hold this information (in this case “v1.10”):
APP_VERSION = `git describe --always` unless defined? APP_VERSION
This constant simply contains the output of Git describe.
Now I can use it anywhere in my app where I would like to display the version number.

This post is written by Santosh.

Post Comments And Suggestions

Sunday, 17 August 2014

How to Print Full Stack Trace In Mule Flow

To print full exception stack trace in mule , you need to add a grrovy scripting element like this :
<?xml version="1.0" encoding="UTF-8"?>

<mule xmlns:scripting="http://www.mulesoft.org/schema/mule/scripting"
 xmlns:http="http://www.mulesoft.org/schema/mule/http" xmlns="http://www.mulesoft.org/schema/mule/core" xmlns:doc="http://www.mulesoft.org/schema/mule/documentation" xmlns:spring="http://www.springframework.org/schema/beans" version="CE-3.3.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="
http://www.mulesoft.org/schema/mule/scripting http://www.mulesoft.org/schema/mule/scripting/current/mule-scripting.xsd 
http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd 
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-current.xsd 
http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd ">
    
    <flow name="muleMavenSampleFlow1" doc:name="muleMavenSampleFlow1">
        <http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8081" doc:name="HTTP"/>
        <catch-exception-strategy doc:name="Catch Exception Strategy">
         <scripting:transformer doc:name="Print StackTrace">
    <scripting:script engine="Groovy">
                    <scripting:text><![CDATA[org.apache.log4j.Logger.getLogger("").error("Error Trace is : \n",exception)]]></scripting:text>
    </scripting:script>
   </scripting:transformer>
        </catch-exception-strategy>
       
    </flow>
</mule>

Post Comments And Suggestions !!



Wednesday, 16 July 2014

Mule Cron Job : Job Name Can Not be Empty Error

Writing cron job is very easy in mule.You might get error like this in mule application start up :
Caused by: org.mule.api.lifecycle.LifecycleException: Failed to start inbound endpoint "endpoint.quartz.test.job"
 at org.mule.endpoint.DefaultInboundEndpoint.start(DefaultInboundEndpoint.java:122)
 at org.mule.construct.AbstractFlowConstruct.startIfStartable(AbstractFlowConstruct.java:317)
 at org.mule.construct.AbstractPipeline.doStart(AbstractPipeline.java:302)
 at org.mule.construct.AbstractFlowConstruct$2.onTransition(AbstractFlowConstruct.java:143)
 at org.mule.construct.AbstractFlowConstruct$2.onTransition(AbstractFlowConstruct.java:139)
 at org.mule.lifecycle.AbstractLifecycleManager.invokePhase(AbstractLifecycleManager.java:141)
 at org.mule.construct.FlowConstructLifecycleManager.fireStartPhase(FlowConstructLifecycleManager.java:95)
 at org.mule.construct.AbstractFlowConstruct.start(AbstractFlowConstruct.java:138)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
 at java.lang.reflect.Method.invoke(Method.java:601)
 at org.mule.lifecycle.phases.DefaultLifecyclePhase.applyLifecycle(DefaultLifecyclePhase.java:225)
 at org.mule.lifecycle.RegistryLifecycleManager$RegistryLifecycleCallback.onTransition(RegistryLifecycleManager.java:276)
 at org.mule.lifecycle.RegistryLifecycleManager.invokePhase(RegistryLifecycleManager.java:155)
 at org.mule.lifecycle.RegistryLifecycleManager.fireLifecycle(RegistryLifecycleManager.java:126)
 at org.mule.registry.AbstractRegistryBroker.fireLifecycle(AbstractRegistryBroker.java:80)
 at org.mule.registry.MuleRegistryHelper.fireLifecycle(MuleRegistryHelper.java:120)
 at org.mule.lifecycle.MuleContextLifecycleManager$MuleContextLifecycleCallback.onTransition(MuleContextLifecycleManager.java:94)
 at org.mule.lifecycle.MuleContextLifecycleManager$MuleContextLifecycleCallback.onTransition(MuleContextLifecycleManager.java:90)
 at org.mule.lifecycle.MuleContextLifecycleManager.invokePhase(MuleContextLifecycleManager.java:72)
 at org.mule.lifecycle.MuleContextLifecycleManager.fireLifecycle(MuleContextLifecycleManager.java:64)
 at org.mule.DefaultMuleContext.start(DefaultMuleContext.java:250)
 at org.mule.module.launcher.application.DefaultMuleApplication.start(DefaultMuleApplication.java:151)
 ... 4 more
Caused by: org.mule.api.lifecycle.LifecycleException: Failed to start Quartz receiver
 at org.mule.lifecycle.AbstractLifecycleManager.invokePhase(AbstractLifecycleManager.java:156)
 at org.mule.transport.ConnectableLifecycleManager.fireStartPhase(ConnectableLifecycleManager.java:51)
 at org.mule.transport.AbstractTransportMessageHandler.start(AbstractTransportMessageHandler.java:318)
 at org.mule.transport.AbstractConnector.registerListener(AbstractConnector.java:1259)
 at org.mule.endpoint.DefaultInboundEndpoint.start(DefaultInboundEndpoint.java:108)
 ... 27 more
Caused by: org.mule.api.endpoint.EndpointException: Failed to start Quartz receiver
 at org.mule.transport.quartz.QuartzMessageReceiver.doStart(QuartzMessageReceiver.java:195)
 at org.mule.transport.AbstractMessageReceiver.doStartHandler(AbstractMessageReceiver.java:484)
 at org.mule.transport.AbstractTransportMessageHandler$3.onTransition(AbstractTransportMessageHandler.java:322)
 at org.mule.lifecycle.AbstractLifecycleManager.invokePhase(AbstractLifecycleManager.java:141)
 ... 31 more
Caused by: java.lang.IllegalArgumentException: Job name cannot be empty.
 at org.quartz.JobDetail.setName(JobDetail.java:192)
 at org.mule.transport.quartz.QuartzMessageReceiver.doStart(QuartzMessageReceiver.java:95)
 ... 34 more

Here's the xml file :
<?xml version="1.0" encoding="UTF-8"?>

<mule xmlns:quartz="http://www.mulesoft.org/schema/mule/quartz" xmlns="http://www.mulesoft.org/schema/mule/core" xmlns:doc="http://www.mulesoft.org/schema/mule/documentation" xmlns:spring="http://www.springframework.org/schema/beans" version="CE-3.3.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="
http://www.mulesoft.org/schema/mule/quartz http://www.mulesoft.org/schema/mule/quartz/current/mule-quartz.xsd 
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-current.xsd 
http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd ">
    <flow name="crontestFlow1" doc:name="crontestFlow1">
        <quartz:inbound-endpoint jobName="test_job" cronExpression="0 0/100 * * * ?" responseTimeout="10000" doc:name="Price File Report Quartz Job" >
   <quartz:event-generator-job>
   </quartz:event-generator-job>
  </quartz:inbound-endpoint>
        <logger level="INFO" doc:name="Logger"/>
    </flow>
</mule>

Notice that your jobName is not empty . The issue is with underscore . you can not have underscore in jobName property. Just remove underscore from jobName and it will run fine.You can not have white space characters in job name either

Here's the bug.

Post Comments And Suggestions !!