Apache Camel – JDBC with Spring Transaction support

Posted by admin | Posted in Code Snippets, ESB | Posted on 22-12-2011

0

Continuing my journey with Fuse ESB (ServiceMix) and Apache Camel I will present a small example on how to route your messages in a transacted way using Spring Transaction Manager.
For the purpose of this tutorial we are going to define a datasource to in memory Hsqldb instance and configure it with ‘org.springframework.jdbc.datasource.DataSourceTransactionManager’. Our camel example will be based on the tutorial/document from the FuseSource website itself which could be found at : http://fusesource.com/docs/router/2.5/transactions/index.html.
Our application will do the following:

  1. Create database table in the in-memory hsqldb database and populate it with same data – we are going to use JdbcTemplate for this purpose
  2. The route itself will pick up a messages from the specified directory, one by one, one of the messages will contain data causing an exception and rolling back our transaction and database commit.
  3. After each message is processed sucessfully the dump of our database will be printed to the console
  4. If the exception occurs and the transaction will be rolled back, the appropriate log would be displayed stating the current database content

The full source code for this example, packaged as a maven based project can be downloaded from the Github website.

1. We are going to use 2 spring beans for our example, one with injected datasource in a constructor which will populate our database data:

package tutorial.jdbc;

import javax.sql.DataSource;

import org.apache.log4j.Logger;
import org.springframework.jdbc.core.JdbcTemplate;

public class CreateTable {
    private static Logger log = Logger.getLogger(CreateTable.class);

    protected DataSource dataSource;
    protected JdbcTemplate jdbc;

    public DataSource getDataSource() {
        return dataSource;
    }

    public void setDataSource(DataSource dataSource) {
        this.dataSource = dataSource;
    }
   
    public CreateTable(DataSource ds) {
        log.info("CreateTable constructor called");
        setDataSource(ds);
        setUpTable();
    }
   
    public void setUpTable() {
        log.info("About to set up table...");
        jdbc = new JdbcTemplate(dataSource);
        jdbc.execute("create table accounts (name varchar(50), amount int)");
        jdbc.update("insert into accounts (name,amount) values (?,?)",
                new Object[] {"Major Clanger", 2000}
        );
        jdbc.update("insert into accounts (name,amount) values (?,?)",
                new Object[] {"Tiny Clanger", 100}
        );
        log.info("Table created");
    }
}

another bean will be responsible for our route logic, performing database operations. Datasource for this bean is injected using a property (see the camel-context.xml file below for more details):

package tutorial.jdbc;

import java.util.List;

import javax.sql.DataSource;

import org.apache.camel.Exchange;
import org.apache.camel.language.XPath;
import org.apache.log4j.Logger;
import org.springframework.jdbc.core.JdbcTemplate;

public class AccountService {
    private static Logger log = Logger.getLogger(AccountService.class);
    private JdbcTemplate jdbc;

    public AccountService() {
    }

    public void setDataSource(DataSource ds) {
        jdbc = new JdbcTemplate(ds);
    }

    /**
     * Adds a specific amount of money to a named account
     *
     * @param name - account name
     * @param amount - amount to add
     */

    public void credit(@XPath("/transaction/transfer/receiver/text()") String name,
            @XPath("/transaction/transfer/amount/text()") String amount) {
        log.info("credit() called with args name = " + name + " and amount = " + amount);
        int origAmount = jdbc.queryForInt("select amount from accounts where name = ?", new Object[] { name });
        int newAmount = origAmount + Integer.parseInt(amount);
        jdbc.update("update accounts set amount = ? where name = ?", new Object[] { newAmount, name });
    }

    /**
     * Subtract a specific amount of money from a named account.
     *
     * @param name - account name
     * @param amount - amount to add
     */

