Showing posts with label java. Show all posts
Showing posts with label java. Show all posts

Friday, July 22, 2016

Creating WSDL/SOAP web services in Spring Boot using CXF, JAX-WS and JAXB

Here's a quick way to use Spring Boot to expose web services via WSDL/SOAP using CXF, JAX-WS and JAXB.

Add the following artifacts into your Spring Boot pom.xml:


    org.apache.cxf
    cxf-rt-frontend-jaxws
    3.1.6



    org.apache.cxf
    cxf-rt-transports-http
    3.1.6


Wednesday, August 14, 2013

Spring 3 MVC + Hibernate 4 + JdbcTemplate + Partial REST controller (Part 3)

Last part of the article is to use either Hibernate or Spring's JdbcTemplate to retrieve data. The following class is the BaseDao where DataSource and Hibernate SessionFactory are injected and used by concrete DAO classes:

package com.techtots.services.api.dao;

import javax.sql.DataSource;

import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;

public abstract class BaseDao {

	@Autowired
	protected SessionFactory sessionFactory;
	
	protected DataSource dataSource;

	protected JdbcTemplate jdbcTemplate;
	protected NamedParameterJdbcTemplate namedParameterJdbcTemplate;

	public DataSource getDataSource() {
		return dataSource;
	}

	@Autowired
	public void setDataSource(DataSource dataSource) {
		this.dataSource = dataSource;
		this.jdbcTemplate = new JdbcTemplate(this.dataSource);
		this.namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(this.dataSource);
		
	}

	public JdbcTemplate getJdbcTemplate() {
		return jdbcTemplate;
	}

	public NamedParameterJdbcTemplate getNamedParameterJdbcTemplate() {
		return namedParameterJdbcTemplate;
	}

}

Once we have this out of the way, we can now define a concrete DAO class. We'll have a simple UserDao for testing.

package com.techtots.services.api.dao;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import org.hibernate.Criteria;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;

import com.techtots.services.api.entity.User;
import com.techtots.services.common.vo.UserVo;

@Repository
public class UserDao extends BaseDao {

	public List<User> getList() {
		Criteria criteria = sessionFactory.getCurrentSession().createCriteria(User.class);
		
		return criteria.list();
	}
	
	public List<UserVo> list() {
		final List<UserVo> list = new ArrayList<UserVo>();
		
		getJdbcTemplate().query("select * from tbl_user", new RowMapper<Object>() {

			@Override
			public Object mapRow(ResultSet rs, int arg1) throws SQLException {
				UserVo vo = new UserVo();
				
				vo.setId(rs.getInt("id"));
				vo.setUsername(rs.getString("nickname"));
				
				list.add(vo);
				
				return null;
			}
			
		});
		
		return list;
	}
}


Since this is just a reference, I've implemented 2 different function to retrieve data. getList() uses Hibernate's SessionFactory while list() uses JdbcTemplate. Following classes are the UserVo and User entity classes which are used by the DAO respectively:

package com.techtots.services.common.vo;

public class UserVo {

	private int id;
	private String username;

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

}

package com.techtots.services.api.entity;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "tbl_user2")
public class User {

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	@Column(name = "id", nullable = false)
	private int id;

	@Column(name = "name", nullable = false, length = 200)
	private String name;

	@Column(name = "email", nullable = false, length = 250, unique = true)
	private String email;

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

}

To call this from your UserController, you'll need to add the @Transactional annotation at either the class or method level. You wouldn't usually add this at the controller level as it's better to have everything wrapped up in a service class.

Spring 3 MVC + Hibernate 4 + JdbcTemplate + Partial REST controller (Part 2)

Second part of the article will focus on the controllers which will process clients' requests as well as other helper classes.

We start off with a custom exception. We add on a HttpStatus code into the exception to return to clients:

package com.techtots.services.api.common.exceptions;

import org.springframework.http.HttpStatus;

public class RestException extends Exception {

