Tuesday, August 26, 2014

Embarassing pastes and how to avoid them

The other day my manager asked me in a work chatroom for a link to some tool. I went look for it and pasted it in the chat room. To my embarrassment, my "copy" step didn't take effect so I pasted some randomly link I had previously copied and it turned out to be a link to a silly image. It could have been worse though.

So how to avoid this situation? You can always carefully read and check what you type but sometimes your finger is fast to hit enter. I've decided to write a Windows desktop app that will clear out the clipboard buffer if the text has been in there after some amount of time, ie. 1 minute. If you have an image paste, it will leave it alone.

There is also an option to recover what was cleared out so you'll never lose anything precious. The paste timeout is configurable also. The app was developed with Visual Studio 2013 for Desktop, written in C#.

Here it is if you want to try it out: ClearPaste

Monday, May 27, 2013

Weird case of org.apache.openejb:javaee-api:5.0-2: Javamail mail.smtp.host is ignored

I've just run into very odd bug. I was setting up a verify simple test case for sending gmail with Javamail
        Properties props = new Properties();
        props.put("mail.smtp.auth", "true");
        props.put("mail.smtp.port", "465");
        props.put("mail.smtp.ssl.enable", "true");
        props.put("mail.smtp.host", "smtp.gmail.com");
        props.put("mail.debug", "true");
        Session session = Session.getInstance(props,
                new javax.mail.Authenticator() {
                    protected PasswordAuthentication getPasswordAuthentication() {
                        return new PasswordAuthentication("xxx", "xxx");
                    }
                });
        try {
            Message message = new MimeMessage(session);
            message.setFrom(new InternetAddress("xxx@gmail.com"));
            message.setRecipients(Message.RecipientType.TO,
                    InternetAddress.parse("xxx@gmail.com"));
            message.setSubject("Test Subject");
            message.setText("Test message");
            Transport.send(message);
            System.out.println("Sent");

        } catch (MessagingException e) {
            throw new RuntimeException(e);
        }
Despite the "mail.smtp.host" setting, the thing decided to connect to "localhost" instead
java.lang.RuntimeException: javax.mail.SendFailedException: 
Send failure 
(javax.mail.MessagingException: Could not connect to SMTP host: localhost, port: 465 
(java.net.ConnectException: Connection refused: connect))
        at java.net.DualStackPlainSocketImpl.connect0(Native Method)
        at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:69)
        at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:339)
        at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:200)
        at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:182)
        at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:157)
        at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:391)
        at java.net.Socket.connect(Socket.java:579)
        at java.net.Socket.connect(Socket.java:528)
        at com.sun.mail.util.SocketFetcher.createSocket(SocketFetcher.java:321)
        at com.sun.mail.util.SocketFetcher.getSocket(SocketFetcher.java:237)
        at com.sun.mail.smtp.SMTPTransport.openServer(SMTPTransport.java:1927)
        at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:654)
        at javax.mail.Service.connect(Service.java:254)
        at javax.mail.Service.connect(Service.java:85)
        at javax.mail.Service.connect(Service.java:70)
        at javax.mail.Transport.send(Transport.java:94)
        at javax.mail.Transport.send(Transport.java:48)
        at org.quartz.jobs.SendMailJobTest.testSendMail(SendMailJobTest.java:71)
My classpath had both org.apache.openejb:javaee-api:5.0-2 and javax.mail:mail:1.4.7 on it. The javaee-api was there as provided scope for compilation and the java.mail was there with test scope. Searching the web for answers didn't come up with anything so I decided to remove javaee-api and voila, everything worked from then on. That was a wild goose chase. I have to note that the latest javaee-api:5.0-3 or javaee-api:6.0-5 don't seem to contain that bug. It's good be up to date.

Monday, April 16, 2012

Interrupt a Quartz job that doing IO

If you want the ability to interrupt a Quartz job that is doing IO, it's possible if you make use of InterruptibleChannel.

This is the quote from Oracle link above:

A channel that implements this interface is also interruptible: If a thread is blocked in an I/O operation on an interruptible channel then another thread may invoke the blocked thread's interrupt method. This will cause the channel to be closed, the blocked thread to receive a ClosedByInterruptException, and the blocked thread's interrupt status to be set.

As it turns out, you can create channel easily from a stream, socket, or a pipe which already implements InterruptibleChannel interface.

So the plan is to get the reference to the executing thread of your own job upon entry and save it for later use. When Quartz scheduler interrupts the job, you could then call interrupt() method on that thread to stop the read/write action.

Here's a simple example of such job: downloading a big file

package demo;

// import statements excluded for brevity

public class MyJob implements InterruptableJob {