    public void debit(@XPath("/transaction/transfer/sender/text()") String name, @XPath("/transaction/transfer/amount/text()") String amount) {
        log.info("debit() called with args name = " + name + " and amount = " + amount);
        int iamount = Integer.parseInt(amount);
        if (iamount > 100) {
            throw new IllegalArgumentException("Debit limit is 100");
        }
        int origAmount = jdbc.queryForInt("select amount from accounts where name = ?", new Object[] { name });
        int newAmount = origAmount - Integer.parseInt(amount);
        if (newAmount < 0) {
            throw new IllegalArgumentException("Not enough in account");
        }

        jdbc.update("update accounts set amount = ? where name = ?", new Object[] { newAmount, name });
    }
    public void dumpTable(Exchange ex) {
        log.info("dump() called");
        List<?> dump = jdbc.queryForList("select * from accounts");
        ex.getIn().setBody(dump.toString());
    }
}

Our datasource, transaction manager and injection points for our beans are defined in camel-context.xml file located in ‘resources/META-INF/spring’ directory:

<?xml version="1.0" encoding="UTF-8"?>
<!-- Configures the Camel Context-->
<beans xmlns="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="
      http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
      http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">


  <camelContext xmlns="http://camel.apache.org/schema/spring">
    <package>tutorial</package>
  </camelContext>
 
  <!-- spring transaction manager -->
    <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <!-- datasource to the database -->
    <bean id="dataSource" class="org.springframework.jdbc.datasource.SimpleDriverDataSource">
        <property name="driverClass" value="org.hsqldb.jdbcDriver"/>
        <property name="url" value="jdbc:hsqldb:mem:camel"/>
        <property name="username" value="sa"/>
        <property name="password" value=""/>
    </bean>
   
    <!--  Bean to initialize table in the DB -->
    <bean id="createTable" class="tutorial.jdbc.CreateTable">
        <constructor-arg ref="dataSource" />
    </bean>
   
    <!-- Bean for account service -->
    <bean id="accountService" class="tutorial.jdbc.AccountService">
        <property name="dataSource" ref="dataSource"/>
    </bean>
</beans>

2 and 3. When our configuration and the spring beans are ready we can start coding our route:

//our route definition
        //noop option - if true, the file is not moved or deleted in any way
        from("file:src/data?noop=true")
        //mark the route as transacted
        .transacted()
        //execute spring bean methods
        .beanRef("accountService","credit")
        .beanRef("accountService","debit")
        .beanRef("accountService","dumpTable")
        //log the result
        .to("log:ExampleRouter");

4. For simple error handling mechanism I have decided to use ‘onException’ which will be executed every time an exception will be thrown in our route and transaction will be rolled back

//handle exceptions and log them
        //handle exceptions and log them
        onException(IllegalArgumentException.class).
        maximumRedeliveries(0)
        .handled(true)
        .beanRef("accountService", "dumpTable")
        .to("file:target/messages?fileName=deadLetters.xml&fileExist=Append")
        .markRollbackOnly();

Remember to use SpringRouteBuilder for our transacted route instead of simple RouteBuilder class, below is the full source of our route configuration using Java DSL:

package tutorial;

import org.apache.camel.spring.SpringRouteBuilder;

/**
 * A Camel Router
 *
 * @version $
 */

public class MyRouteBuilder extends SpringRouteBuilder {


    public void configure() {
        //handle exceptions and log them
        onException(IllegalArgumentException.class).
        maximumRedeliveries(0)
        .handled(true)
        .beanRef("accountService", "dumpTable")
        .to("file:target/messages?fileName=deadLetters.xml&fileExist=Append")
        .markRollbackOnly();

        //our route definition
        //noop option - if true, the file is not moved or deleted in any way
        from("file:src/data?noop=true")
        //mark the route as transacted
        .transacted()
        //execute spring bean methods
        .beanRef("accountService","credit")
        .beanRef("accountService","debit")
        .beanRef("accountService","dumpTable")
        //log the result
        .to("log:ExampleRouter");
       
    }
}