 private static final long serialVersionUID = -6373811042517187537L;

 public static final HttpStatus DEFAULT_ERROR_STATUS = HttpStatus.BAD_REQUEST;
 
 private HttpStatus status;
  
 public HttpStatus getStatus() {
  return status;
 }

 public void setStatus(HttpStatus status) {
  this.status = status;
 }

 public RestException() {
  super();
  
  this.status = DEFAULT_ERROR_STATUS;
 }

 public RestException(String message) {
  super(message);
 
  this.status = DEFAULT_ERROR_STATUS;
 }
 
 public RestException(HttpStatus status, String message) {
  super(message);
  
  this.status = status;
 }
}

With Spring 3.2, we can use the @ControllerAdvice annotation to centralize validation and exception handling.

package com.techtots.services.api.common;

import org.apache.commons.lang3.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;

import com.techtots.services.api.common.exceptions.RestException;

@ControllerAdvice
public class RestResponseExceptionHandler extends ResponseEntityExceptionHandler {

 Logger log = LoggerFactory.getLogger(RestResponseExceptionHandler.class);
 
 @ExceptionHandler(RestException.class)
 protected ResponseEntity handleBadRequest(RestException ex) {

  log.error(ExceptionUtils.getStackTrace(ex));
  
  HttpHeaders headers = new HttpHeaders();
  headers.setContentType(MediaType.TEXT_HTML);
  
  ResponseEntity entity = new ResponseEntity(ex.getMessage(), headers, ex.getStatus()); 
  
  return entity;
 }
}


Finally, a test controller to hook everything up:

package com.techtots.services.api.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.techtots.services.api.common.exceptions.RestException;

@Controller
@RequestMapping("/auth")
public class AuthController extends BaseController {
 @RequestMapping(value = "/test", method = RequestMethod.GET, produces = "application/json")
 @ResponseBody
 public String test() throws Exception {

  return "ok";
 }

 @RequestMapping(value = "/test2", method = RequestMethod.POST, consumes = "application/json", produces = "application/json")
 @ResponseBody
 public void test2() throws Exception {

  throw new RestException("something's missing...");
 }

}

Calling the test method will return a JSON encoded message. While calling the test2 method will throw a HTTP exception with the message "something's missing" with HTTP error code 400 (the default HTTP error code returned in RestResponseExceptionHandler).

Spring 3 MVC + Hibernate 4 + JdbcTemplate + Partial REST controller (Part 1)

This is post serves as a reference point to quickly setup a Java web application with Spring 3 MVC, Hibernate 4, JdbcTemplate and a partial REST controller. We'll be consuming and responding JSON content via the REST controllers.

I'm using Eclipse as the IDE and will be connecting to MySQL database.

Let's start off with the libraries:

  • antlr-2.7.7.jar
  • aopalliance.jar
  • bonecp-0.7.1.RELEASE.jar
  • commons-lang3-3.1.jar
  • commons-logging-1.1.3.jar
  • dom4j-1.6.1.jar
  • guava-14.0.1.jar
  • hibernate-commons-annotations-4.0.2.Final.jar
  • hibernate-core-4.2.4.Final.jar
  • hibernate-jpa-2.0-api-1.0.1.Final.jar
  • jackson-annotations-2.2.0.jar
  • jackson-core-2.2.0.jar
  • jackson-databind-2.2.0.jar
  • javassist-3.15.0-GA.jar
  • jboss-logging-3.1.0.GA.jar
  • jboss-transaction-api_1.1_spec-1.0.1.Final.jar
  • mysql-connector-java-5.1.26-bin.jar
  • slf4j-api-1.7.5.jar
  • slf4j-simple-1.7.5.jar
  • spring-aop-3.2.3.RELEASE.jar
  • spring-beans-3.2.3.RELEASE.jar
  • spring-context-3.2.3.RELEASE.jar
  • spring-core-3.2.3.RELEASE.jar
  • spring-expression-3.2.3.RELEASE.jar
  • spring-jdbc-3.2.3.RELEASE.jar
  • spring-orm-3.2.3.RELEASE.jar
  • spring-tx-3.2.3.RELEASE.jar
  • spring-web-3.2.3.RELEASE.jar
  • spring-webmvc-3.2.3.RELEASE.jar

