Google

Jul 30, 2013

Spring JMS with Websphere MQ (aka MQ Series) -- Part 1 (configuration)

Messaging systems are used in enterprise applications for scalability. Here is the series of JMS tutorials. Stay tuned for more parts to follow.



Step 1: Add the relevant dependency jars to the pom.xml file.

<!-- Spring -->
<dependency>
 <groupId>org.springframework</groupId>
 <artifactId>spring-jms</artifactId>
</dependency>
<!-- JMS/MQ -->
<dependency>
 <groupId>com.ibm.webshere.mq7</groupId>
 <artifactId>commonservices</artifactId>
</dependency>
<dependency>
 <groupId>com.ibm.webshere.mq7</groupId>
 <artifactId>com-ibm-mqjms</artifactId>
</dependency>
<dependency>
 <groupId>com.ibm.webshere.mq7</groupId>
 <artifactId>com-ibm-mq</artifactId>
</dependency>
<dependency>
 <groupId>com.ibm.webshere.mq7</groupId>
 <artifactId>dhbcore</artifactId>
</dependency>
<dependency>
 <groupId>com.ibm.webshere.mq7</groupId>
 <artifactId>com-ibm-mq-jmqi</artifactId>
</dependency>
<dependency>
 <groupId>javax.jms</groupId>
 <artifactId>jms</artifactId>
</dependency>
<dependency>
 <groupId>javax.jms</groupId>
 <artifactId>jms</artifactId>
</dependency>


Step 2: Define the JMS properties jms/internalConnection.properties as shown below

#connection factory properties
jms.transportType=1  # i.e. TCP
jms.hostName=your_host
jms.channel=your.channel
jms.port=1414
jms.queueManager=your.que.manager
jms.sslEnabled=false
jms.sslCipherSuite=
jms.ssl.keystore.path=
jms.ssl.password=
 
#destination property 
my.queueName=my.queue 


Step 3: An abstract class that configures the  ConnectionFactory.

package com.myapp.jms;

import java.util.Properties;

import javax.jms.ConnectionFactory;
import javax.jms.JMSException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.convert.support.ConfigurableConversionService;
import org.springframework.core.convert.support.DefaultConversionService;

import com.ibm.mq.jms.MQConnectionFactory;
import com.ibm.mq.jms.MQQueueConnectionFactory;

public class AbstractMqJmsConnectionConfig {

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

 private final ConfigurableConversionService conversionService = new DefaultConversionService();

 protected ConnectionFactory createQueueConnectionFactory(Properties properties) throws JMSException {
  MQQueueConnectionFactory connectionFactory = new MQQueueConnectionFactory();

  setConnectionFactoryProperties(connectionFactory, properties);

  return connectionFactory;
 }

 private void setConnectionFactoryProperties(MQConnectionFactory connectionFactory, Properties properties)
   throws JMSException {
    
  connectionFactory.setTransportType(conversionService.convert(properties.getProperty("jms.transportType"), Integer.class));
  connectionFactory.setHostName(properties.getProperty("jms.hostName"));
  connectionFactory.setChannel(properties.getProperty("jms.channel"));
  connectionFactory.setPort(conversionService.convert(properties.getProperty("jms.port"), Integer.class));
  connectionFactory.setQueueManager(properties.getProperty("jms.queueManager"));
  connectionFactory.setClientID(properties.getProperty("jms.clientid"));
  
  if (conversionService.convert(properties.getProperty("jms.sslEnabled"), Boolean.class)) {
   setSSLSystemProperties(properties);
   connectionFactory.setSSLCipherSuite(properties.getProperty("jms.sslCipherSuite"));
  }
 }

 private void setSSLSystemProperties(Properties properties) {
  String sslkeystoreFullPath = properties.getProperty("jms.ssl.keystore.path");
  LOG.info("Setting sslkeystoreFullPath : {}", sslkeystoreFullPath);
  System.setProperty("javax.net.ssl.keyStore", sslkeystoreFullPath);
  System.setProperty("javax.net.ssl.keyStorePassword", properties.getProperty("jms.ssl.password"));
 }

}

Note:  The  ConfigurableConversionService  utility class from spring is handy to convert string property values to relevant data types like Integer, Boolean, etc.

Step 4: Define the concrete class that loads the internalConnection.properties and has the Spring @Configuration annotation for the Spring dependency injection.

package com.myapp.jms;

import java.io.IOException;
import java.util.Properties;

import javax.jms.ConnectionFactory;
import javax.jms.JMSException;

import org.springframework.beans.factory.config.PropertiesFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;

@Configuration
public class InternalJmsConnectionFactoryConfig extends AbstractMqJmsConnectionConfig {
 
 
 @Bean (name="internalJmsConnectionFactory")
 protected ConnectionFactory createQueueConnectionFactory() throws JMSException, IOException {
  return createQueueConnectionFactory(internalUMJMSProperties());
 }
 

 private Properties internalJMSProperties() throws IOException {
  PropertiesFactoryBean factory = new PropertiesFactoryBean();
  factory.setLocation(new ClassPathResource("jms/internalConnection.properties"));
  factory.afterPropertiesSet();
  return factory.getObject();
 }
}


More on JMS

Labels: ,

Jul 26, 2013

Creating Java custom annotations with Spring aspectj AOP

There are situations where you want to retry a particular method that fails. For example, retry submitting a message to an messaging queue 3 times, retry external service calls, etc. AOP (Aspect Oriented Programming) is well suited for this as this is a cross cutting concern. In this tutorial, I use aspectj, spring-aop, and Java annotation. Here are the steps.

Step 1:  The pom.xml file to outline the dependency jar files.

<!-- Spring -->
<dependency>
 <groupId>org.springframework</groupId>
 <artifactId>spring-core</artifactId>
 <version>3.1.2.RELEASE</version>
</dependency>
<dependency>
 <groupId>org.springframework</groupId>
 <artifactId>spring-context</artifactId>
 <version>3.1.2.RELEASE</version>

</dependency>
<dependency>
 <groupId>org.springframework</groupId>
 <artifactId>spring-aop</artifactId>
 <version>3.1.2.RELEASE</version>
</dependency>
<dependency>
 <groupId>org.springframework</groupId>
 <artifactId>spring-context-support</artifactId>
 <version>3.1.2.RELEASE</version>
</dependency>

<dependency>
 <groupId>cglib</groupId>
 <artifactId>cglib</artifactId>
 <version>2.2</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
 <artifactId>spring-aspects</artifactId>
 <version>3.1.2.RELEASE</version>
</dependency>


<!-- Aspectj -->
<dependency>
 <groupId>org.aspectj</groupId>
 <artifactId>aspectjrt</artifactId>
 <version>1.6.11</version>
</dependency>

<dependency>
 <groupId>org.aspectj</groupId>
 <artifactId>aspectjweaver</artifactId>
 <version>1.6.10</version>
</dependency>


Step 2:Define the annotation -- RetryOnFailure.

package com.mycompany.app9;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(
{
    ElementType.METHOD, ElementType.TYPE
})
public @interface RetryOnFailure
{
    int attempts() default 3;
    
    int delay() default 1000; //default 1 second
}

Step 3: Define the aspect point cut implementation RetryOnFailureAspect.

package com.mycompany.app9;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.core.NestedRuntimeException;

@Aspect
public class RetryOnFailureAspect
{
    public static final String RETRY_LIMIT_EXCEEDED_MSG = "Retry limit exceeded.";
    
    @Around("execution(* *(..)) && @annotation(retry)")
    public Object retry(ProceedingJoinPoint pjp, RetryOnFailure retry) throws Throwable
    {
        
        Object returnValue = null;
        for (int attemptCount = 1; attemptCount <= (1 + retry.attempts()); attemptCount++)
        {
            try
            {
                returnValue = pjp.proceed();
            }
            catch (Exception ex)
            {
                handleRetryException(pjp, ex, attemptCount, retry);
            }
        }
        return returnValue;
    }
    
    private void handleRetryException(ProceedingJoinPoint pjp, Throwable ex,
            int attemptCount, RetryOnFailure retry) throws Throwable
    {
        
        if (ex instanceof NestedRuntimeException)
        {
            ex = ((NestedRuntimeException) ex).getMostSpecificCause();
        }
        
        if (attemptCount == 1 + retry.attempts())
        {
            throw new RuntimeException(RETRY_LIMIT_EXCEEDED_MSG, ex);
        }
        else
        {  
            System.out.println(String
                    .format("%s: Attempt %d of %d failed with exception '%s'. Will retry immediately. %s",
                            pjp.getSignature(), attemptCount,
                            retry.attempts(),
                            ex.getClass().getCanonicalName(),
                            ex.getMessage()));
        }
    }
}