To run an example, navigate into the project folder and execute the following command:

 mvn camel:run

Eclipse RCP – Auto-complete Text and Combo widgets

Posted by admin | Posted in Code Snippets, Eclipse RCP | Posted on 01-08-2011

0

Today I will describe a simple way to add auto-completion to you Eclipse RCP/SWT based application using some resources I’ve found browsing the web. To not reinvent the wheel, I have found a project on sourceforge which does just that, and which does the job well enough.

First of all go to the sourceforge website and download the sources, you don’t have to download a full eclipse plugin project, just download the packages we need from here by clicking ‘Download GNU Tarball’.
Copy and paste the whole downloaded folder into your ‘src’ directory visible in eclipse ‘package explorer’.

You can use this classes in the following way:

//eg for text fields
new AutocompleteTextInput(fieldTxt, options);

Where ‘fieldTxt’ is your textfield object (already created) and ‘options’ is a String array (String[]) with possible options to display.

Thanks to derekhunter4 for this project. You can find more info on sourceforge: swtaddons

Eclipse RCP – Simple Logging mechanism

Posted by admin | Posted in Code Snippets, Eclipse RCP | Posted on 28-07-2011

0

This is a short snippet to solve you logging needs in Eclipse RCP application by using build in logging functionality.
I have created 3 simple static utility methods but you can create your LogUtil utility class as you wish based on this example:

import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;

public class LogUtil {

    public static void logError(String msg){
        IStatus st = new Status(IStatus.ERROR,Activator.PLUGIN_ID, msg);
        Activator.getDefault().getLog().log(st);
    }
    public static void logInfo(String msg){
        IStatus st = new Status(IStatus.INFO,Activator.PLUGIN_ID, msg);
        Activator.getDefault().getLog().log(st);
    }
    public static void logWarning(String msg){
        IStatus st = new Status(IStatus.WARNING,Activator.PLUGIN_ID, msg);
        Activator.getDefault().getLog().log(st);
    }
}

Hope that helps someone who was forced to use System.out.println to debug simple RCP plugin applications.

Java EE 6 – JSF 2.0 Internationalization with session scoped language switcher bean

Posted by admin | Posted in Code Snippets | Posted on 05-04-2011

5

Today I will present a short tutorial on how to implement internationalization feature in your JSF 2.0 web application. This tutorial is based on the previous one called Java EE 6 – Getting Started (maven, CDI and persistence) ready project.

