Tuesday, February 12, 2013

Introduction to JRuby

JRuby
JRuby is an implementation of Ruby which runs on top of Java Virtual Machine. JRuby code can be embedded in Java code and your JRuby code can interact with Java Objects and has access to every Java API.

Why to use JRuby?
Ruby being a scripting language is dynamic and much faster than Java. There are lot of things that can be easily accomplished in Ruby for example I found that parsing & scraping HTML is much easier and faster in Ruby using HPricot. As a Java programmer and you can write part of your application in JRuby and then either embed this in your Java code or use JRubyC compiler to convert your JRuby code in to Java.

Your first JRuby program

[ruby]
require 'rubygems'
class MyClass
def initialize()
end
def myfunction(msg)
puts msg;
end
end
MyClass.new.myfunction('Hello JRuby!');
[/ruby]

Executing the above code can be done using the following command
jruby

Monday, February 11, 2013

Handling Home Key in Android

I recently came across "Todler lock" application which had lot of interesting features. One of the most intriguing feature was handling  of Home key event.

1.Create a Activity Alias

We use Activity alias in order to programmatically enable or disable home screen launcher. An alias of an activity acts as an independent entity and intent filters that are not in the original activity can be added.

Declare your activity and declare an alias for your activity with the following intent filters


[xml]
<activity
android:name="com.vkslabs.example.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity-alias
android:name=".MainActivityAlias"
android:targetActivity="com.vkslabs.example.MainActivity"
>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.HOME" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.MONKEY"/>
</intent-filter>
</activity-alias>
[/xml]

2. Enabling and disabling component using setComponentEnabledSetting
[java]
PackageManager manager = getPackageManager();
ComponentName compName = new ComponentName("com.vkslabs.example", "com.vkslabs.example.MainActivityAlias");
//ComponentName compName = new ComponentName("<Package Name>", "<Package Name.Alias Name>");