  private static Logger    LOG              = LoggerFactory.getLogger(MyJob.class);

  private volatile boolean isJobInterrupted = false;

  private JobKey           jobKey           = null;

  private volatile Thread  thisThread;

  public MyJob() {
  }

  public void execute(JobExecutionContext context) throws JobExecutionException {
    thisThread = Thread.currentThread();
    LOG.info("Thread name of the current job: " + thisThread.getName());

    jobKey = context.getJobDetail().getKey();
    LOG.info("Job " + jobKey + " executing at " + new Date());

    try {
      String fileUrl = "http://d2zwv9pap9ylyd.cloudfront.net/terracotta-3.6.1.tar.gz"; // 59 MB
      String localFile = "terracotta-3.6.1.tar.gz";
      download(fileUrl, localFile);
    } catch (ClosedByInterruptException e) {
      LOG.info("Caught ClosedByInterruptException... exiting job.");
    } catch (IOException e) {
      LOG.info("Caught IOException... exiting job.", e);
    } finally {
      if (isJobInterrupted) {
        LOG.info("Job " + jobKey + " did not complete");
      } else {
        LOG.info("Job " + jobKey + " completed at " + new Date());
      }
    }
  }
  
  // this method is called by the scheduler
  public void interrupt() throws UnableToInterruptJobException {
    LOG.info("Job " + jobKey + "  -- INTERRUPTING --");
    isJobInterrupted = true;
    if (thisThread != null) {
      // this call causes the ClosedByInterruptException to happen
      thisThread.interrupt(); 
    }
  }

  private void download(String address, String localFileName) throws ClosedByInterruptException, IOException {
    URL url = new URL(address);
    ReadableByteChannel src = Channels.newChannel(url.openStream());
    WritableByteChannel dest = new FileOutputStream(new File(localFileName)).getChannel();
    try {
      System.out.println("Downloading " + address + " to " + new File(localFileName).getCanonicalPath());
      int size = fastChannelCopy(src, dest);
      System.out.println("Download completed! " + (size / 1024 / 1024) + " MB");
    } finally {
      src.close();
      dest.close();
    }
  }
  
  // Code copied from http://thomaswabner.wordpress.com/2007/10/09/fast-stream-copy-using-javanio-channels/
  private static int fastChannelCopy(final ReadableByteChannel src, final WritableByteChannel dest) throws IOException {
    final ByteBuffer buffer = ByteBuffer.allocateDirect(16 * 1024);
    int count = 0;
    int total = 0;
    while ((count = src.read(buffer)) != -1) {
      total += count;
      // prepare the buffer to be drained
      buffer.flip();
      // write to the channel, may block
      dest.write(buffer);
      // If partial transfer, shift remainder down
      // If buffer is empty, same as doing clear()
      buffer.compact();
    }
    // EOF will leave buffer in fill state
    buffer.flip();
    // make sure the buffer is fully drained.
    while (buffer.hasRemaining()) {
      dest.write(buffer);
    }
    return total;
  }
}
And this is my main class that creates Quartz scheduler and simulates the intended interruption. The download will take about 40 seconds to finish (a 59MB file). To see that our job is indeed interrupted during download, we start the scheduler and sleep for 5 seconds then interrupt the job.
NOTE: If you want to see the job to finish, sleep for about 40 seconds.
package demo;

import static org.quartz.DateBuilder.nextGivenSecondDate;
import static org.quartz.JobBuilder.newJob;
import static org.quartz.SimpleScheduleBuilder.simpleSchedule;
import static org.quartz.TriggerBuilder.newTrigger;

// other imports excluded for brevity

public class InterruptExample {

  public void run() throws Exception {
    final Logger log = LoggerFactory.getLogger(InterruptExample.class);

    log.info("------- Initializing ----------------------");

    // First we must get a reference to a scheduler
    SchedulerFactory sf = new StdSchedulerFactory();
    Scheduler sched = sf.getScheduler();

    log.info("------- Initialization Complete -----------");

    log.info("------- Scheduling Jobs -------------------");

    // get a "nice round" time a few seconds in the future...
    Date startTime = nextGivenSecondDate(null, 1);

    JobDetail job = newJob(MyJob.class).withIdentity("myJob", "group1").build();

    SimpleTrigger trigger = newTrigger().withIdentity("trigger1", "group1").startAt(startTime)
        .withSchedule(simpleSchedule()).build();

    sched.scheduleJob(job, trigger);

    // start up the scheduler (jobs do not start to fire until
    // the scheduler has been started)
    sched.start();
    log.info("Scheduler thread's name: " + Thread.currentThread().getName());
    log.info("------- Started Scheduler -----------------");

    try {
      // if you want to see the job to finish successfully, sleep for about 40 seconds
      Thread.sleep(5 * 1000L);
      // tell the scheduler to interrupt our job
      sched.interrupt(job.getKey());
      Thread.sleep(3 * 1000L);
    } catch (Exception e) {
      e.printStackTrace();
    }

    log.info("------- Shutting Down ---------------------");

    sched.shutdown(true);

    log.info("------- Shutdown Complete -----------------");
  }