We will continue from that point and add simple i18n feature with language switching capabilities.
First of all you need to define available languages for your application in faces-config.xml found in (src/main/webapp/WEB-INF/faces-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<!-- This file is not required if you don't need any extra configuration. -->
<faces-config version="2.0"
  xmlns="http://java.sun.com/xml/ns/javaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="
     http://java.sun.com/xml/ns/javaee
     http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd">


   <!-- Write your navigation rules here. You are encouraged to use CDI for creating @Named managed beans. -->
<application>      
        <locale-config>
            <default-locale>en</default-locale>
            <supported-locale>pl</supported-locale>
        </locale-config>
        <resource-bundle>
            <base-name>com.softwarepassion.j2ee6tutorial.messages</base-name>
            <var>msg</var>
        </resource-bundle>
    </application>
</faces-config>

As you can see, I have defined support for two languages here, ‘pl’ – Polish and English which is the default one.
In order to use your language specific messages you need to define ‘.properties’ file for each single language.
Place your files in /src/main/resources/name/of/your/package/*.properties’ We will start with the english version first (messages.properties):

I have added just one single property for the string key called ‘Title’

Do the same for the second properties file called ‘messages_pl_PL.properties’ and place the file in the same location. As you have probably noticed already, the file for each language must follow simple naming convention like messages_+your language code+.properties

Now its time to actually implement i18n handling logic. To save selected language for each user we will use the most natural option which is a session scoped JSF managed bean.

import java.io.Serializable;
import java.util.Locale;
import java.util.logging.Logger;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;



/**
 * Used for managing i18n in application for each user
 * @author Krzysztof Grajek
 *
 */

@ManagedBean
@SessionScoped
public class LanguageSwitcher implements Serializable {

    private static final long serialVersionUID = 2756934361134603857L;
    private static final Logger LOG = Logger.getLogger(LanguageSwitcher.class.getName());
   
    private Locale locale = FacesContext.getCurrentInstance().getViewRoot().getLocale();

    public Locale getLocale() {
        return locale;
    }

    public String getLanguage() {
        return locale.getLanguage();
    }

    /**
     * Sets the current {@code Locale} for each user session
     *
     * @param languageCode - ISO-639 language code
     */

    public void changeLanguage(String language) {
        locale = new Locale(language);
        FacesContext.getCurrentInstance().getViewRoot().setLocale(locale);
    }
   
}

Once we have properties files defined, created our session scoped managed JSF bean, its time to wire it up in your xhtml documents.
I will add all language switching code inside my xhtml template which is used throughout the project as the template for all xhtml documents.
Locate your template file called ‘default.xhtml’ (src/main/webapp/WEB-INF/templates/default.xhtml) and add change it to the following:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html lang="#{languageSwitcher.language}"
        xmlns="http://www.w3.org/1999/xhtml"
        xmlns:f="http://java.sun.com/jsf/core"
        xmlns:h="http://java.sun.com/jsf/html"
        xmlns:ui="http://java.sun.com/jsf/facelets">
   <f:view locale="#{languageSwitcher.locale}">
   <h:head>
      <title>Java EE 6 Starter Application</title>
      <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
      <h:outputStylesheet name="css/screen.css"/>
   </h:head>
   <h:body>
      <div id="container">
         <div id="content">
            <div id="sidebar">
               <h3>Language switcher:</h3>
               <h:form id="langauge_form">
                  <h:commandLink action="#{languageSwitcher.changeLanguage('pl')}" value="Polski" /> |
                  <h:commandLink action="#{languageSwitcher.changeLanguage('en')}" value="English" />
               </h:form>
            </div>
            <ui:insert name="content">
               [Template content will be inserted here]
            </ui:insert>
         </div>
         <div id="footer">
            <h:graphicImage value="/resources/gfx/weld.png" alt="Weld logo"/>
            <p>
               This project was generated from a Maven archetype maintained by the Weld team.<br/>
               Weld is the reference implementation of CDI, released under the Apache License, Version 2.0.<br/>
            </p>
         </div>
      </div>
   </h:body>
   </f:view>
</html>

Final webpage with language switcher:

You can download the project files from here: sp_J2EE6Tutorial

Java EE 6 – Getting Started (maven, CDI and persistence) ready project

Posted by admin | Posted in Code Snippets | Posted on 03-04-2011

10

This short tutorial describes how to get started easily and quickly with Java EE 6 development. For the purpose of this tutorial you would need to have installed the following tools:

1. Maven 3
2. JBoss AS 6.0
3. Eclipse (I will use Helios release)
4. Eclipse m2eclipse plugin (for managing Maven based projects)

If you have all this tools ready, you can quickly create an maven J2EE archetype provided by JBoss.

1. Open up the Eclipse IDE and select ‘File -> New -> Project’

2. One the next screen just click ‘Next’

3. One the archetype selection screen, type ‘weld’ in a filter box and select weld.jsf.jee archetype 1.0.0-BETA1

4. Fill up the details for your project

5. Click ‘Finish’

6. Right click on the newly created project and select ‘Run As.. -> Run on Server’ and select Jboss 6.0 server to run your project. If you haven’t configured your jboss server with eclipse you can do it here.

7. Go to the page at: http://localhost:8080/J2EE6Tutorial where J2EE6Tutorial is the name of my project and 8080 is the port I had installed JBoss application server.

What you will see is probably the error saying:

javax.servlet.ServletException: /home.xhtml: The class 'java.lang.String' does not have the property 'id'.
    javax.faces.webapp.FacesServlet.service(FacesServlet.java:321)
    org.jboss.weld.servlet.ConversationPropagationFilter.doFilter(ConversationPropagationFilter.java:67)

This is due to the bug in the j2ee weld artifact.

8. To solve the mentioned bug, open up home.xhtml file located in ‘scr/main/webapp/’ folder and change the following line:

 <h:dataTable var="_widget" value="#widgets">

to:

 <h:dataTable var="_widget" value="#{widgets}">

9. Redeploy the application on the server. Go to the ‘Servers’ tab, select our application, right click on it, and select ‘Full Publish’.

10. Now you can refresh the application in the browser.

Getting started with Drools Flow

Posted by admin | Posted in Code Snippets, Jboss Drools, Learning Materials | Posted on 10-02-2011

14

Today I will present my latest discovery called JBoss Drools and Drools Flow in particular. I am completely new to the drools framework and because I couldn’t find myself a quick and simple intro to the framework I will post it myself. Presented example is completely useless from the business perspective and it doesn’t describe any real world scenario.

According to the Drools Flow website itself:

Drools Flow provides workflow or (business) process capabilities to the Drools platform. A business process or workflow describes the order in which a series of steps need to be executed, using a flow chart. This makes it much easier to describe a complex composition of various tasks. Processes are especially useful in describing state-based, long-running processes. Drools Flow allows end users to specify, execute and monitor (a part of) their business logic using these processes. The Drools Flow process framework is easily embeddable into any Java application (as a simple Java component) or can run standalone in a server environment.

First of all you need to prepare your development environment. You will need the following:

For the purpose of this tutorial that’s enough, you can try to download full Drools stack using the installer (including JBoss AS, Eclipse IDE, Birt reporting, Guvnor etc) but I didn’t have any luck with this installer and I guess you will be better off once you do install everything by hand as you learn.

Unpack drools binaries somewhere on your machine and Drools Eclipse workbench into eclipse folder. Restart your IDE and you should be able to create new Drools projects by now.

Select File -> New Project from the Eclipse file menu:

Provide descriptive name for your project:

Un-click all the proposed examples which eclipse plugin wants to generate for you, you can do that later if you want to learn more on drools.

Select Drools runtime, if you have no runtime configured, click ‘Configure Workspace settings’ and point to the directory where you have downloaded your binaries.

After you click finish, you should have a basic Drools project structure created for you:

Android Series: Display device CPU and Memory info

Posted by admin | Posted in Code Snippets, Mobile Development | Posted on 07-02-2011

1

Today I will post a short snippet on how to display cpu and memory info of our andorid device. The program uses external utilities to get the device info by calling cat on ‘/proc/meminfo’ and ‘/proc/cpuinfo’.
The activity displaying the data from the ‘cat’ output is displayed in a TextView contained withing ‘ScrollView’.

This is the output of the cat command running in emulator on my machine:

Layout file:

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/ScrollView01"
     android:layout_width="fill_parent"
     android:layout_height="wrap_content">
<LinearLayout
 android:orientation="vertical"
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 >
 <TextView
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 android:textColor="#FF0000"
 android:text="CPU Info:"
 />
<TextView
 android:id="@+id/cpuinfo"
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 />
 <TextView
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 android:textColor="#0000FF"
 android:text="Memory Info:"
 />
<TextView
 android:id="@+id/memoryinfo"
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 />
</LinearLayout>
</ScrollView>

Main activity:

package com.softwarepassion;

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

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

public class CpuSpeed extends Activity {
private TextView cpuInfo;
private TextView memoryInfo;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
cpuInfo = (TextView) findViewById(R.id.cpuinfo);
cpuInfo.setText(getCPUinfo());
memoryInfo = (TextView)findViewById(R.id.memoryinfo);
memoryInfo.setText(getMemoryInfo());
}

private String getMemoryInfo(){
ProcessBuilder cmd;
String result = new String();

try{
String[] args = {"/system/bin/cat", "/proc/meminfo"};
cmd = new ProcessBuilder(args);

Process process = cmd.start();
InputStream in = process.getInputStream();
byte[] re = new byte[1024];
while(in.read(re) != -1){
System.out.println(new String(re));
result = result + new String(re);
}
in.close();
} catch(IOException ex){
ex.printStackTrace();
}
return result;
}
private String getCPUinfo()
{
ProcessBuilder cmd;
String result="";

try{
String[] args = {"/system/bin/cat", "/proc/cpuinfo"};
cmd = new ProcessBuilder(args);

Process process = cmd.start();
InputStream in = process.getInputStream();
byte[] re = new byte[1024];
while(in.read(re) != -1){
System.out.println(new String(re));
result = result + new String(re);
}
in.close();
} catch(IOException ex){
ex.printStackTrace();
}
return result;
}
}