Step 4: Now wire up aspectj and the annotation via Spring xml files.

Firstly, wire up aop via spring-aop.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:aop="http://www.springframework.org/schema/aop" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
 xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">

 <!-- Enable the @AspectJ support -->
 <aop:aspectj-autoproxy />

 <bean id="retryOnFailureAspect" class="com.mycompany.app9.RetryOnFailureAspect" />

</beans>

Next, the application context xml file springApplicationContext.xml


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
 xmlns:p="http://www.springframework.org/schema/p"
 xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

 <!-- Import your AspectJ config -->
 <import resource="classpath:spring-aop.xml" />

 <!-- Scan you spring services for annotations -->
 <context:component-scan base-package="com.mycompany.app9" />

</beans>


Step 5: Finally, the test class that uses this annotation. Forcefully throw an exception to see if the method is retried.

package com.mycompany.app9;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Component;

@Component
public class RetryOnFailureTest
{
    
    @RetryOnFailure(attempts = 3, delay = 2000)
    public void testRetry()
    {
        System.out.println("Entered ....................");
        throw new RuntimeException("Forcing an exception");
    }
    
    public static void main(String[] args)
    {
        final ApplicationContext context = new ClassPathXmlApplicationContext("springApplicationContext.xml");
        // Get me my spring managed bean
        final RetryOnFailureTest retryFailureTest = context.getBean(RetryOnFailureTest.class);
        retryFailureTest.testRetry();
    }
}

Step 6: The output will be


Jul 24, 2013 6:41:24 PM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@5e3974: startup date [Wed Jul 24 18:41:24 EST 2013]; root of context hierarchy
Jul 24, 2013 6:41:24 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [springApplicationContext.xml]
Jul 24, 2013 6:41:24 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [spring-aop.xml]
Jul 24, 2013 6:41:24 PM org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@1dc423f: defining beans [org.springframework.aop.config.internalAutoProxyCreator,retryOnFailureAspect,retryOnFailureTest,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.annotation.ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor#0]; root of factory hierarchy
Entered ....................
void com.mycompany.app9.RetryOnFailureTest.testRetry(): Attempt 1 of 3 failed with exception 'java.lang.RuntimeException'. Will retry immediately. Forcing an exception
Entered ....................
void com.mycompany.app9.RetryOnFailureTest.testRetry(): Attempt 2 of 3 failed with exception 'java.lang.RuntimeException'. Will retry immediately. Forcing an exception
Entered ....................
void com.mycompany.app9.RetryOnFailureTest.testRetry(): Attempt 3 of 3 failed with exception 'java.lang.RuntimeException'. Will retry immediately. Forcing an exception
Entered ....................
Exception in thread "main" java.lang.RuntimeException: Retry limit exceeded.
 at com.mycompany.app9.RetryOnFailureAspect.handleRetryException(RetryOnFailureAspect.java:43)
 at com.mycompany.app9.RetryOnFailureAspect.retry(RetryOnFailureAspect.java:26)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
 at java.lang.reflect.Method.invoke(Method.java:597)
 at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:621)
 at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:610)
 at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:65)
 at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:161)
 at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:90)
 at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
 at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:622)
 at com.mycompany.app9.RetryOnFailureTest$$EnhancerByCGLIB$$4086c6b6.testRetry()
 at com.mycompany.app9.RetryOnFailureTest.main(RetryOnFailureTest.java:23)
Caused by: java.lang.RuntimeException: Forcing an exception
 at com.mycompany.app9.RetryOnFailureTest.testRetry(RetryOnFailureTest.java:15)
 at com.mycompany.app9.RetryOnFailureTest$$FastClassByCGLIB$$e37240e1.invoke()
 at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:191)
 at org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation.invokeJoinpoint(Cglib2AopProxy.java:689)
 at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
 at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:80)
 at com.mycompany.app9.RetryOnFailureAspect.retry(RetryOnFailureAspect.java:22)
 ... 13 more


Labels: ,

Jul 25, 2013

Core Java Executor Service (Thread Pool) Tutorial



Here is a simple code that uses a thread pool of 3 threads to output a list. A stop watch is used to measure the time.

package com.mycompany.app8;

import java.util.Arrays;
import java.util.List;

public class ExecutorServiceTest
{
    
    public static void main(String[] args)
    {
        MyBusinessService bs = new MyBusinessServiceImpl();
        
        for (int i = 0; i < 3; i++)
        {
            List<String> items = Arrays.asList("Java", "JEE", "JDBC", "EJB");
            bs.process(items);
        }
        
    }  
}


package com.mycompany.app8;

import java.util.List;

public interface MyBusinessService
{
    abstract void process(List<String> values);
    
    abstract void shutdownAndAwaitTermination();
}


package com.mycompany.app8;

import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.apache.camel.util.StopWatch;

public class MyBusinessServiceImpl implements MyBusinessService
{
    
    private ExecutorService threadPool;
    
    public MyBusinessServiceImpl()
    {
        init();
    }
    
    void init()
    {
        threadPool = Executors.newFixedThreadPool(3);
    }
    
    public void process(final List<String> values)
    {
        threadPool.execute(new Runnable()
        {
            
            public void run()
            {
                StopWatch watch = new StopWatch();
                String threadName = Thread.currentThread().getName();
                System.out.println(threadName + " --> " + values);
                System.out.println(threadName + " --> elapse time:" + watch.stop());
                
            }
            
        });
    }
    
}

The output will be:

pool-1-thread-2 --> [Java, JEE, JDBC, EJB]
pool-1-thread-3 --> [Java, JEE, JDBC, EJB]
pool-1-thread-3 --> elapse time:0
pool-1-thread-1 --> [Java, JEE, JDBC, EJB]
pool-1-thread-2 --> elapse time:0
pool-1-thread-1 --> elapse time:0


Q. what is missing from the above?
A. The thread pool does not shut down. The shut down logic can be added as shown below.


Add the following method to MyBusinessServiceImpl class.

 public void shutdownAndAwaitTermination()
    {
        final int timeout = 60;
        final TimeUnit timeoutUnit = TimeUnit.SECONDS;
        threadPool.shutdown(); // Disable new tasks from being submitted
        try
        {
            // Wait a while for existing tasks to terminate
            if (!threadPool.awaitTermination(timeout, timeoutUnit))
            {
                threadPool.shutdownNow(); // Cancel currently executing tasks
                // Wait a while for tasks to respond to being cancelled
                if (!threadPool.awaitTermination(timeout, timeoutUnit))
                {
                    System.out.println("MyBusinessServicee did not terminate");
                }
            }
        }
        catch (InterruptedException ie)
        {
            // (Re-)Cancel if current thread also interrupted
            threadPool.shutdownNow();
            // Preserve interrupt status
            Thread.currentThread().interrupt();
        }
    }
    

The ExecutionServiceTest will invoke this method.

package com.mycompany.app8;

import java.util.Arrays;
import java.util.List;

public class ExecutorServiceTest
{ 
    public static void main(String[] args)
    {
        MyBusinessService bs = new MyBusinessServiceImpl();
        
        for (int i = 0; i < 3; i++)
        {
            List<String> items = Arrays.asList("Java", "JEE", "JDBC", "EJB");
            bs.process(items);
        }
        
        bs.shutdownAndAwaitTermination();
    } 
}

Note: The Google library has a StopWatch class (com.google.common.base.Stopwatch) as well.

Labels: ,

Jul 24, 2013

Merging code with subversion, and things you must know



Branching and merging in Subversion is very common in large projects, but it has a reputation for being so difficult so that many developers either hate performing these tasks or do it incorrectly. Here are some questions and answers style tips to perform these tasks with a greater understanding.

Q. When will you merge code from a branch to trunk?
A. Merging from a branch to trunk is done
  • When you’ve finished development in your branch, and 
  • When you no longer need the branch.
So, only perform this merge when you are completely finished with your branch!  After merging your branch into trunk, you will no longer be able to use your branch.  In fact, you should delete your branch after merging it into trunk. If you want to add further new features, then create a new branch from your trunk.

This process of merging code from a branch to trunk is also known as "reintegrate". The diagram below shows that "Tortoise SVN" and "Eclipse SVN client" providing the initial merge options, and reintegration is one of them. You can only reintegrate a branch to trunk, after you have rebased your branch with changes in the trunk.