  public static void main(String[] args) throws Exception {
    InterruptExample example = new InterruptExample();
    example.run();
  }
}
And this is the excerpt from the log, stating that our job is intterupted and exit prematurely upon ClosedByInterruptException
INFO [main] ------- Scheduling Jobs -------------------
INFO [main] Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED started.
INFO [main] Scheduler thread's name: main
INFO [main] ------- Started Scheduler -----------------
INFO [DefaultQuartzScheduler_Worker-1] Thread name of the current job: DefaultQuartzScheduler_Worker-1
INFO [DefaultQuartzScheduler_Worker-1] Job group1.myJob executing at Mon Apr 16 16:24:40 PDT 2012
 Downloading http://d2zwv9pap9ylyd.cloudfront.net/terracotta-3.6.1.tar.gz to S:\quartz-interrupt-demo\terracotta-3.6.1.tar.gz
INFO [main] Job group1.myJob  -- INTERRUPTING --
INFO [DefaultQuartzScheduler_Worker-1] Caught ClosedByInterruptException... exiting job.
INFO [DefaultQuartzScheduler_Worker-1] Job group1.myJob did not complete
ERROR [DefaultQuartzScheduler_Worker-1] Worker thread was interrupt()'ed.
 java.lang.InterruptedException
 at java.lang.Object.wait(Native Method)
 at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:552)
INFO [main] ------- Shutting Down ---------------------
INFO [main] Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED shutting down.
INFO [main] Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED paused.
INFO [main] Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED shutdown complete.
INFO [main] ------- Shutdown Complete -----------------
The whole example can be downloaded here

Friday, October 07, 2011

Ruby script to list process info in Windows

Below is a Ruby script to list process id and its command line in Windows.

To run it:
ruby pid.rb <process-name>
ie: ruby pid.rb java: will list java.exe and javaw.exe processes


class ProcessInfo
  attr_accessor :cmdLine, :pid
  
  def self.parseWmic(cmd)
    result = `#{cmd}`
    raise("Error: " + result) unless $? == 0
    processes = []
    pinfo = nil
    result.split(/\r?\n/).each do |line|
      next if line =~ /^\s*$/
      if line =~ /CommandLine=(.*)/i
        pinfo = ProcessInfo.new
        pinfo.cmdLine = $1
      elsif line =~ /ProcessId=(\d+)/i
        pinfo.pid = $1
        processes << pinfo unless pinfo.pid.to_i == $$.to_i
      end
    end
    return processes
  end
  
  def self.queryProcess(processName)
    return self.parseWmic("wmic process where \"name like '" + processName + 
                "%'\" get ProcessID,Commandline /format:list")
  end
  
  def self.queryJavaProcess
    return self.queryProcess('java')
  end  
  
  def to_s
    @pid.to_s + " " + @cmdLine
  end 
end 

puts ProcessInfo.queryProcess(ARGV[0])

Thursday, October 06, 2011

Equivalent of ps -ef | grep java in Windows

If you want to list a process and its command line, process id in Windows, this is the command:

 wmic process where "name='java.exe'" get ProcessID, Commandline /format:list

That is the equivalent of "ps -ef | grep java" in Linux. Then you could use taskkill /f /pid <PID> to kill it.

Friday, September 23, 2011

Install JDK on Windows without a UI

in CMD.exe shell:

./jdk-6u27-windows-x64.exe /s INSTALLDIR=\c:\jdk\jdk1.6.0_27-x64

This will allow you to install the JDK automatically without any GUI prompt, ideal for automation script.Note the forward slash before the c: drive is necessary.

Thursday, April 07, 2011

Force JBoss to load your lib jars

If you're running JBoss and you want it to favor librarires that go with your WAR instead of using what JBoss bundled with. Add this jboss-web.xml to your WEB-INF dir


<jboss-web>
<class-loading java2classloadingcompliance="false">
<loader-repository>
org.terracotta:archive=all-in-one.war
<loader-repository-config>
java2ParentDelegation=false
</loader-repository-config>
</loader-repository>
</class-loading>
</jboss-web>

Substitute "org.terracotta" for your package name and "all-in-one.war" for your WAR