You don’t need to modify anything inside AndroidManifest.xml file.

Android Series: Download files with Progress Dialog

Posted by admin | Posted in Code Snippets, Mobile Development | Posted on 05-02-2011

25

Today, I will present a short tutorial on how to download files in android displaying at the same time download progress based on the bytes downloaded. For the purpose of this tutorial we will use build in AsyncTask mechanism together with ProgressDialog class.
The whole application consists of one activity displaying a ‘Start Download’ button. Clicking our start button we initialize file download passing to the asynctask the url or the resource we want to download.


AndroAsync.java

package com.softwarepassion;

import java.io.BufferedInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLConnection;

import android.app.Activity;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class AndroAsync extends Activity {
   
    public static final int DIALOG_DOWNLOAD_PROGRESS = 0;
    private Button startBtn;
    private ProgressDialog mProgressDialog;
   
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        startBtn = (Button)findViewById(R.id.startBtn);
        startBtn.setOnClickListener(new OnClickListener(){
            public void onClick(View v) {
                startDownload();
            }
        });
    }

    private void startDownload() {
        String url = "http://farm1.static.flickr.com/114/298125983_0e4bf66782_b.jpg";
        new DownloadFileAsync().execute(url);
    }
    @Override
    protected Dialog onCreateDialog(int id) {
        switch (id) {
            case DIALOG_DOWNLOAD_PROGRESS:
                mProgressDialog = new ProgressDialog(this);
                mProgressDialog.setMessage("Downloading file..");
                mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
                mProgressDialog.setCancelable(false);
                mProgressDialog.show();
                return mProgressDialog;
            default:
                return null;
        }
    }
    class DownloadFileAsync extends AsyncTask<String, String, String> {
       
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            showDialog(DIALOG_DOWNLOAD_PROGRESS);
        }

        @Override
        protected String doInBackground(String... aurl) {
            int count;

            try {
                URL url = new URL(aurl[0]);
                URLConnection conexion = url.openConnection();
                conexion.connect();

                int lenghtOfFile = conexion.getContentLength();
                Log.d("ANDRO_ASYNC", "Lenght of file: " + lenghtOfFile);

                InputStream input = new BufferedInputStream(url.openStream());
                OutputStream output = new FileOutputStream("/sdcard/some_photo_from_gdansk_poland.jpg");

                byte data[] = new byte[1024];

                long total = 0;

                while ((count = input.read(data)) != -1) {
                    total += count;
                    publishProgress(""+(int)((total*100)/lenghtOfFile));
                    output.write(data, 0, count);
                }

                output.flush();
                output.close();
                input.close();
            } catch (Exception e) {}
            return null;

        }
        protected void onProgressUpdate(String... progress) {
             Log.d("ANDRO_ASYNC",progress[0]);
             mProgressDialog.setProgress(Integer.parseInt(progress[0]));
        }

        @Override
        protected void onPostExecute(String unused) {
            dismissDialog(DIALOG_DOWNLOAD_PROGRESS);
        }
    }
}