Q. What are the key steps involved in merging code from branch to a trunk?
A

Step 1: Firstly, merge trunk into your branch and commit any changes to your branch. This is a very important step as you need to make sure your branch is consistent with trunk before merging it back.

This is also known as re-basing.



You can either select a range of revisions to merge or leave it empty to merge all the revisions.

Step 2:  Commit rebased changes in your feature branch to the subversion.

Step 3: Checkout the trunk.

Step 4: Reintegrate your feature branch into trunk.

Step 5: Build and test your merged code.

Step 6: Commit the code into SVN.

Step 7: You can delete the branch.  As mentioned earlier, after merging a branch into trunk, the branch can no longer be used.  Subversion keeps track of merges using the svn:mergeinfo property.  Because of the way it uses this property, once a branch is merged into trunk it can no longer be involved in merges properly.


Tip: Copy trunk to a new branch, merge it with feature branch/s. When things done, merge the new branch back to the trunk. This technique is quite like the mercurial and git rebasing. 


Q. What do you understand by the term "working copy"?
A. It is the local copy that you had checked out. Your local working copy reflects some directory in the remote Subversion repository. For example, if you had checked out from a trunk, then trunk is your working copy, and if you had checked out from a branch, then branch is your working copy. Once you make changes to you working copy, you can commit them to the SVN. If you check your local working copy folders, you will see ".svn" folders that contain info about the SVN.

Q. What if you had made a mistake during your merge?
A. You can use the "revert" function to bring in the latest code from the SVN and overwrite your working copy. This means, undoing your uncommitted changes.

You can also switch between branches and trunk.

Labels: ,

Jul 23, 2013

5 Handy Firefox browser plugins for web developers




The trend to develop single page web applications with MVC or MVVM frameworks like Angular requires good tools and plugins to debug and isolate issues on client side. On the previous tutorial I covered writing JavaScript functions and debugging it with the FireBug plugin for Firefox. In this blog post, I will cover 5 handy Firefox plugins that can make you more productive in fixing issues relating client side code like JavaScript errors, effective CSS applied, HTML errors, etc and client to server interactions like what header was sent? what data was posted?, etc
  1. FireBug
  2. Fire Cookie
  3. YSlow
  4. Tamper Data
  5. Modify Headers
There are other useful plugins like modify headers, HTML validator, etc.

  1. FireBug is  handy to debug and tune client side HTML, CSS, and JavaScript on the fly.
  2. Fire Cookie makes possible to view and manage cookies in your browser. Especially, you can modify and delete cookies.
  3. YSlow analyzes web pages and suggests ways to improve their performance based on a set of rules for high performance web pages. YSlow is an extension to FireBug, and you need to install FireBug before installing YSlow. The YSlow grades your web application and provides recommendations to improve performance. Alternatively, you can also install Page Speed from Google. Similar to Yslow!, it tests website performance.
  4. Tamper Data is a fast, simple yet effective tool which can be used to do penetration testing. Use tamper data to view and modify HTTP/HTTPS headers, trace and time http response/requests and to security test web applications by modifying the POST parameters.
  5. Modify Headers is handy for modifying or adding new headers for testing purpose. For example, add SSO headers to test your application locally.

The FireBug has other developer productivity tools natively within Tools --> Web Developer

Native Inspect Element

This native "Inspect Element" from Firefox may look similar to “Inspect Element in Firebug”, but it  acts in different ways. There is one distinctive feature known as the the 3D view, which analyses the web page in depth.


Responsive Design View

This native "Responsive Design View " assists with the Responsive Website Design (i.e. RWD). With more and more mobile users online via smartphones and tablets, it has never been more important to design a friendly environment for those visitors. A responsive website design allows your visitors to navigate to your site that is optimally designed for the device they are using like smartphone, tablet, or laptop/desktop, without having to painfully zoom in and zoom out.


Style Editor

If you work frequently with CSS then the "style editor" is very handy as it allows you to edit the CSS and see the impact of your change instantly. This is available from version 11.


Here are some step by step tutorials on using FireBug:

Labels:

Jul 19, 2013

Core Java multi-thread coding -- printing odd and even numbers with two threads and a blocking queue

Core Java Coding Questions and Answers for beginner to intermediate level

Q1 Q2 Q3 Q4 Q5 Q6

This is an alternative approach using a blocking queue compared to using an AtomicInteger and a lock.

Q. Can you write code to print odd and even numbers by two threads in sequence?
A. Even though this is not a practical question, a handy beginner level question test your ability to write multi-threaded code.

Considerations:

Use a blocking queue: A BlockingQueue is used to have one thread produce objects, which another thread consumes.T he producing thread will keep producing new objects and insert them into the queue, until the queue reaches some upper bound on what it can contain. If the blocking queue reaches its upper limit, the producing thread is blocked while trying to insert the new object. The consuming thread keeps taking objects out of the blocking queue, and processes them. If the consuming thread tries to take an object out of an empty queue, the consuming thread is blocked until a producing thread puts an object into the queue.

You can use 2 blocking queues -- one for odd numbers and another for the even numbers.

Step: 1: Put 1 into the odd queue.

Step 2: The odd number thread 
  • takes the number out of the odd number queue
  • prints the odd number
  • increments the number by 1
  • puts the even number in the even number queue.
  • when the queue is empty, it is blocked.

Step 3: Similarly,  The even number thread

  • takes the number out of the even number queue
  • prints the even number
  • increments the number by 1
  • puts the odd number in the even number queue.
  • when the queue is empty, it is blocked. 

Here is the diagram that  depicts this.



Finally, here is the working code.

Step 1: The main class OddAndEvenSignalling. 



  
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;

public class OddAndEvenSignalling
{
    
    private static final int MAX_NUMBER = 10;
    
    public static void main(String[] args)
    {
        BlockingQueue<Integer> odds = new LinkedBlockingQueue<Integer>();
        BlockingQueue<Integer> evens = new LinkedBlockingQueue<Integer>();
        ExecutorService executorService = Executors.newFixedThreadPool(2);
        
        //odd numbers are removed from the "from" queue --> printed --> incremented --> placed on the "to" queue by one thread
        //"from" queue is "odd number" queue and "to" queue is "even number" queue
        executorService.submit(new TakeAndOfferNext(odds, evens, MAX_NUMBER));
        
        //even numbers are removed from the "from" queue --> printed --> incremented --> placed on the "to" queue by another thread
        //"from" queue is "even number" queue and "to" queue is "odd number" queue
        executorService.submit(new TakeAndOfferNext(evens, odds, MAX_NUMBER));
        odds.offer(1);
    }
}


Step 2: The callable class TakeAndOfferNext that executes the logic as depicted in the diagram.


  
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Callable;

public class TakeAndOfferNext implements Callable<Object>
{
    
    BlockingQueue<Integer> takeFrom;
    BlockingQueue<Integer> offerTo;
    int maxNumber;
    
    public TakeAndOfferNext(BlockingQueue<Integer> takeFrom, BlockingQueue<Integer> offerTo, int maxNumber)
    {
        this.takeFrom = takeFrom;
        this.offerTo = offerTo;
        this.maxNumber = maxNumber;
    }
    
    public Object call() throws Exception
    {
        print();
        return null;
    }
    
    public void print()
    {
        while (true)
        {
            try
            {
                int i = takeFrom.take(); //removes the value in the "from" queue
                System.out.println(Thread.currentThread().getName() + " --> " + i);
                offerTo.offer(i + 1);    //increments the value by 1 and puts it in the "to" queue.
                if (i >= (maxNumber - 1))
                {
                    System.exit(0);
                }
            }
            catch (InterruptedException e)
            {
                throw new IllegalStateException("Unexpected interrupt", e);
            }
        }
    }
    
}


Step 3: The output

  
pool-1-thread-2 --> 1
pool-1-thread-1 --> 2
pool-1-thread-2 --> 3
pool-1-thread-1 --> 4
pool-1-thread-2 --> 5
pool-1-thread-1 --> 6
pool-1-thread-2 --> 7
pool-1-thread-1 --> 8
pool-1-thread-2 --> 9
pool-1-thread-1 --> 10


Labels: ,

Jul 18, 2013

Core Java multi-thread coding -- printing odd and even numbers with two threads



Q. Can you write code to print odd and even numbers by two threads in sequence?
A. Even though this is not a practical question, a handy beginner level question test your ability to write multi-threaded code.

