Thursday, August 8, 2013

Java: How to solve the InputStream waiting for data indeterminately

I've worked in a web project written in Java where I got a weird bug using a InputStream object. My project works as a client of another system what I do not have control and needed to download some data from that.

My problem was that somehow, when I was downloading some data using a InputStream the object was locked, waiting for data forever, even when the transmission had already finished.

To solve that problem, considering that I didn't have control about the server, what I did was implement a kind of timeout to the InputStream.

For that, I read all the streaming, counting the time since the last time that some data had come. When it completed TIME_OUT milliseconds (in this case 1000) since the last reading, I manually stop the reading and created a new InputStream object with the data alright read.

Let's see the code!

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Calendar;

public class InputStreamUtils {
 
 public static long TIME_OUT = 1000;
 
 public static InputStream autoFinish(InputStream is) throws IOException{
  if (is == null){
   return null;
  }
  
  long lastTimeDataWasRead = Calendar.getInstance().getTimeInMillis();
  
  ByteArrayOutputStream buffer = new ByteArrayOutputStream();
  int nRead = 0;
  byte[] data = new byte[1024];

  while (nRead != -1) {
   if (is.available() == 0){
    long timeSinceLastReading = Calendar.getInstance().getTimeInMillis() - lastTimeDataWasRead;
    if (timeSinceLastReading >= TIME_OUT){
     nRead = -1;
     break;
    }
   }
   else{
    lastTimeDataWasRead = Calendar.getInstance().getTimeInMillis();
    nRead = is.read(data, 0, 1024);
    if (nRead != -1){
     buffer.write(data, 0 , nRead);
    }
   }
  }
  buffer.flush();
  return (InputStream) new ByteArrayInputStream(buffer.toByteArray());
 }
}

Yet, if you want to use the data as a byte array representation you can return buffer.toByteArray() instead of (InputStream) new ByteArrayInputStream(buffer.toByteArray()).

Tuesday, May 21, 2013

Ubuntu: How to install the Oracle Java on Ubuntu via Repository/PPA

OpenJDK is a great open-source implementation of Java Platform supported by open-source community and Oracle itself. However it's very well stable and compatible with Java applications there is a few cases where it's necessary to use the Oracle Java JRE/JDK itself.

The problem about this is that there isn't an official Oracle Java repository available for Ubuntu. Even there's no *.DEB package available to download in Oracle Java site.

However, the Web Upd8 team has provide a Ubuntu PPA with the Oracle Java packages what today it's provide 3 versions of that: 6, 7 and the newest 8. If you want to check the PPA itself you can check it on https://launchpad.net/~webupd8team/+archive/java.

So, the installation of a ppa software itself is quite simple, just follow the next lines:

sudo add-apt-repository ppa:webupd8team/java
sudo apt-get update 
sudo apt-get install oracle-java6-installer

or
sudo apt-get install oracle-java7-installer

or
sudo apt-get install oracle-java8-installer

Monday, May 20, 2013

GWT: Drag and Drop Event

The client.Element GWT class has a method called 'setDraggable', what do exactly what its name says: It mark an object as draggable. Let's check how it works out exactly.

In GWT (Google Web Toolkit), if you have a component that extends from client.Element, for sure it has the setDraggable method to say the system that it can be dragged through the screen.

That's quite simple. However we'll need to catch that object in another place (by another event) and change both by each other.

For sure we'll need to have a copy of the dragging object to work on it afterward.

For that example, let's suppose that we're building a table what has its cells represented as a MyCell object what extends client.Element. Let's see the following lines:
private MyCell draggingCell = null;
private MyCell targetCell = null;
protected void setAsDraggable(final MyCell cell){
  cell.getElement().setDraggable(Element.DRAGGABLE_TRUE);

  cell.addDomHandler(new DragStartHandler() {
   @Override
   public void onDragStart(final DragStartEvent event) {
    //this line is necessary for that the event works on Firefox!
    event.setData("text", "drag started!");
    draggingCell = (MyCell)event.getSource();
   }
  }, DragStartEvent.getType());
 }

protected void setCatchDrag(final MyCell cell){
  cell.addDomHandler(new DragOverHandler() {
   @Override
   public void onDragOver(final DragOverEvent event) {
   }
  }, DragOverEvent.getType());

  cell.addDomHandler(new DropHandler() {
   @Override
   public void onDrop(final DropEvent event) {
    event.preventDefault();
    targetCell = (MyCell)event.getSource();
    changeContexts(draggingCell, targetCell);
   }
  }, DropEvent.getType());
 }

protected void changeContexts(MyCell from, MyCell to){
  MyCell aux = to;
  to = from;
  from = aux;
}

At the onDragStart handler, I just save a copy of the dragging object and after, when then user drop the object and the onDrop event is dispatched it's time to save the target object and call the changeContexts method to do it's properly change the object's place and so, we could have the drag and drop effect as well.

Note that I've written two principal methods setAsDraggable and setCatchDrag what must be call to every cell that we want to turn draggable and catchable respectively.

Friday, January 11, 2013

Android: Getting Started developing for Google TV

If you are an Android developer and want to get started developing for Google TV you came to the right place. I'm getting started on Google TV right now I want to share codes with you. So, let's get start.


Google TV limitations:

The thirst thing to keep in mind about Google TV app is that it's an Android app yet! However, we need consider some little things:

- Google TV is NOT a touch device;
- Google TV is large screen device;
- Google TV doesn't have sensors like accelerometer and compass;
- Google TV doesn't support camera, GPS, Bluetooth, microphone;
- Google TV doesn't support NDK;

As we can see, we are talking about a special kind of Android device and so we need consider some special features for that can work. To know the complete list of unsupported features of Google TV see the official report.

After remember that Google TV is a kind of special device we need to know that it needs a specific Android SDK version to work. Until today, the unique version of Android API compatible with Google TV is the 12 (Android 3.1). Another thing about developing for Google TV is that besides the API, it's necessary install the Google TV Addon (which is available on Android SDK Manager as well), what can be a problem is: this runs just on Linux!

So, if as me you have no problem about work with Linux (or even prefer it) neither about the Google TV hardware limitations, congratulations, you are able to keeping forward! =)

How to configure the Android Virtual Device to emulate the Google TV:

The process to emulate Google TV is the same as any Android device, but you have to select the Google TV Addon option on the Target field of the Android Virtual Device edit screen from Android Virtual Device Manager and a tvdpi or xhdpi device on Device field. Know more about Google TV AVDs.

Android Virtual Device edit screen
Android Virtual Device edit screen

After create your AVD following the specification of the image above, you'll need to do some manual adjusts on that. So, open the ~/.android/avd/GoogleTV.avd/config.ini file and overwrite the follow lines:

skin.name=720p
skin.path=add-ons/addon-google_tv_addon-google-12/skins/720p
skin.dynamic=no

Now you'd be able to run the Google TV emulation. Yet if you get the follow message error, that means you can't read or write in /dev/kvm what is required for that the emulator can run.

Failed to load libGL.so
ioctl(KVM_CREATE_VM) failed: Interrupted system call
error libGL.so: cannot open shared object file: No such file or directory

ko:failed to initialize KVM
Failed to load libGL.so
error libGL.so: cannot open shared object file: No such file or directory

To correct that, open your Linux terminal and do:

sudo chmod a+rw /dev/kvm

So now you can start developing you first Google TV application as well.

Google TV emulator booting
Google TV emulator booting

Some important notes before starting coding:

I'm assuming that you are already an Android developer, so I'll not show you how to start a new Android project. However, it's important remember that the Android system assumes that all application require a touchscreen, so we need to say the oppose for it. For that we can put the follow code in the AndroidManifest.xml file:

<uses-feature
android:name="android.hardware.touchscreen"
android:required="false"/>

Another important note is that if you are doing an application to runs both on Google TV and smartphones or tablets you can use layout-large-notouch for layouts and drawable-land-xhdpi (1080p) or drawable-land-tvdpi (720p) for drawables to target Google TV. Even you can determine if the app is running on Google TV by testing:

if (getPackageManager().hasSystemFeature("com.google.android.tv")) {
    Log.d("TV Test", "Running on Google TV!");
}

A very simple test app running in the emulator
A very simple test app running in the emulator

Hope this help you, til next code!


The follows links are consulted to write this post:
https://developers.google.com/tv/
http://oncelinux.blogspot.com.br/2013/01/googletv-emulator-hang-on-logo-screen.html

I would like to specially thanks to +David Carver who helped me a lot with some emulator's problems.

Thursday, January 3, 2013

Grails: How to Read Properties Files in a Groove Class

Reading value from a *.properties file on a *.gpg page is very easy. Also, the scaffold generated CRUD pages have a lot of example what can be consulted as a start point.
Let’s suppose that we have a <my project>/i18n/parameters.properties file which has line
myparameter.something=My Value
So, if we want to get the ‘My Value’ value on a *.gpg page we just need write:
${message(code: 'myparameter.something', default: 'Some default value')}
But, what to do if it’s necessary reading a property’s value in a Groove Class? The answer is quite easy! Supposing the same parameters.properties file we supposed before, we can do:
import org.springframework.context.i18n.LocaleContextHolder as LCH
class MyClass {
 /** Dependency injection for getMessage. */
 def messageSource

 public def getMyParameter(){
  return messageSource.getMessage('myparameter.something', null, 'Some default value', LCH.getLocale())
 }
}
That's all folks!

Wednesday, January 2, 2013

Canonical Annouces Ubuntu for Phones

After a one-day-counting-down, which read 'So close, you can almost touch it.', Canonical, the Ubuntu developer, has announced Ubuntu for Phones, a new Smartphone SO running Linux. According to the official website, the newest smartphone SO will be shows up on CES 2013 and must run native apps as well as web apps.

Even according to the Ubuntu's page, developers will be able to write apps compatible between desktop and smartphone Ubuntu versions by using the Ubuntu SDK.

Ubuntu for Phone: Official pictures

Sure it's very early to say anything about Ubuntu for Phone, so let's follow the next steps...

Find out more on http://www.ubuntu.com/devices/phone.

Friday, December 7, 2012

How to Know If The DataTables is Running

That's just a tip for you guys who are working with the DataTables plug-in. If you need to know if the DataTables JS code is properly running, you can just pass a parameter to it to have a message box as result.

That's is really simples:
$(document).ready( function() {
   $('#example').dataTable( {
     "fnInitComplete": function(oSettings, json) {
       alert( 'DataTables has finished its initialisation.' );
     }
   } );
} )

The fnInitComplete function is called when the Datatables finishes its initialization, so if that doesn't show up, you will be able to know that the plug-in haven't started.

I know that's quite simple, but this small code has helped me to find out an another big problem.