layout file (main.xml) :

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:orientation="vertical"
   android:layout_width="fill_parent"
   android:layout_height="fill_parent"
   >
<TextView  
   android:layout_width="fill_parent"
   android:layout_height="wrap_content"
   android:text="@string/hello"
   />
<Button
    android:text="Start long running task.."
    android:id="@+id/startBtn"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content">
</Button>
</LinearLayout>

While downloadin a file from the internet remember to add INTERNET permission in AndroidManifest.xml

<uses-permission android:name="android.permission.INTERNET" />

Check your sd card folder for what was downloaded and enjoy!

Design Patterns Series – Part Five: Adapter pattern

Posted by admin | Posted in Code Snippets, General Programming | Posted on 04-02-2011

1

According to wikipedia:

In computer programming, the adapter pattern (often referred to as the wrapper pattern or simply a wrapper) is a design pattern that translates one interface for a class into a compatible interface.

The adapter pattern is commonly used when there is a need to access an object through the interface which doesn’t match the one you need. This pattern is especially useful if you have a set of existing classes and you need to use them together with other ones, exposing different interface.


The purpose of this pattern is to make some objects look like something they are not. Normally, you wouldn’t use this pattern at the design stage but rather while extending an existing application, working with 3rd party libraries or tools.

Simple example using adapter pattern:
We have an existing class called ThirdPartyShape with a method ‘paintShape’ we want to move into a common interface.