manager.setComponentEnabledSetting(compName,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
[/java]
You can use COMPONENT_ENABLED_STATE_DISABLED for disabling the alias.

Thursday, January 31, 2013

Saving bitmap buffer as bitmap image

Eclipse Memory Analyzer doesn’t provide option to view a bitmap buffer directly. Try the following steps that will allow you to save the bitmap buffer as a bitmap image that you can view using any image viewer.

1. Select the bitmap buffer that you would like to Save


domtree



2. Save the buffer to your computer


Select the Location in your computer where you would like to save the buffer file. You can give any name and extension
savebuffer



3. Enable inspector view in Eclipse


Once you have saved the bitmap buffer you will have to convert the bitmap buffer to bitmap for which you will need to know height and width of the bitmap.

You can use the inspector window to view the height and width of the bitmap. If inspector window is not available you can enable it using the following option.

inspectorview


showview



4. Find the dimension of the bitmap


imagedim



5. Convert the bitmap buffer in to bitmap image


Once you have the bitmap buffer, bitmap dimension you can execute the attached java program with the following command line option.

[code]
Java MATBitmap.java &lt;input.bmp&gt; &lt;output.bmp&gt; &lt;bitmap width&gt; &lt;bitmap height&gt;
[/code]

Example

[code]
java MATBitmap debug.bmp converted.bmp 800 800
[/code]

Bingo! now you can open the converted.bmp in any image editor.

Download MATBitmap.java

Fixing Bitmap memory leaks in Android

The biggest hurdle for Android developers is memory leaks. Especially if you are using a lot of images you tend to see memory leaks more often. Android internally handles the images as Bitmaps so even if the images used are optimized or of low quality it takes the same amount of memory. For example an image of size 800X600 takes 4 bytes per pixel which means the size will be 1.8 MB (4*800*600 = 1920000 bytes) whereas the same image will be 200 KB – 600 KB based on the quality of the image.
If you are facing frequent Out Of Memory errors then the first handy tool will be DDMS and Memory Analyzer tool (MAT).

Whenever you take memory dump you could see that there are bitmaps held in heap but most of the time you will not be able to find which image exactly the bitmap instance holds. MAT doesn’t provide an easy way to view the bitmap image held in a bitmap objects.
You can do the following steps to view the image in the bitmap buffer.

Friday, April 13, 2012

Starting with JPA with JBoss and MySQL

Environment

  • JBoss 7.1.1

  • MySQL 5.5


Note: Make sure the datasource is configured properly. Visit the post (http://vkslabs.com/adding-mysql-data-store-to-jboss-7-x/) to find out how to configure datasource.

Step 1: Configure persistence.xml

Create a file called persistence.xml and add the following content

[xml]
&lt;persistence xmlns=&quot;http://java.sun.com/xml/ns/persistence&quot;
xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
xsi:schemaLocation=&quot;http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd&quot;
version=&quot;2.0&quot;&gt;
&lt;persistence-unit name=&quot;testjpa&quot; transaction-type=&quot;RESOURCE_LOCAL&quot;&gt;
&lt;jta-data-source&gt;java:jboss/datasources/myDS&lt;/jta-data-source&gt;
&lt;class&gt;com.test.StudentBean&lt;/class&gt;
&lt;properties&gt;
&lt;property name=&quot;hibernate.dialect&quot; value=&quot;org.hibernate.dialect.MySQLDialect&quot;/&gt;
&lt;property name=&quot;hibernate.hbm2ddl.auto&quot; value=&quot;update&quot;/&gt;
&lt;property name=&quot;hibernate.transaction.jta.platform&quot;
value=&quot;org.hibernate.service.jta.platform.internal.JBossAppServerJtaPlatform&quot; /&gt;
&lt;/properties&gt;
&lt;/persistence-unit&gt;
&lt;/persistence&gt;
[/xml]

Make sure the datasource name matches the datasource configured in JBoss

Step 2: Create your bean

Create the bean which you would like to persist

[java]
package com.test;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

@Entity (name=&quot;student&quot;)
public class StudentBean {
@Id
@GeneratedValue
private int id;
private String name;
private int age;

public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
[/java]

  • @Entity annotations should be mentioned to denote the bean is a entity bean

  • @Id annotation makes the field as primary key of the table

  • @GeneratedValue annotation makes the field value as auto generated


Step 3: Persist your bean using EMF

[java]
EntityManagerFactory entityManagerFactory =  Persistence.createEntityManagerFactory(&quot;testjpa&quot;);
EntityManager em = entityManagerFactory.createEntityManager();
EntityTransaction userTransaction = em.getTransaction();

userTransaction.begin();
StudentBean student = new StudentBean();
student.setName(name);
student.setAge(age);
em.persist(student);
em.flush();
userTransaction.commit();
em.close();
entityManagerFactory.close();
[/java]

  1. testjpa is the name of persistence-unit in the persistence.xml

  2. Calling persist() just marks the bean for persistence and might not populate DB immediately, in order to see the data in database immediately flush() must be called.


Note:

  • The value for the property hibernate.hbm2ddl.auto can be


                        validate: validate the schema, makes no changes to the database.
                        update: update the schema.
                        create: creates the schema, destroying previous data.
                        create-drop: drop the schema at the end of the session.

  •    In case there is no exception when bean is persisted but no row is found in DB then make sure the value for the property hibernate.hbm2ddl.auto is not set to create-drop



  • Important:  The common mistake the developers make is to create the file in the META-INF folder under the project folder which is wrong.


The META-INF folder where persistence.xml is present should be in classpath but for JPA the root of the persistence unit is the WEB-INF/classes directory hence the persistence.xml should be copied in to WEB-INF/classes/META-INF folder (You might have to create META-INF folder manually).

If the persistence.xml is not created in the right folder the following error will be encountered
javax.persistence.PersistenceException: No Persistence provider for EntityManager named testjpa:       No META-INF/persistence.xml was found in classpath.

Wrong location for persistence.xml




  • In case you face the following exception make sure the persistence.xml has the  attribute transaction-type="RESOURCE_LOCAL"


ERROR [stderr] (http-localhost-127.0.0.1-8080-1) java.lang.NullPointerException
ERROR [stderr] (http-localhost-127.0.0.1-8080-1)     at org.hibernate.engine.transaction.internal.jta.JtaStatusHelper.getStatus(JtaStatusHelper.java:73)
ERROR [stderr] (http-localhost-127.0.0.1-8080-1)     at org.hibernate.engine.transaction.internal.jta.JtaStatusHelper.isActive(JtaStatusHelper.java:115)
ERROR [stderr] (http-localhost-127.0.0.1-8080-1)     at org.hibernate.engine.transaction.internal.jta.CMTTransaction.join(CMTTransaction.java:149)
ERROR [stderr] (http-localhost-127.0.0.1-8080-1)     at org.hibernate.ejb.AbstractEntityManagerImpl.joinTransaction(AbstractEntityManagerImpl.java:1207)
ERROR [stderr] (http-localhost-127.0.0.1-8080-1)     at org.hibernate.ejb.AbstractEntityManagerImpl.postInit(AbstractEntityManagerImpl.java:176)
ERROR [stderr] (http-localhost-127.0.0.1-8080-1)     at org.hibernate.ejb.EntityManagerImpl.<init>(EntityManagerImpl.java:89)
ERROR [stderr] (http-localhost-127.0.0.1-8080-1)     at org.hibernate.ejb.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:125)
ERROR [stderr] (http-localhost-127.0.0.1-8080-1)     at org.hibernate.ejb.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:120)

Thursday, April 12, 2012

Adding MySQL data source to JBoss 7.X

Today I spent almost 4-5 hours figuring how to configure MySQL for JBoss. Since I am new to JEE world it was a real struggle for me. So hopefully this post will help newbies like me...

  1. Download and extract  JBoss v7.1.1 (Download URL : http://www.jboss.org/jbossas/downloads/)

  2. Download and install MySQL (Download URL : http://dev.mysql.com/downloads/)

  3. Download MySQL JDBC driver (Download URL: http://dev.mysql.com/downloads/connector/j/)


Step 1 - Copy JDBC driver to JBoss folder

  • Extract the downloaded JDBC Driver (mysql-connector-java-5.1.19.zip) which contains source, readme files along with the driver JAR file (mysql-connector-java-5.1.19-bin.jar). For now we will be using only this JAR file.

  • Go to the folder JBOSS_HOME\modules\com and create a folder called mysql and inside mysql create another folder called main.


                 Note: JBOSS_HOME is your JBoss root folder in my case it is d:\D:\jboss-as-7.1.1.Final

  • Copy the driver JAR file (mysql-connector-java-5.1.19-bin.jar) in to this folder (D:\jboss-as-7.1.1.Final\modules\com\mysql\main)

  • Create a XML file called module.xml with the following content


[xml]
<module xmlns="urn:jboss:module:1.1" name="<strong>com.mysql</strong>"><resources>
<resource-root path="mysql-connector-java-5.1.19-bin.jar"/>
</resources>
<dependencies>
<module name="javax.api"/>
<module name="javax.transaction.api"/>
<module name="javax.servlet.api" optional="true"/>
</dependencies>
</module>

[/xml]

Note: Make sure the module name in XML (marked in bold) follows the directory structure you have created else this won't work.

Step 2 - Configure MySQL Driver

  • Go to the folder JBOSS_HOME\standalone\configuration and open the standalone.xml

  • Search for the text h2 until you find the datasources configuration which will look like


[xml]
<datasources>
<datasource jndi-name="java:jboss/datasources/ExampleDS" pool-name="ExampleDS" enabled="true" use-java-context="true">
<connection-url>jdbc:h2:mem:test;DB_CLOSE_DELAY=-1</connection-url>
<driver>h2</driver>
<security>
<user-name>sa</user-name>
<password>sa</password>
</security>
</datasource>
<drivers>
<driver name="h2" module="com.h2database.h2">
<xa-datasource-class>org.h2.jdbcx.JdbcDataSource</xa-datasource-class>
</driver>
</drivers>
</datasources>
[/xml]

  • Add MySQL Driver details to the drivers tag


[xml]
<driver name="mysql" module="<strong>com.mysql</strong>">
<xa-datasource-class>com.mysql.jdbc.Driver</xa-datasource-class>
</driver>
[/xml]
Note: the module name (marked in bold) should match the module name specified in the module.xml in Step 1.

Step 3 - Configure MySQL DataSource

Add the MySQL Data Store to the datasources tag
[xml]
<datasource jndi-name="java:jboss/datasources/myds" pool-name="myds" enabled="true" use-java-context="true">
<connection-url>jdbc:mysql://localhost:3306/mydb</connection-url>
<driver><strong>mysql</strong></driver>
<security>
<user-name>root</user-name>
<password>mypassword</password>
</security>
</datasource>
[/xml]
Note: the driver name (marked in bold) should be the same as the driver name specified in Step 2.

The final XML data source tag should look like
[xml]
<subsystem xmlns="urn:jboss:domain:datasources:1.0">
<datasources>
<datasource jndi-name="java:jboss/datasources/ExampleDS" pool-name="ExampleDS" enabled="true" use-java-context="true">
<connection-url>jdbc:h2:mem:test;DB_CLOSE_DELAY=-1</connection-url>
<driver>h2</driver>
<security>
<user-name>sa</user-name>
<password>sa</password>
</security>
</datasource>
<datasource jndi-name="java:jboss/datasources/myds" pool-name="myds" enabled="true" use-java-context="true">
<connection-url>jdbc:mysql://localhost:3306/mydb</connection-url>
<driver>mysql</driver>
<security>
<user-name>root</user-name>
<password>mypassword</password>
</security>
</datasource>
<drivers>
<driver name="h2" module="com.h2database.h2">
<xa-datasource-class>org.h2.jdbcx.JdbcDataSource</xa-datasource-class>
</driver>
<driver name="mysql" module="com.mysql">
<xa-datasource-class>com.mysql.jdbc.Driver</xa-datasource-class>
</driver>
</drivers>
</datasources>
</subsystem>
[/xml]
Note: Alternatively you can configure your datasource using the admin console by going to http://localhost:9990 and adding the datasource details (http://localhost:9990/console/App.html#datasources)

Wednesday, April 4, 2012

Android Marketplace APIs

Google known for releasing API for every service it offers has still not opened up their marketplace for the developers. There is no official API to access the marketplace and execute a search. But I came across this interesting project that uses the protobuf (The protocol that Google uses for almost all structured data communication).

http://code.google.com/p/android-market-api/

This is a Java implementation of the unofficial marketplace APIs and the site also has links to projects on other languages such as Ruby and PHP. Since this is an unofficial API there are many glitches for instance you cannot search beyond the 500th app details if your search query returns more than 500 results.

Searching by keyword

[java]
String query = "india";

AppsRequest appsRequest = AppsRequest.newBuilder()
.setQuery(query)
.setStartIndex(0).setEntriesCount(10)
.setWithExtendedInfo(true)
.build();

session.append(appsRequest, new Callback<AppsResponse>() {
public void onResult(ResponseContext context, AppsResponse response) {
//Process the response here
List<App> list =     appsResponse.getAppList();
int count = appsResponse.getAppCount();
for (int i = 0; i< count; i++)
{
App app = list.get(i);
System.out.println(" App Title is ::  "+app.getTitle() +"  App  Price:: "+app.getPrice()  +" App  Rating :: "+app.getRating()  +" App  Ratings Count :: "+app.getRatingsCount());
}
}
});
[/java]

You can query apps based on the Package Name as well as publisher name.
Search By Package Name
String query = "pname:<package name>"

eg: String query = "pname:com.vkslabs.buybooks";

Search By Publisher
String query = "pub:<publisher name>";

eg: String query = "pub:vkslabs";

Troubleshooting
If the search API works for keyword based search but not for package name or publisher name search then it might be due to the invalid Android ID. You need to set a valid Android ID for the API to work properly.

How to get a valid Android ID?

  • Install the application "Android System Info" from Marketplace and launch the app.

  • Goto Menu -> More -> Gtalk Service Monitor

  • Find the line aid:<Android ID value> (this is usually the second line in the screen)

  • Copy the value and set it as the Android ID in the MarketSession using the API


session.getContext().setAndroidId("XXXXXXXXXX");