We'll continue to configure the web app by specifying the web.xml:





  
    contextConfigLocation    /WEB-INF/*ctx.xml  

  
    org.springframework.web.context.ContextLoaderListener
  

  
    api
    org.springframework.web.servlet.DispatcherServlet
    1
  

  
    api
    /api/*
  

  
    /errors/error.jsp
  



Next is to create the application context XML. We'll only have 3 bean definitions in the app-ctx:





 
  
  
  
  
  
  
  
  
  
  
  
  
 

 
  

  
    
      org.hibernate.dialect.MySQL5Dialect
      true
    
  
  
 
 
 
  
 
 



Now for the api-servlet.xml. No bean definition in this file as everything is annotation based.




 

 

 



We also have a single JSP to handle errors in errors/error.jsp. This is as bare as it gets:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>




ERROR



<%
out.println(request.getAttribute("javax.servlet.error.message"));
out.println(request.getAttribute("javax.servlet.error.status_code"));

%>



This concludes basic setup for the webapp. Next part will include Java classes for the controller and error handling.

Wednesday, July 31, 2013

Java Message Format Using Named Placeholder

The Java MessageFormat class allows user to pre-define a string with placeholders and then fill the placeholders with actual strings later to construct a proper message.

It's all fine if you're used to numbered placeholders e.g. {0} and {1}. Since I'm used to Drupal's format_string() function, here's a better alternative. Apache Commons has a StrSubstitutor class which allows use of named placeholders. Instead of using:

String template = "Welcome {0}!  Your last login was {1}";
String output = MessageFormat.format(template1, new Object[] { "gabe", new Date().toString() });

You can now do:

String template = "Welcome ${username}!  Your last login was ${lastlogin}";

Map data = new HashMap();
data.put("username", "gabe");
data.put("lastlogin", new Date().toString());
  
String output2 = StrSubstitutor.replace(template2, data);

Although StrSubstitutor is a bit more verbose, but it helps when you're handling lots of key/value pairs.

Monday, July 15, 2013

Output XLS file to servlet output stream using JExcelAPI

Here's a quick way (although not the best one) to stream an Excel file generated by JExcelAPI (http://jexcelapi.sourceforge.net/). I'm using the servlet output stream in this case.

HttpServletResponse response = getContext().getResponse();

ServletOutputStream sos = response.getOutputStream();

WritableWorkbook workbook = Workbook.createWorkbook(sos);
WritableSheet sheet = workbook.createSheet("Report", 0);
sheet.addCell(new Label(1, 1, "asdfasdfasdf"));

response.setContentType("application/vnd.ms-excel");
response.setHeader("Expires", "0");
response.setHeader("Cache-Control", "must-revalidate, post-check=0, pre-check=0");
response.setHeader("Pragma", "public");
response.setHeader("Content-Disposition", "inline; filename=report-.xls");

workbook.write();
workbook.close();
sos.close();

Sunday, February 24, 2013

JavaOne 2012 videos on YouTube

Here's list of videos from the recent JavaOne 2012 symposium:

http://www.theserverside.com/news/thread.tss?thread_id=72456

Have fun!

Thursday, August 2, 2012

Checking if Java/Solaris is 32 or 64 bit

To check if Solaris is 32 or 64 bit, use the following command:

$ isainfo -kv
64-bit sparcv9 kernel modules


To check if JRE in Solaris is 32 or 64 bit, use the following command:

$ java -d64 -version
execve(): No such fie or directory
Failed to start a 64-bit JVM process from a 32-bit JVM

Well, that's a complain :)

Monday, December 12, 2011

Using logback to log to a syslog server

In my previous posts, we've configured a rsyslogd server to accept remote connections via TCP/UDP as well as a rsyslogd instance to write to a remote rsyslogd server.  We'll now take this further by logging to the rsyslogd server we've configured earlier using the logback library (http://logback.qos.ch/). 

Besides the logback JAR files, you'll need to grab the latest SLF4J libraries as well from http://slf4j.org/.  Below are the JAR files required to get logback working:
  • logback-core-1.0.0.jar
  • logback-classic-1.0.0.jar
  • slf4j-api-1.6.4.jar
Pay attention to the version of SLF4J you're using.  If you get the following exception when running your program, you're most likely using an older SLF4J library:
SLF4J: The requested version 1.6 by your slf4j binding is not compatible with [1.5.5, 1.5.6]
SLF4J: See http://www.slf4j.org/codes.html#version_mismatch for further details.
Exception in thread "main" java.lang.NoSuchMethodError: org.slf4j.helpers.MessageFormatter.arrayFormat(Ljava/lang/String;[Ljava/lang/Object;)Lorg/slf4j/helpers/FormattingTuple;
    at ch.qos.logback.classic.spi.LoggingEvent.(LoggingEvent.java:114)
    at ch.qos.logback.classic.Logger.buildLoggingEventAndAppend(Logger.java:468)
    at ch.qos.logback.classic.Logger.filterAndLog_0_Or3Plus(Logger.java:424)
    at ch.qos.logback.classic.Logger.info(Logger.java:628)
    at com.test.RemoteTest.main(RemoteTest.java:11)
On to the logback.xml configuration file.  It's a very basic configuration.  Just two appenders: STDOUT and SYSLOG.  SYSLOG appender is the one we're interested in.
<configuration>

    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <!-- encoders are assigned the type ch.qos.logback.classic.encoder.PatternLayoutEncoder
            by default -->
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger - %msg%n</pattern>
        </encoder>
    </appender>

    <appender name="SYSLOG" class="ch.qos.logback.classic.net.SyslogAppender">
        <syslogHost>myhost</syslogHost>
        <facility>USER</facility>
        <suffixPattern>[%thread] %logger %msg</suffixPattern>
    </appender>

    <root level="debug">
        <appender-ref ref="SYSLOG"/>
        <appender-ref ref="STDOUT"/>
    </root>
</configuration>
  • syslogHost - syslog server host to log to
  • facility - identify the source of the message
  • suffixPattern - format of the log message
More info can be obtained in logback's manual on appenders: http://logback.qos.ch/manual/appenders.html#SyslogAppender.

The Java class to test the appenders:
package com.test;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class RemoteTest {
    static final Logger logger = LoggerFactory.getLogger(RemoteTest.class);
   
    public static void main(String[] args) {
       
        logger.info("hello world");
    }
}
The rsyslogd host should have the following entry once you run the RemoteTest class:
Dec 12 16:16:37 my-noteb [main] com.test.RemoteTest hello world

Thursday, December 8, 2011

Barebones JSF2 Eclipse project

Quick view on minimal libraries required to get a JSF2 project running in Eclipse (should work everywhere else):
  • com.springsource.javax.servlet.jsp-2.1.0.jar ==> Obtained from Spring framework dependencies package
  • com.springsource.javax.servlet.jsp.jstl-1.1.2.jar ==> Obtained from Spring framework dependencies package
  • javax.faces.jar ==> Obtained from http://javaserverfaces.java.net/.  Downloaded Mojarra 2.1 release.  Available in Spring framework dep package, but it's an older version (1.2).
  • jstl-impl-1.2.jar  ==> Obtained from http://jstl.java.net/.  Available in Spring framework dep package, but it's an older version (1.1.2).
You can start developing a JSF2 app with just these 4 files.  Have tried the following:
  • Facelets (xmlns:ui="http://java.sun.com/jsf/facelets")
  • HTML elements (xmlns:h="http://java.sun.com/jsf/html")
  • Core elements (xmlns:f="http://java.sun.com/jsf/core")
I used Apache Tomcat 7.  But I'm sure this will work with other app server/servlet containers as well.  

Saturday, February 20, 2010

EHCache with Spring AOP

Building on the previous post (Spring AOP with @AspectJ annotations), we now add EHCache functionality to the Aspect class.  We won't be adding any new Java class files, but we'll be modifying the existing class files.  Here's a screenshot of the finished project in Eclipse.  New elements are highlighted in red.




Adding EHCache functionality

Add the EHCache JAR file to the project.  We'll be using ehcache-core-1.7.0.jar.  Grab your copy from http://www.ehcache.org.  You'll also need to create configuration file for EHCache.  Name it ehcache.xml and put it under the com.aop package.  Here's the content of the file:

<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="ehcache.xsd" updateCheck="false">

    <diskStore path="java.io.tmpdir"/>

    <defaultCache
            maxElementsInMemory="10000"
            eternal="false"
            timeToIdleSeconds="120"
            timeToLiveSeconds="120"
            overflowToDisk="true"
            diskSpoolBufferSizeMB="30"
            maxElementsOnDisk="10000000"
            diskPersistent="false"
            diskExpiryThreadIntervalSeconds="120"
            memoryStoreEvictionPolicy="LRU"
            />


    <cache name="defaultCache"
           maxElementsInMemory="100"
           eternal="false"
           timeToIdleSeconds="1800"
           timeToLiveSeconds="3600"          
           overflowToDisk="false"
           diskPersistent="false"
           memoryStoreEvictionPolicy="LRU"
            />

</ehcache>
Next, we'll need to configure EHCache to be available in Spring.  For this, the app-ctx.xml needs to be edited.  Add the following lines to the app-ctx.xml file:


<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
    <property name="configLocation" value="classpath:com/aop/ehcache.xml"></property>
</bean>

<bean id="methodCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean">
    <property name="cacheManager">
        <ref local="cacheManager" />
    </property>
    <property name="cacheName" value="defaultCache"/>
</bean>


The Caching Aspect Class

Now that Spring and EHCache have been configured, we can modify the MyAspect.java class file to include the caching features.  We begin by changing the PointCut in the MyAspect.java.  Instead of intercepting all public methods, we now only intercept public methods beginning with getMap.  In addition, we a private Cache property to hold the method cache as well as some logic to store/retrieve the method cache.  Here's the updated MyAspect.java class:

package com.aop;

import net.sf.ehcache.Cache;
import net.sf.ehcache.Element;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;

@Aspect
public class MyAspect {
   
    private Cache methodCache;
   
    @Around("execution(public * getMap*(..))")
    public Object executor(ProceedingJoinPoint point) throws Throwable {

        System.out.println("Cutting before...");
       
        Object retVal;
       
        String methodName = point.getTarget().getClass().toString() + "," + point.toShortString();

        if (methodCache.isKeyInCache(methodName)) {
            System.out.println("Returning from cache....");
            return methodCache.get(methodName).getObjectValue();
        } else {
            retVal = point.proceed();
           
            if (retVal != null) {
                System.out.println("returned object: " + retVal.toString());
                System.out.println("Storing into cache...");
               
                methodCache.put(new Element(methodName, retVal));
            }
           
        }

        System.out.println("Cutting after...");
       
        return retVal;
    }

    public Cache getMethodCache() {
        return methodCache;
    }

    public void setMethodCache(Cache methodCache) {
        this.methodCache = methodCache;
    }
}
As the cache key, we're using a combination of the class name and the method name.  The rest of the changes are pretty straight forward. 


Spring Managed Bean - MyBean.java

We add a new method called getMap1() in MyBean.java.  Here's the code:


public HashMap<String, String> getMap1() {
   
    System.out.println("getMap1 == init");
   
    HashMap<String, String> map = new HashMap<String, String>();
   
    for (int i = 0; i < 100; i++) {
        map.put(Integer.toString(i), "new value " + i);
    }

    System.out.println("getMap1 == return");
   
    return map;
   
}


Main Runner

In the class which contains the main method, we'll be calling the getMap1() multiple times to determine if the caching is working.  The output should be like below:

Cutting before...
getMap1 == init
getMap1 == return
returned object: {35=new value 35, 36=new value 36, 33=new value 33, 34=new value 34, 39=new value 39, 37=new value 37, 38=new value 38, 43=new value 43, 42=new value 42, 41=new va
lue 41, 40=new value 40, 22=new value 22, 23=new value 23, 24=new value 24, 25=new value 25, 26=new value 26, 27=new value 27, 28=new value 28, 29=new value 29, 3=new value 3, 2=ne
w value 2, 1=new value 1, 0=new value 0, 30=new value 30, 7=new value 7, 6=new value 6, 32=new value 32, 5=new value 5, 31=new value 31, 4=new value 4, 9=new value 9, 8=new value 8
, 19=new value 19, 17=new value 17, 18=new value 18, 15=new value 15, 16=new value 16, 13=new value 13, 14=new value 14, 11=new value 11, 12=new value 12, 21=new value 21, 20=new v
alue 20, 99=new value 99, 98=new value 98, 97=new value 97, 96=new value 96, 95=new value 95, 94=new value 94, 93=new value 93, 92=new value 92, 91=new value 91, 90=new value 90, 1
0=new value 10, 88=new value 88, 89=new value 89, 79=new value 79, 78=new value 78, 77=new value 77, 82=new value 82, 83=new value 83, 80=new value 80, 81=new value 81, 86=new valu
e 86, 87=new value 87, 84=new value 84, 85=new value 85, 67=new value 67, 66=new value 66, 69=new value 69, 68=new value 68, 70=new value 70, 71=new value 71, 72=new value 72, 73=n
ew value 73, 74=new value 74, 75=new value 75, 76=new value 76, 59=new value 59, 58=new value 58, 57=new value 57, 56=new value 56, 55=new value 55, 64=new value 64, 65=new value 6
5, 62=new value 62, 63=new value 63, 60=new value 60, 61=new value 61, 49=new value 49, 48=new value 48, 45=new value 45, 44=new value 44, 47=new value 47, 46=new value 46, 51=new
value 51, 52=new value 52, 53=new value 53, 54=new value 54, 50=new value 50}
Storing into cache...
Cutting after...
Cutting before...
Returning from cache....
Cutting before...
Returning from cache....
Cutting before...
Returning from cache....

Friday, February 19, 2010

Spring AOP with @AspectJ annotations

Here's a quick sample on how to use Spring's AOP feature with @AspectJ annotations.  First off, please read the Spring Reference manual on AOP.  This post is a copy and paste tutorial (hopefully I get it right :P).  We begin by creating a normal Java Project in Eclipse.  I've named it "springtest".  You can name it whatever you like.  Here's a screenshot of the project in Eclipse:

Take note of the JAR files in the project.  Those are the JAR files required by Spring to use AOP features.  They can be found in Spring's lib and dist folders (you'll need the full Spring download with dependencies).
  • spring.jar - main Spring JAR file; obtained from the "dist" folder
  • aspectjrt.jar, aspjectjweaver.jar - AspectJ JAR file; obtained from "lib/aspectj" folder
  • commons-logging.jar - Commons logging JAR file; obtained from "lib/jakarta-commons" folder
  • cglib-nodep-2.1_3.jar - Code generation lib JAR file; obtained from "lib/cglib" folder

Spring Application Context File - app-ctx.xml
Create the Spring app context file in the com.aop package and name it app-ctx.xml.  Here's the contents of the file:

<?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:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">

    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
   
    <bean id="myBean" class="com.aop.MyBean"/>
   
    <bean id="myAspect" class="com.aop.MyAspect"/>
</beans>

The highlighted line is to enable @AspectJ autoproxying of beans declared. 


Aspect Class - MyAspect.java
Next, create a Java class file and name it MyAspect.java.  This file will contain the Aspect as well as the PointCut we'll be using for this simple how to.  File content shown below:

package com.aop;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;

@Aspect
public class MyAspect {
   
    @Around("execution(public * *(..))")
    public Object executor(ProceedingJoinPoint point) throws Throwable {

        System.out.println("Cutting before...");
       
        Object retVal = point.proceed();
       
        if (retVal != null) {
            System.out.println("returned object: " + retVal.toString());
        }
       
        System.out.println("Cutting after...");
       
        return retVal;
    }
}
Remember that aspectj-autoproxy declaration in the app-ctx.xml file?  Once we annotate a class file using the @Aspect, Spring AOP will automatically pickup and process the class files.

Notice that we're using the Around advice.  What this does is prints the line "Cutting before..." right before the method is executed and "Cutting after..." right after the method is executed.  If the method returns a value, print it out.  For more information on other types of advices, please refer to the Spring reference doc :)  What we're doing here is to cut around all public methods. 


The Simple Spring Managed Bean - MyBean.java
This is a simple Spring managed bean which contains methods which will be intercepted by the aspect class defined above.  Here's the file contents:

package com.aop;

public class MyBean {
    public void test() {
        System.out.println("MyBean>>>test");
    }
   
    public void test2() {
        System.out.println("MyBean>>>test2");
    }
   
    public String returnTest() {
        System.out.println("MyBean>>>returnTest");
        return "this is a test";
    }
}

The Main class - MainRunner.java
This will be the class which contains the main method.  Here's the contents:

package com.aop;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MainRunner {
    public static void main(String[] args) {
        try {
            ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("com/aop/app-ctx.xml");
           
            MyBean bean = (MyBean) ctx.getBean("myBean");
            bean.test();
            bean.test2();
            bean.returnTest();
           
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
   
}
The first step is to obtain the application context via ClassPathXmlApplicationContext.  Then call get an instance of MyBean and subsequently call its methods (test, test2 and returnTest).  If you've done everything right, run the program and the following output should be displayed:

Cutting before...
MyBean>>>test
Cutting after...
Cutting before...
MyBean>>>test2
Cutting after...
Cutting before...
MyBean>>>returnTest
returned object: this is a test
Cutting after...
There you have it, the simplest way of AOP :)

Thursday, January 14, 2010

Connecting to MQ using Spring without WAS

Here's how to connect to MQ using spring without WAS.  First, here's the properties value for the connection settings:
# MQ related values
mq.jms.qcf=IBMMQQCF
mq.jms.request.queue=TEST.REQUEST.QUEUE

# Connection details
mq.host.url=192.168.1.200:1415/SYSTEM.DEF.SVRCONN
mq.factoryclass=com.ibm.mq.jms.context.WMQInitialContextFactory

# Authentication details
mq.auth=simple
mq.user=username
mq.password=password
Now the Spring beans configuration:
    <bean id="queueConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
        <property name="jndiName" value="${mq.jms.qcf}" />
        <property name="resourceRef" value="false" />
        <property name="jndiEnvironment">
            <props>
                <prop key="java.naming.factory.initial">${mq.factoryclass}</prop>
                <prop key="java.naming.provider.url">${mq.host.url}</prop>
                <prop key="java.naming.security.authentication">${mq.auth}</prop>
                <prop key="java.naming.security.principal">${mq.user}</prop>
                <prop key="java.naming.security.credentials">${mq.password}</prop>
            </props>
        </property>
    </bean>

    <bean id="requestQueue" class="org.springframework.jndi.JndiObjectFactoryBean">
        <property name="jndiName" value="${mq.jms.request.queue}" />
        <property name="resourceRef" value="false" />
        <property name="jndiEnvironment">
            <props>
                <prop key="java.naming.factory.initial">${mq.factoryclass}</prop>
                <prop key="java.naming.provider.url">${mq.host.url}</prop>
                <prop key="java.naming.security.credentials">${mq.password}</prop>
                <prop key="java.naming.security.authentication">${mq.auth}</prop>
            </props>
        </property>
    </bean>
Once that's done, you can use the normal JMS calls to send the message to the queue.  Below is a sample of how to send a message:
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueReceiver;
import javax.jms.QueueSender;
import javax.jms.QueueSession;
import javax.jms.Session;
import javax.jms.TextMessage;

import org.apache.log4j.Logger;

public class JMSProcessor {
    private QueueConnectionFactory qcf;
    private Queue reqQ;
    private Queue respQ;

    private long timeout = 0;

    private Logger log = Logger.getLogger(MessageProcessor.class);

    public void sendMessage(final String msg) throws Exception {
       
        String messageOut = null;
       
        QueueConnection connection = null;
        QueueSession queueSession = null;
        QueueSender queueSender = null;

        try {
            connection = qcf.createQueueConnection();
            connection.start();
       
            queueSession = connection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
       
            queueSender = queueSession.createSender(reqQ);
           
            TextMessage reqMsg = queueSession.createTextMessage(msg);
           
            reqMsg.setJMSDestination(reqQ);

            queueSender.send(reqMsg);

        } catch (Exception e) {
            throw e;

        } finally {
            try {
                connection.close();
                queueSession.close();
                queueSender.close();
            } catch (JMSException e1) {
                log.error(e1.getMessage(), e1);
            }
        }
    }

}


Friday, January 8, 2010

.NET and Apache Axis Interop Problem

I've been using Apache Axis for a long time to publish web services in Java apps.  But recently, it's the first time that a .NET client is used to call the web services published via Axis.  Although I do not have the exact error messages in the .NET client, the client mentioned they received "null" errors when parsing the response.

First thing to do was to disable "multirefs" output.  This can be achieved by adding the following parameter in either the global configuration or service based configuration.  Either way, output below shows the tag to disable sending "multiref" output:
<parameter name="sendMultiRefs" value="false"/>
The second option I tried was to turn on the "dotNetSoapEncFix".  Again, this can be applied in the global or service configuration.  Setting shown below:
<parameter name="dotNetSoapEncFix" value="true"/>
Unfortunately, I didn't have much luck with the "dotNetSoapEncFix" parameter.  The last thing I tried was to change the output style to "wrapped".  This option can only be turned on in the service tag.  Here's how I did it:
<service name="myService" provider="java:RPC" style="wrapped"/>
After the server's restarted, the output is a lot shorter without the "soapenc" definitions which were causing the problems.

Here's the output before setting the style to "wrapped":

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <soapenv:Body>
      <ns1:function1 soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns1="http://com.testing">
         <function1_Return xsi:type="ns2:Map" xmlns:ns2="http://xml.apache.org/xml-soap">
            <item xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">
               <key xsi:type="soapenc:string">DESC</key>
               <value xsi:type="soapenc:string">EXCEPTION</value>
            </item>
            <item>
               <key xsi:type="soapenc:string" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">STATUS</key>
               <value xsi:type="soapenc:string" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">0</value>
            </item>
         </function1_Return>
      </ns1:function1>
   </soapenv:Body>
</soapenv:Envelope>

Here's the output after:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <soapenv:Body>
      <function1 xmlns="http://com.testing">
         <function1_Return>
            <item xmlns:ns1="http://xml.apache.org/xml-soap" xmlns="">
               <key xsi:type="xsd:string">DESC</key>
               <value xsi:type="xsd:string">EXCEPTION</value>
            </item>
            <item xmlns="">
               <key xsi:type="xsd:string">STATUS</key>
               <value xsi:type="xsd:string">0</value>
            </item>
         </function1_Return>
      </function1>
   </soapenv:Body>
</soapenv:Envelope>