package adapterpattern;

/**
 *
 * @author kris
 */

public class ThirdPartyShape {

    public void paintShape(){
        System.out.println("Painting 3rd party shape");
    }
}

Common interface in our new application:

package adapterpattern;

/**
 *
 * @author kris
 */

public interface ShinyShapeIfc {

    public void paint();
}

Example of standard shape class in our application:

package adapterpattern;

/**
 *
 * @author kris
 */

public class MyNewShinyShape implements ShinyShapeIfc{

    public void paint(){
        System.out.println("Painting brand new and shiny custom shape!");
    }
}

Adapter class used to utilize functionality of 3rd party class into our interface for painting shapes

package adapterpattern;

/**
 *
 * @author kris
 */

public class ShinyShape3rdpartyAdapter implements ShinyShapeIfc{

    private ThirdPartyShape thirdPartyShape;

    public ShinyShape3rdpartyAdapter(ThirdPartyShape tps){
        this.thirdPartyShape = tps;
    }
    /**
     * Method adapting 3rd party functionality into a common
     * interface
     */

    public void paint() {
        this.thirdPartyShape.paintShape();
    }

}

Simple proof of concept, using our shapes with existing 3rd party shapes by implementing and adapter pattern:

/**
 *
 * @author kris
 */

public class Main {

    /**
     * @param args the command line arguments
     */

    public static void main(String[] args) {
        ThirdPartyShape thirdPartyShape = new ThirdPartyShape();
        ShinyShapeIfc myOwnShinyShape = new MyNewShinyShape();
        //adapting 3rd party class into a common interface using an adapter
        ShinyShapeIfc adapted3rdPartyShape = new ShinyShape3rdpartyAdapter(thirdPartyShape);

        //object below implement common interface
        myOwnShinyShape.paint();
        adapted3rdPartyShape.paint();
    }

}

Android Series: Creating custom dialogs

Posted by admin | Posted in Code Snippets, Mobile Development | Posted on 03-02-2011

5

Every android developer will face one day a need to create a custom dialog, where the user has to input some data for processing or any other purposes. This post is a short tutorial on how to create a custom dialog in android, dimming the background activity and asking user to input a string for a search query.
Custom dialog is implemented as another activity and treated as dialog by using special option in AndroidManifest.xml (listed at the end of this post).
The whole application consists of two activities (main + custom dialog), two small layout xml files and a modified AndroidManifest.xml.