Here are the considerations.

  • It needs to be atomic so that the numbers can be printed in sequence. You can use either the AtomicInteger class or maintain two boolean flags like oddPrinted and evenPrinted  to coordinate between the two threads.
  • Both threads need to have a lock to coordinate odd and even printing. In Java, every object has a lock. So, we can create a Object lock = new Object( ) as the lock for both threads to use.
  • The Java Object class has wait and notify/notifyAll methods to facilitate inter thread communication via the Object lock. The notify/notifyAll methods notify the waiting threads to get hold of the lock. Only one thread can execute the code snippet that is synchronized on the lock.
  • You need a main method that creates a main thread and then spawn two new threads to print odd and even numbers respectively. 
 Here is the sample code.

Step 1: The main thread class PrintOddEvenNumbersWithTwoThreads that spawns the two new threads via the thread pool.

  
package com.mycompany.app6;

import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * main thread
 */
public class PrintOddEvenNumbersWithTwoThreads
{
    public static void main(String[] args)
    {
        final int max = 10;
        final AtomicInteger i = new AtomicInteger(1); //start with 0
        Executor dd = Executors.newFixedThreadPool(2);
        
        final Object lock = new Object();
        
        //the main thread spawns two threads to print odd and even numbers respectively
        dd.execute(new OddNumber(max, i, lock));
        dd.execute(new EvenNumber(max, i, lock));
        
        do
        {
            try
            {
                Thread.sleep(1000);
            }
            catch (InterruptedException e)
            {
                e.printStackTrace();
            }
        }
        
        while (i.get() != max + 1);
        
        System.out.println("\nDone");
        System.exit(0);
    }
}


Step 2: The OddNumber thread that prints odd numbers.

  
package com.mycompany.app6;

import java.util.concurrent.atomic.AtomicInteger;

public class OddNumber implements Runnable
{
    private int maxNumber;
    private AtomicInteger number;
    private Object lock;
    
    public OddNumber(int maxNumber, AtomicInteger number, Object lock)
    {
        this.maxNumber = maxNumber;
        this.number = number;
        this.lock = lock;
    }
    
    public void run()
    {
        print();
    }
    