AndroDialog (main activity)

package com.softwarepassion;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class AndroDialog extends Activity {

private Button startDialogBtn;
private static final int MY_CUSTOM_DIALOG = 0;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
startDialogBtn = (Button)findViewById(R.id.startdialog);
startDialogBtn.setOnClickListener(new OnClickListener(){
public void onClick(View v) {
startCustomDialog();
}
});
}

/**
* Starts an Activity which in this case is a custom
* dialog, as specified in AndroidManifest.xml
*/

private void startCustomDialog() {
Intent intent = new Intent(this,SearchDialog.class);
startActivityForResult(intent, MY_CUSTOM_DIALOG);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch(requestCode) {
case (MY_CUSTOM_DIALOG) : {
if (resultCode == Activity.RESULT_OK) {
Log.d("ANDRO_DIALOG","Coming back from the search dialog..");
String searchQuery = data.getStringExtra(SearchDialog.SEARCH_QUERY_RESULT_FROM_DIALOG);
Log.d("ANDRO_DIALOG", "Search query result: " + searchQuery);
}
break;
}
}
}
}

main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
<TextView  
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="@string/hello"
    />
<Button android:text="Show Custom Dialog"
    android:id="@+id/startdialog"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content">
</Button>
</LinearLayout>

SearchDialog.java (custom dialog activity)

package com.softwarepassion;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.EditText;

public class SearchDialog extends Activity{

public static final String SEARCH_QUERY_RESULT_FROM_DIALOG = "SEARCH_DIALOG";
private Button searchBtn;
private Button cancelBtn;
private EditText searchEdit;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.custom_dialog);
searchBtn = (Button)findViewById(R.id.search);
searchBtn.setOnClickListener(new OnClickListener(){
public void onClick(View v) {
returnSearchQuery();
}
});
cancelBtn = (Button)findViewById(R.id.cancel);
cancelBtn.setOnClickListener(new OnClickListener(){
public void onClick(View v) {
cancelDialog();
}
});
searchEdit = (EditText)findViewById(R.id.search_query);
searchEdit.setText("query");
getWindow().setFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND,
WindowManager.LayoutParams.FLAG_BLUR_BEHIND);

}
private void returnSearchQuery(){
Intent resultIntent = new Intent(this, SearchDialog.class);
resultIntent.putExtra(SEARCH_QUERY_RESULT_FROM_DIALOG, searchEdit.getText().toString());
setResult(Activity.RESULT_OK, resultIntent);
finish();
}
private void cancelDialog(){
finish();
}
}

custom dialog xml layout

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:id="@+id/layout_root"
              android:orientation="vertical"
              android:layout_width="fill_parent"
              android:layout_height="fill_parent"
              android:padding="10dp">
    <EditText android:id="@+id/search_query"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"/>
    <LinearLayout android:orientation="horizontal"
    android:background="@android:drawable/bottom_bar" android:paddingLeft="4.0dip"
    android:paddingTop="5.0dip" android:paddingRight="4.0dip"
    android:paddingBottom="1.0dip" android:layout_width="fill_parent"
    android:layout_height="wrap_content">
    <Button android:id="@+id/search" android:layout_width="0.0dip"
        android:layout_height="fill_parent" android:text="Search"
        android:layout_weight="1.0" />
    <Button android:id="@+id/cancel" android:layout_width="0.0dip"
        android:layout_height="fill_parent" android:text="Cancel"
        android:layout_weight="1.0" />
</LinearLayout>
</LinearLayout>

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.softwarepassion"
      android:versionCode="1"
      android:versionName="1.0">
    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".AndroDialog"
                  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 android:name="SearchDialog"
          android:label="Search Dialog"
          android:theme="@android:style/Theme.Dialog"/>
    </application>
</manifest>

Hope this helps anyone needing to write a custom dialog for the android platform.