    public void print()
    {
        while (number.get() < maxNumber + 1)
        {
            if (number.get() % 2 == 0)
            {
                System.out.println(Thread.currentThread().getName() + " --> " + number.getAndAdd(1));
                
                synchronized (lock)
                {
                    lock.notifyAll();//notify all waiting threads on this lock to resume 
                }
            }
            else
            {
                synchronized (lock)
                {
                    try
                    {
                        lock.wait(); //wait for the lock
                    }
                    catch (InterruptedException e)
                    {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    
}



Step 3: The EvenNumber thread that prints even numbers. The implementation is very similar except for the boundary condition that checks for odd or even number.

  
package com.mycompany.app6;

import java.util.concurrent.atomic.AtomicInteger;

public class EvenNumber implements Runnable
{
    private int maxNumber;
    private AtomicInteger number;
    private Object lock;
    
    public EvenNumber(int maxNumber, AtomicInteger number, Object lock)
    {
        this.maxNumber = maxNumber;
        this.number = number;
        this.lock = lock;
    }
    
    public void run()
    {
        print();
    }
    
    public void print()
    {
        while (number.get() < maxNumber + 1)
        {
            if (number.get() % 2 != 0)
            {
                System.out.println(Thread.currentThread().getName() + " --> " + number.getAndAdd(1));
                
                synchronized (lock)
                {
                    lock.notify(); //notify all waiting threads on this lock to resume 
                }
            }
            else
            {
                synchronized (lock)
                {
                    try
                    {
                        lock.wait();  //wait for the lock
                    }
                    catch (InterruptedException e)
                    {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    
}





Step 4: Run the main thread class PrintOddEvenNumbersWithTwoThreads to execute the code.

The output:

  
pool-1-thread-2 --> 1
pool-1-thread-1 --> 2
pool-1-thread-2 --> 3
pool-1-thread-1 --> 4
pool-1-thread-2 --> 5
pool-1-thread-1 --> 6
pool-1-thread-2 --> 7
pool-1-thread-1 --> 8
pool-1-thread-2 --> 9
pool-1-thread-1 --> 10

Done



There are other alternative approaches as described in the NumberGenerator class.

Labels: ,

Jul 17, 2013

Spring Batch code snippets

This post compliments some of the other Spring batch tutorials Spring batch part1 and Spring batch part 2 and Spring batch advanced.



A sample spring context file (e.g. applicationContext-test.xml)

  
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:batch="http://www.springframework.org/schema/batch"
 xmlns:task="http://www.springframework.org/schema/task" xmlns:context="http://www.springframework.org/schema/context"
 xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop"
 xmlns:int="http://www.springframework.org/schema/integration"
 xmlns:p="http://www.springframework.org/schema/p"
 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
 http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd
 http://www.springframework.org/schema/batch http://www.springframework.org/schema/batch/spring-batch.xsd
 http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
 http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration-2.0.xsd
 http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
 
    <bean id="jdbcTestTemplate" class="org.springframework.jdbc.core.JdbcTemplate" p:dataSource-ref="dataSource" />
 <bean id="myappDao" class="myapp.dao.MyappDaoImpl" />
 <bean id="myappFeedDao" class="myapp.dao.MyappDaoImpl" />
 
 
 <bean id="jobRepository" class="myapp.batch.repository.support.NoopJobRepository"/>
 
 <bean id="jobExecutorThreadPool"
  class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
  <property name="corePoolSize" value="1" />
  <property name="threadNamePrefix" value="jobExecutorThread-" />
 </bean>
 
 <bean id="jobLauncher"
  class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
  <property name="jobRepository" ref="jobRepository" />
  <!-- <property name="taskExecutor" ref="jobExecutorThreadPool" /> -->
 </bean>
 
 <job id="myappJob" xmlns="http://www.springframework.org/schema/batch">
  <listeners>
   <listener ref="myappJobExecutionListener" />
  </listeners>
  <step id="loadMyappFeedData" >

   <tasklet transaction-manager="txnManager">
    <listeners>
     <listener ref="stepExecutionListener" />
     <listener ref="myappFileImportListener" />
    </listeners>

    <chunk reader="groupCfDetailsReader" writer="myappFileItemWriter"
     commit-interval="1" />
   </tasklet>
  </step>
 </job>
 
 
    <!-- ============= readers, writers and listeners ============== -->
 <bean id="myappFileItemReader" class="org.springframework.batch.item.file.FlatFileItemReader" scope="step">
  <property name="resource" value="#{jobParameters['dataFileName']}" />
   
  <property name="lineMapper">
   <bean class="org.springframework.batch.item.file.mapping.DefaultLineMapper">
    <property name="lineTokenizer">
     <bean
      class="org.springframework.batch.item.file.transform.DelimitedLineTokenizer">
      <property name="names"
       value="accountCd,currency,txnCd, amount" />
     </bean>
    </property>
    <property name="fieldSetMapper">
     <bean
      class="myapp.mapper.MyappFieldSetMapper" />
    </property>
   </bean>
  </property>
  <property name="linesToSkip" value="1" />
  <property name="skippedLinesCallback" ref="cfFileHeaderLineCallbackHandler" />

 </bean>

 <bean id="groupCfDetailsReader"
  class="myapp.item.reader.MyappItemReader">
  <property name="delegate" ref="myappFileItemReader" />
 </bean>

 <bean id="myappFileItemWriter"
  class="myapp.item.writer.MyappItemWriter" />
  
  <bean id="myappMetaFileItemWriter"
  class="myapp.item.writer.MyappMetaFileItemWriter" />

 <bean id="stepExecutionListener"
  class="myapp.util.StepExecutionListenerCtxInjecter" />
  
    <bean id="myappFileImportListener"
  class="myapp.listener.MyappFileImportListener"
  scope="step" />
 
</beans>


Q. How do you kick off a batch job?
A. Here is an example of a test class kicking off the batch job. It also demonstrates how to add job parameters like "dataFileName". The "jobLauncher" and "myappJob" are injected from the above context file.

 
package myapp.batch.myapp;
//..
import java.math.BigDecimal;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.annotation.Resource;

import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.JobParametersBuilder;
import org.springframework.batch.core.JobParametersInvalidException;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException;
import org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException;
import org.springframework.batch.core.repository.JobRestartException;
import org.springframework.batch.test.StepScopeTestExecutionListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestExecutionListeners;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
import org.springframework.test.context.transaction.TransactionConfiguration;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

@RunWith(SpringJUnit4ClassRunner.class)
@TestExecutionListeners(
{
    DependencyInjectionTestExecutionListener.class, StepScopeTestExecutionListener.class
})
@TransactionConfiguration(transactionManager = "txManager", defaultRollback = true)
@Transactional
@ContextConfiguration(locations =
{"/applicationContext-test.xml"
})

public class MyappBatchJobTest
{
    
    private final static Logger logger = LoggerFactory.getLogger(MyappBatchJobTest.class);
    
 private static final String BATCH_JOB_ID_FIELD_NAME = "batchJobIdFieldName";
    private static final String BATCH_JOB_ID_FIELD_VALUE = "batchJobId";
    private static final String BATCH_ID = "batchId";
    
    @Autowired
    private JobLauncher jobLauncher;
    
    @Resource(name = "myappJob")
    private Job job;
    

    public int kickOffTheBatchJob(String dataFileName)
            throws JobExecutionAlreadyRunningException,
            JobRestartException, JobInstanceAlreadyCompleteException, JobParametersInvalidException, ParseException
    {
        
  //Adding job paramters
        JobParameters jobParameters = new JobParametersBuilder()
                .addString("dataFileName", dataFileName)
                .addString("metaDataFileName", metadataFileName)
                .addString(BATCH_JOB_ID_FIELD_NAME, BATCH_JOB_ID_FIELD_VALUE)
                .addString(BATCH_ID, getBatchId())
                .addDate("valuationDate", getValuationDate())
                .addLong("parentBatchJobId", PARENT_BATCHJOB_ID)
                .toJobParameters();
        
        JobExecution jobExecution = jobLauncher.run(job, jobParameters);
        
        int batchJobId = jobExecution.getExecutionContext().getInt("batchJobId");
        
        logger.info("The cash forecast batch job has started ................");
        
        if (positiveTest)
        {
            Assert.assertEquals("job failed: ", "COMPLETED", jobExecution.getExitStatus().getExitCode());
        }
        else
        {
            Assert.assertEquals("job should have failed: ", "FAILED", jobExecution.getExitStatus().getExitCode());
        }
        Assert.assertTrue("Batch job Id is not created: ", batchJobId >= 1);
        
        batchJobIds.add(batchJobId);
        
        return batchJobId;
    }
}


Q. How will you write a custom reader that reads data in chunks as shown below?

Each account has an OPENBAL txnCd record followed by 0 or more transactional records for that account.


A. Here is the custom reader "groupCfDetailsReader" that chunks and delegates each record to "myappFileItemReader" as defined in the above context file.

1. Custom file handler that groups records

 
package myapp.item.reader;

import java.util.ArrayList;

import org.springframework.batch.item.ExecutionContext;
import org.springframework.batch.item.ItemStreamException;
import org.springframework.batch.item.ItemStreamReader;
import org.springframework.batch.item.ParseException;
import org.springframework.batch.item.UnexpectedInputException;

import myapp.model.MyappDetail;
import myapp.model.MyappParent;

public class MyappItemReader implements ItemStreamReader<MyappParent> {

 private ItemStreamReader<MyappDetail> delegate;
 private MyappDetail curItem = null;

 @Override
 public MyappParent read() {
  MyappParent parent = null;
  try {

   if (curItem == null) {
    curItem = delegate.read();
   }

   if (curItem != null) {
    parent = new MyappParent();
    parent.setBalanceDetail(curItem);
   }

   curItem = null;

   if (parent != null) {
    parent.setTxnDetails(new ArrayList<MyappDetail>());
    MyappDetail detail = peek();
    while (detail != null && !"OPENBAL".equalsIgnoreCase(peek().getTxnCd())) {
     parent.getTxnDetails().add(curItem);
     curItem = null;
     detail = peek();
    }
   }

  }

  catch (Exception e) {
   e.printStackTrace();
  }

  return parent;
 }

 public MyappDetail peek() throws Exception, UnexpectedInputException, ParseException {
  if (curItem == null) {
   curItem = delegate.read();
  }

  return curItem;
 }

 @Override
 public void close() throws ItemStreamException {
  delegate.close();
 }

 @Override
 public void open(ExecutionContext arg0) throws ItemStreamException {
  delegate.open(arg0);
 }

 @Override
 public void update(ExecutionContext arg0) throws ItemStreamException {
  delegate.update(arg0);

 }

 public void setDelegate(ItemStreamReader<MyappDetail> delegate) {
  this.delegate = delegate;
 }
}


2. The model classes used to map data to Java POJOs. The container class.

 
package myapp.model;

import java.io.Serializable;
import java.util.List;

public class MyappParent implements Serializable {

 private static final long serialVersionUID = 1L;
 
 private String metaData;
 private MyappDetail balanceDetail;
 private List<MyappDetail> txnDetails;
 
 public MyappDetail getBalanceDetail() {
  return balanceDetail;
 }
 public void setBalanceDetail(MyappDetail balanceDetail) {
  this.balanceDetail = balanceDetail;
 }
 public List<MyappDetail> getTxnDetails() {
  return txnDetails;
 }
 public void setTxnDetails(List<MyappDetail> txnDetails) {
  this.txnDetails = txnDetails;
 }
 
 public String getMetaData() {
  return metaData;
 }
 public void setMetaData(String metaData) {
  this.metaData = metaData;
 }
 
 @Override
 public String toString() {
  return "MyappHeader [balanceDetail=" + balanceDetail + ", txnDetails=" + txnDetails + "]";
 }
}

The detail class that represents each record.

 
package myapp.model;

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;

public class MyappDetail implements Serializable
{    
    private static final long serialVersionUID = 1L;
  
    private String accountCd;
 private String currencyCd;
    private String txnCd;
    private BigDecimal amount;
    
 //getters, setters, etc  
}

3. The mapper class that maps data to POJO model defined above.

 
package myapp.mapper;

import myapp.model.MyappDetail;

import java.math.BigDecimal;
import java.text.ParseException;

import org.apache.commons.lang.time.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.item.file.mapping.FieldSetMapper;
import org.springframework.batch.item.file.transform.FieldSet;
import org.springframework.validation.BindException;

public class MyappFieldSetMapper implements FieldSetMapper<MyappDetail>
{
    private final static Logger logger = LoggerFactory.getLogger(MyappFieldSetMapper.class);
    
    private static final String DATE_FORMAT = "dd/MM/yyyy";
    
    @Override
    public MyappDetail mapFieldSet(FieldSet fs) throws BindException
    { 
        if (fs == null)
        {
            return null;
        }
        
        MyappDetail appd = new MyappDetail();
        appd.setAccountCd(fs.readString("accountCd"));
  appd.setCurrencyCd(fs.readString("currency"));
        appd.setTxnCd(fs.readString("txnCd"));
        BigDecimal amount = fs.readBigDecimal("amount");
        appd.setAmount(amount != null ? amount : BigDecimal.ZERO);  
       
        return appd;        
    } 
}


Labels:

Jul 16, 2013

Java Security Interview Questions and Answers: Single Sign-On (i.e. SSO) with Spring 3 Security

Q. Can you provide a high level overview of the "access control security" in a recent application you had worked?
A. As shown below, SiteMinder is configured to intercept the calls to authenticate the user. Once the user is authenticated, a HTTP header "SM_USER" is added with the authenticated user name. For example "123". The user header is passed to Spring 3 security. The "Security.jar" is a custom component that knows how to retrieve user roles for a given user like 123 from a database or LDAP server. This custom component is responsible for creating a UserDetails Spring object that contains the roles as authorities. Once you have the authorities or roles for a given user, you can restrict your application URLs and functions to provide proper access control.







Q. What is SSO (i.e. Single Sign-ON)?
A. Single sign-on (SSO) is a session/user authentication process that permits a user to enter one name and password in order to access multiple applications. The process authenticates the user for all the applications they have been given rights to and eliminates further prompts when they switch applications during a particular session. For example, SiteMinder, TivoliAccessManager (i.e. TAM), etc provides SSO. As shown in the diagram above SiteMinder authenticates the user and adds the SM_USER HTTP header to the application. It removes all the "SM" headers and add them after authenticating the user. This prevents amy malicious headers being injected via the browser with plugins like "Firefox Modify headers".


Q. How will you go about implementing authentication and authorization in a web application?
A. Use SSO application like SIteminder or Tivoli Access Manager to authenticate users, and Spring security 3 for authorization as described in the following Spring 3 security tutorials. Spring security pre-authentication scenario assumes that a valid authenticated user is available via  either Single Sign On (SSO) applications like Siteminder, Tivoli, etc or a X509 certification based authentication. The Spring security in this scenario will only be used for authorization. The links to the tutorials below demonstrates this with code.


Q. Can you describe your understanding of SSL, key stores, and trust stores?
ASSL, key stores and trust stores


Q. What tools do you use to test your application for security holes?
A. These tests are known as PEN (i.e. penetration) testing or security vulnerability testing. There are tools like
  • SkipFish (web application security scanner) from Google.
  • Tamper data from Firefox. 

Q. What is a two factor authentication?
A. Two-factor authentication is a security process in which the user provides two means of identification. This includes
  • something you have and something you know. For example, a bank card is which something you have and a PIN (i.e. Personal Identification Number) is something you know.
  • two forms of identification like password and a biometric data like finger print or voice print. Some security procedures now require three-factor authentication, which involves possession of a physical token and a password, used in conjunction with biometric data. 
Q. What are the different layers of security?
A.

Application-Layer Security: For example, Spring 3 Security, JAAS (Java Authentication and Authorization) that provides a set of APIs to provide authentication and authorization (aka access control), etc. JAAS provides pluggable and extendable  framework for programmatic user authentication and authorization at the JSE level (NOT JEE level). JAAS provides security at the JVM level (e.g. classes, resources). JAAS is the the core underlying technology for JEE Security. Spring security tackles security at the JEE level (e.g. URLs, Controller methods, service methods, etc)

Transport-Layer Security: Java Secure Sockets Extension (JSSE) provides a framework and an implementation for a Java version of the Secure Sockets Layer (SSL) and Transport Layer Security (TLS) protocols and includes functionality for data encryption, server authentication, message integrity, and optional client authentication to enable secure Internet communications. (TLS) 1.0 / (SSL) 3.0, is the mechanism to provide private, secured and reliable communication over the internet between the client and the server. It is the most widely used protocol that provides HTTPS for internet communications between the client (web browsers) and web servers.

Message-Layer Security: In message-layer security, security information is contained within the SOAP message and/or SOAP message attachment, which allows security information to travel along with the message or attachment. For example, the credit card number is signed by a sender and encrypted for a particular receiver to decrypt. Java Generic Security Services (Java GSS-API) is a token-based API used to securely exchange messages between communicating applications. The GSS-API offers application programmers uniform access to security services on top of a variety of underlying security mechanisms, including Kerberos. The advantage of this over point to point transport layer security is that the security stays with the message over all hops and after the message arrives at its destination. So, it can be used with intermidiaries over multiple hops and protocols (e.g. HTTP, JMS, etc). The major disadvantage is that it is more complex to implement and requires more processing.

Note: Simple Authentication and Security Layer (SASL) is a framework for authentication and data security in Internet protocols.  SASL is an Application-Layer security that supports TLS to compliment the services offered SASL.

Note: The Java security API is complicated and Spring security as demonstrated via the above tutorials might be a better alternative.

Labels: , ,

Jul 15, 2013

JasperReports xls download via Spring MVC



This is an extension to the JasperReport step by step tutorial to demonstrate how to generate an Excel file. This extends the tutorial on stand-alone excel file to demonstrate how to produce xls as a file attachment via Spring MVC RESTful service call.

The controller class will be something like

 
//...
@Controller
public class MyApproller
{

    @Resource(name = "myAppService")
    private MyAppService myAppService;
 
 @Resource(name = "reportWriter")
    private ReportWriter reportWriter;

 @RequestMapping(
            value = "/person.xls",
            method = RequestMethod.GET,
            produces = "application/vnd.ms-excel")
 @ResponseBody
 public void getCashForecastCSV(HttpServletResponse response) throws Exception
 {
  //get the report data from the service layer
  Collection<Person> reportData = myAppService.getReportData();
  
  //get the parameters as a Map from the service layer
  Map<String, Object> reportParameters = myAppService.getReportParameters();
  
  //generate the xls report 
  byte[] xlsAsStringForPerson = reportWriter.getXlsAsStringForPerson(reportData, reportParameters);
  
  response.setContentType("application/vnd.ms-excel");
  response.addHeader("Content-Disposition", "attachment; filename=" + "person.xls");
  
  //since binary, write it as stream
  response.getOutputStream().write(xlsAsStringForPerson);
 }

//..
}


 
//...........
@Service(value = "myAppService")
public class MyAppServiceImpl implements MyAppService {

 public Collection<Person> getReportData()
    {
        //declare a list of object
        List<Person> data = new LinkedList<Person>();
        Person p1 = new Person();
        p1.setFirstName("John");
        p1.setSurname("Smith");
        p1.setAge(Integer.valueOf(5));
        data.add(p1);
        return data;
    }
    
    public Map<String, Object> getReportParameters()
    {
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("footerText", "Just to demonstrate how to pass parameters to report");
        return params;
    }
}

Finally, the writer class the creates the xls file from the data

 
//..
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.Collection;
import java.util.Map;

import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperCompileManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import net.sf.jasperreports.engine.design.JasperDesign;
import net.sf.jasperreports.engine.export.JRXlsExporter;
import net.sf.jasperreports.engine.export.JRXlsExporterParameter;
import net.sf.jasperreports.engine.xml.JRXmlLoader;

import org.springframework.stereotype.Component;
//...

@Component(value = "reportWriter")
public class JasperReportWriterImpl implements ReportWriter
{
    
    public static JasperDesign jasperDesign;
    public static JasperPrint jasperPrint;
    public static JasperReport jasperReport;
    public static String reportTemplateUrl = "jasper/person-template.jrxml";
    
    public byte[] getXlsAsStringForPerson(Collection<Person> reportData, Map<String, Object> reportParameters)
    {
        ByteArrayOutputStream output = null;
        
        try
        {
            InputStream resourceAsStream = Thread.currentThread().getContextClassLoader()
                    .getResourceAsStream(reportTemplateUrl);
            //get report file and then load into jasperDesign
            jasperDesign = JRXmlLoader.load(resourceAsStream);
            //compile the jasperDesign
            jasperReport = JasperCompileManager.compileReport(jasperDesign);
            
            output = new ByteArrayOutputStream();
            
            //fill the ready report with data and parameter
            jasperPrint = JasperFillManager.fillReport(jasperReport, reportParameters,
                    new JRBeanCollectionDataSource(
                            reportData));
            
            //coding for Excel
            JRXlsExporter exporterXls = new JRXlsExporter();
            exporterXls.setParameter(JRXlsExporterParameter.JASPER_PRINT, jasperPrint);
            exporterXls.setParameter(JRXlsExporterParameter.OUTPUT_STREAM, output);
            exporterXls.setParameter(JRXlsExporterParameter.IS_ONE_PAGE_PER_SHEET, Boolean.TRUE);
            exporterXls.setParameter(JRXlsExporterParameter.IS_DETECT_CELL_TYPE, Boolean.TRUE);
            exporterXls.exportReport();
            
        }
        catch (JRException e)
        {
            e.printStackTrace();
        }
        
        return output.toByteArray();
    }
}


Labels:

Jul 12, 2013

iReport 5.0 finding your way around

iReport is used to design your report templates. Here is the high level diagram of the key buttons and windows. If any of the windows are not there, you can add them from the menu item "Window".


The report is divided into "bands" and you can drag and drop report elements from the "palette" into the relevant bands. You can define the band and report elements properties via the "properties" window. New parameters, fields, etc can be added from the "Report Inspector" by right-clicking to bring up the contextual menu.

You can bring up the contextual menu on a "report element" as shown below to perform relevant tasks. Here is an example on a "Static Text" report element.


You can also bring it up on a "Text Field" report element as shown below. The "Edit expression" brings up the expression editor.




Finally, you can view it on three different layouts.

1. Designer (as shown above)
2. XML (shows the .jrxml file)
3. The Preview in your preferred output like "PDF Preview", "HTML Preview",  "XLS Preview (Using JExcelAPI)", etc that you select from the top "Preview" menu. This allows you to preview the actual report generated.


Labels:

Jul 11, 2013

JasperReports generating a PDF file


This is an extension to the JasperReport step by step tutorial to demonstrate how to generate a PDF file from the Main.java. To generate a PDF file you  need the iText.jar as a dependency. Here are the Maven dependency files required.

  
<!-- Jasper reports -->
<dependency>
 <groupId>net.sf.jasperreports</groupId>
 <artifactId>jasperreports</artifactId>
 <version>5.0.1</version>
</dependency>
<dependency>
 <groupId>org.codehaus.groovy</groupId>
 <artifactId>groovy-all</artifactId>
 <version>2.1.1</version>
</dependency>
<dependency>
 <groupId>com.lowagie</groupId>
 <artifactId>itext</artifactId>
 <version>2.1.7</version>
</dependency>


Next, the Main.java that writes the output to a PDF file.

  
package com.mycompany.app.jasper;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperCompileManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import net.sf.jasperreports.engine.design.JasperDesign;
import net.sf.jasperreports.engine.export.JRPdfExporter;
import net.sf.jasperreports.engine.export.JRPdfExporterParameter;
import net.sf.jasperreports.engine.xml.JRXmlLoader;

public class Main
{
    
    public static JasperDesign jasperDesign;
    public static JasperPrint jasperPrint;
    public static JasperReport jasperReport;
    public static String reportTemplateUrl = "person-template.jrxml";
    
    public static void main(String[] args) throws IOException
    {
        try
        {
            InputStream resourceAsStream = Thread.currentThread().getContextClassLoader()
                    .getResourceAsStream(reportTemplateUrl);
            //get report file and then load into jasperDesign
            jasperDesign = JRXmlLoader.load(resourceAsStream);
            //compile the jasperDesign
            jasperReport = JasperCompileManager.compileReport(jasperDesign);
            
            ByteArrayOutputStream output = new ByteArrayOutputStream();
            OutputStream outputfile = new FileOutputStream(new File("c:/temp/person.pdf"));
            
            //fill the ready report with data and parameter
            jasperPrint = JasperFillManager.fillReport(jasperReport, getParameters(),
                    new JRBeanCollectionDataSource(
                            findReportData()));
            
            //coding for PDF
            JRPdfExporter exporterPdf = new JRPdfExporter();
            exporterPdf.setParameter(JRPdfExporterParameter.JASPER_PRINT, jasperPrint);
            exporterPdf.setParameter(JRPdfExporterParameter.OUTPUT_STREAM, output);
            exporterPdf.exportReport();
            outputfile.write(output.toByteArray());
            
        }
        catch (JRException e)
        {
            e.printStackTrace();
        }
    }
    
    private static Collection<Person> findReportData()
    {
        //declare a list of object
        List<Person> data = new LinkedList<Person>();
        Person p1 = new Person();
        p1.setFirstName("John");
        p1.setSurname("Smith");
        p1.setAge(Integer.valueOf(5));
        data.add(p1);
        return data;
    }
    
    private static Map<String, Object> getParameters()
    {
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("footerText", "Just to demonstrate how to pass parameters to report");
        return params;
    } 
}

If you run the above class, a PDF file named person.pdf will be generated under c:\temp folder.

Labels:

Jul 10, 2013

Character encoding and decoding


Q. What do you understand by the terms character encoding and decoding?
A. To a computer, text characters are symbols. These symbols are assigned numbers (integers) in order to store these symbols in memory. Encoding is the system by which these numbers are assigned. Decoding is the way in which these numbers are converted to characters.


Q. What is the difference between ASCII and UTF-8?
A.

ASCII was the initial encoding, which only supported 256 letters assuming that the computers were created for english speaking people with some special characters. Google for ASCII table to see those characters. This made sense then when the computer memory was limited as well.

UTF-8 has the added benefit of character support beyond "ASCII-characters". UTF-8 uses Unicode, which has a different way of thinking about characters. There are different Unicode standards and UTF-8 is the most popular standard used in internet as it assumes that the leading bits are 0s




Every letter in every alphabet is assigned a magic number called a "code point".  ASCII has 128 code points, whereas a Unicode comprises 1, 114, 112 code points in the range 0 (hex) to 10FFFF (hex). Google for Unicode table (e.g http://unicode-table.com/en/). In UTF-8, every code point from 0-127 is stored in a single byte. Only code points 128 and above are stored using 2, 3, in fact, up to 6 bytes. This means English text looks exactly the same in UTF-8 as it did in ASCII.  The characters are referred to by their "Unicode code point". Unicode code points are written in hexadecimal (to keep the numbers shorter), preceded by a "U+". The character A is represented as U+0041.


Q. What is the significance of character encoding?
A. Every string has an encoding associated with it. There is no such thing as a plain text.  If you have a string, in memory, in a file, web browser, or in an email message, you have to know what encoding it is in or you cannot interpret it or display it to users correctly. If you open a document and it looks like this, there's one and only one reason for it: Your text editor, browser, word processor or whatever else that's trying to read the document is assuming the wrong encoding. The document is not broken, and you simply need to select the right encoding to display the document.

For an email message, you are expected to have a string in the header of the form

    Content-Type: text/plain; charset="UTF-8"


In HTML 5

   <meta charset="UTF-8">

In HTML 4

   <meta http-equiv="Content-type" content="text/html;charset=UTF-8">
  
Setting encoding to UTF-8 with Java Servlets:

    resource.setContentType ("text/html;charset=utf-8");


Q. Does java.lang.String class in Java has an encoding?
A. No.  the byte[] array has an encoding. For example:

package com.mycompany.app;

import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;

public class CharacterEncoding
{
    public static void main(String[] args) throws UnsupportedEncodingException
    {
        System.out.println(Charset.defaultCharset());
        
        String str = "Copy Right \u00A9";
        
        //uses the default encoding
        System.out.println(new String(str.getBytes()));
        
        //uses utf-8 encoding
        System.out.println(new String(str.getBytes("utf-8")));
        
    }
}


When I ran the above in eclipse, I got the following output.

windows-1252
Copy Right ©
Copy Right ©


This was using Eclipse IDE's default Text encoding.

 
When I changed this encoding to UTF-8 via Window --> Preferences --> General --> Workspace
 

The output has changed to as shown below.

UTF-8
Copy Right ©
Copy Right ©

Labels:

Jul 9, 2013

Java career training resources for Java developers

This Java blog is all about Java developer training the questions and answers way. The training materials are focused on

  • Getting your Java job done in your regular job.
  • Preparing for your Java job interview.
  • Preparing your Java job resume.
  • Finding ways to break free from a stagnating Java job.
  • Getting your first Java job with good technical, job hunting, and resume writing skills and much needed interview preparation.


The examples are not "Hello world" type, but more industrial strength. You can search for wide range of topics like Spring, Hibernate, JSF, JasperReports, JMeter, Spring batch, Spring security, JAXB, Drools, JavaScript, Angular JS, and many more.

Are you a Java developer?

  • If you are an interviewer, use these Java career training resources to hire quality candidates.
  • If you are an interviewee, use these Java career training resources to standout from your competition.
  • If you are on a regular job use these Java career training resources as a quick reference to get your job done.
  • If you are feeling stagnated, you can use these Java career training resources to get your regular technical doses to enhance your skills or stay relevant.


This Java/JEE career companion site is to breed confidence and help you take the road less traveled by presenting yourself in a better light compared to those who are more qualified than you are through preparation and being in the know how.  Here are some of the feedback.

"I used the book to get 6 jobs in 2 weeks. out of which one is an architect job. kudos to the author"

"If a person manages to give answers as given in book, he/she can easily bag a new job..."

"After landing a job I have kept on reading the book and recommend it to all my friends..."

The paid and free resources from this site covers a wide range of topics like Java/JEE core concepts, 16 must know technical key areas, resume writing, interview preparation, networking, and job hunting. The answers are detailed enough for you to not only talk the talk, but also to walk the walk.

Not for you to memorize the answers prior to job interviews for a short term success, but for you to brush up on vast number of Java topics at one place prior to job interviews or for you to fast track your Java career by proactively acquiring the much needed experience with lots of code, practical examples -- no "Hello World" examples :) , diagrams, and industrial scenarios covered here for a more permanent and long term success.

How do you benefit with Java Interview Questions?

  • Reach your career goals a lot sooner by convincing your prospective employer to overlook just the number of years of experience you have with your thorough and detailed job interview answers. 
  • Increase your earning potential with multiple job offers or by becoming a freelance contractor/consultant.
  • Impress your code reviewers with quality design and code.
  • Add value in the crisis and team meetings with your know hows and quick brush up on a particular topic like identifying thread-safety or performance issues. 
  • Expand your horizons and go places with the confidence that you can get a Java job even in a difficult job market with your resume writing skills, technical know hows, interviewing skills, networking, and job hunting skills.
  • The questions and answers approach gives a different perspective to acquire and clarify the fundamentals.  

More of your Java career related questions like
  • Should I get certified?
  • How to get a break in Java?
  • What are the 16 technical key areas?
  • What gives me the real job security?
answered @ Why prepare with these resources?

As a Java developer, you hold the key to your Java career success

Even though the “devil is in the details”, your career success in Java development depends on your “abstract thinking” and how well you communicate that thinking. Diagrams and working code will clarify many concepts and key areas to proactively acquire much needed experience to fast track your Java career. It worked for me, and hope will do for you as well.

There is no substitute for hands on experience, so take the time to practice the code. If the code or explanation is not clear, post your concerns via comments. I will endeavor to improve on the explanation. There is no such thing as real job security in IT, the real security in IT is all about having the right skills and experience.

You hold the key to your Java career success, and hope my Java career training resources will help you reach your career goals a lot sooner.

Core Java coding question - converting String to BigDecimal

There are times while coding you need to convert an entity of one data type to another or validate a given input.



Q. Can you write a generic function that converts an amount in String to double amount?
A.

Step 1: Ask the right questions and arrive at a more detailed requirements.
  • Handling negative amounts like -34.01 or (34.01) with a parenthesis. Parentheses denote a negative value. 
  • Handling commas in formatted values like 1,205.45, etc.
  • Handling negative scenarios like amount being  empty as in ( ).
Since, it is a requirement to write a generic function, all the above scenarios need to be taken care of.

Step 2: Let's use a TDD (Test Driven Development approach).

So, write a skeleton class so that all our unit tests fail.

  
package com.mycompany.app5;

import java.math.BigDecimal;
import java.text.ParseException;

public class ConvertingAmount
{
    
    public BigDecimal convert(String amount) throws ParseException
    {
        BigDecimal result = null;
        return result;
    }
}

Next, write the unit tests based on the above requirements so that all fail, but cover the requirements.

  
package com.mycompany.app5;

import java.math.BigDecimal;
import java.text.ParseException;

import junit.framework.Assert;

import org.junit.Before;
import org.junit.Test;

public class ConvertingAmountTest
{   
    private ConvertingAmount ca;
    
    @Before
    public void setUp()
    {
        ca = new ConvertingAmount();
    }
    
    @Test
    public void testPositiveAmount() throws ParseException
    {
        BigDecimal converted = ca.convert("2255.001");
        Assert.assertEquals(new BigDecimal("2255.001"), converted);
    }
    
    @Test
    public void testNegativeAmount() throws ParseException
    {
        BigDecimal converted = ca.convert("-2255.001");
        Assert.assertEquals(new BigDecimal("-2255.001"), converted);
    }
    
    @Test
    public void testNegativeAmountWithParanthes() throws ParseException
    {
        BigDecimal converted = ca.convert("(2255.001)");
        Assert.assertEquals(new BigDecimal("-2255.001"), converted);
    }
    
    @Test
    public void testPosiotiveAmountFormatted() throws ParseException
    {
        BigDecimal converted = ca.convert("2,255.001");
        Assert.assertEquals(new BigDecimal("2255.001"), converted);
    }
    
    @Test
    public void testNegativeAmountFormatted() throws ParseException
    {
        BigDecimal converted = ca.convert("-2,255.001");
        Assert.assertEquals(new BigDecimal("-2255.001"), converted);
    }
    
    @Test
    public void testNegativeAmountWithParenthesesFormatted() throws ParseException
    {
        BigDecimal converted = ca.convert("(2,255.001)");
        Assert.assertEquals(new BigDecimal("-2255.001"), converted);
    }
    
    @Test(expected = ParseException.class)
    public void testExceptionalScenario() throws ParseException
    {
        String amount = "()";
        ca.convert(amount);
    }
    
    @Test(expected = ParseException.class)
    public void testExceptionalScenario2() throws ParseException
    {
        String amount = "abc";
        ca.convert(amount);
    }
}




Step 3: Implement the functionality, so that all the above unit tests pass.

 
package com.mycompany.app5;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.ParseException;

import org.apache.commons.lang.StringUtils;

public class ConvertingAmount
{
    
    public BigDecimal convert(String amount) throws ParseException
    {
        BigDecimal result = null;
        
        DecimalFormat df = new DecimalFormat("#,#00.00;-#,#00.00"); //positive;negative 
        
        //convert (2255.001) to -2255.001 and (2,255.001) to  -2255.001 
        if (StringUtils.isNotBlank(amount) && amount.startsWith("(") && amount.endsWith(")"))
        {
            String valueStr = amount.substring(1, amount.length() - 1);
            Number valInParenthesis = df.parse(valueStr.trim());
            result = BigDecimal.valueOf(valInParenthesis.doubleValue()).negate();
            amount = result.toPlainString();
        }
        
        //parse 2,255.001 and -2,255.001
        Number val = df.parse(amount);
        result = BigDecimal.valueOf(val.doubleValue());
        
        return result;
    }
}

Now, all green.


Labels: ,

Jul 8, 2013

JasperReports generating an Excel file



This is an extension to the JasperReport step by step tutorial to demonstrate how to generate a Excel file from the Main.java. To generate an Excel file, you  need Apache POI as a dependency. Here are the Maven dependency files required.


 
<!-- Jasper reports -->
<dependency>
 <groupId>net.sf.jasperreports</groupId>
 <artifactId>jasperreports</artifactId>
 <version>5.0.1</version>
</dependency>
<dependency>
 <groupId>org.codehaus.groovy</groupId>
 <artifactId>groovy-all</artifactId>
 <version>2.1.1</version>
</dependency>
<dependency>
  <groupId>com.lowagie</groupId>
  <artifactId>itext</artifactId>
  <version>2.1.7</version>
</dependency>
 <dependency>
 <groupId>org.apache.poi</groupId>
 <artifactId>poi</artifactId>
 <version>3.7</version>
 <optional>true</optional>
</dependency>

Now, the Main.java file to generate the Excel file.

 
package com.mycompany.app.jasper;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperCompileManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import net.sf.jasperreports.engine.design.JasperDesign;
import net.sf.jasperreports.engine.export.JRXlsExporter;
import net.sf.jasperreports.engine.export.JRXlsExporterParameter;
import net.sf.jasperreports.engine.xml.JRXmlLoader;

public class Main
{
    
    public static JasperDesign jasperDesign;
    public static JasperPrint jasperPrint;
    public static JasperReport jasperReport;
    public static String reportTemplateUrl = "person-template.jrxml";
    
    public static void main(String[] args) throws IOException
    {
        try
        {
            InputStream resourceAsStream = Thread.currentThread().getContextClassLoader()
                    .getResourceAsStream(reportTemplateUrl);
            //get report file and then load into jasperDesign
            jasperDesign = JRXmlLoader.load(resourceAsStream);
            //compile the jasperDesign
            jasperReport = JasperCompileManager.compileReport(jasperDesign);
            
            ByteArrayOutputStream output = new ByteArrayOutputStream();
            OutputStream outputfile = new FileOutputStream(new File("c:/temp/person.xls"));
            
            //fill the ready report with data and parameter
            jasperPrint = JasperFillManager.fillReport(jasperReport, getParameters(),
                    new JRBeanCollectionDataSource(
                            findReportData()));
            
            //coding for Excel
            JRXlsExporter exporterXls = new JRXlsExporter();
            exporterXls.setParameter(JRXlsExporterParameter.JASPER_PRINT, jasperPrint);
            exporterXls.setParameter(JRXlsExporterParameter.OUTPUT_STREAM, output);
            exporterXls.setParameter(JRXlsExporterParameter.IS_ONE_PAGE_PER_SHEET, Boolean.TRUE);
            exporterXls.setParameter(JRXlsExporterParameter.IS_DETECT_CELL_TYPE, Boolean.TRUE);
            exporterXls.exportReport();
            outputfile.write(output.toByteArray());
            
        }
        catch (JRException e)
        {
            e.printStackTrace();
        }
    }
    
    private static Collection<Person> findReportData()
    {
        //declare a list of object
        List<Person> data = new LinkedList<Person>();
        Person p1 = new Person();
        p1.setFirstName("John");
        p1.setSurname("Smith");
        p1.setAge(Integer.valueOf(5));
        data.add(p1);
        return data;
    }
    
    private static Map<String, Object> getParameters()
    {
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("footerText", "Just to demonstrate how to pass parameters to report");
        return params;
    }  
}

If you execute the above class, person.xls will be generated  under the c:\temp folder.

Labels: