Tuesday, October 07, 2008

(ISO 8583 + JPOS + Log4J) in Java Socket Programming

SECTION 1. INTRODUCTION
Chapter 1.1. ISO 8583
You can read it's explanation first in Wikipedia.
Chapter 1.2. JPOS
JPOS is opensource framework for ISO 8583. Source code and library are free but documentation is comercial. We can download it here.
Chapter 1.3. Log4J
Log4J is opensource logging library. We can download it's library here and read it's mini e-book first written by Mr. Endy in here.
Chapter 1.4. Java Socket Programming
There's no explanation. Just need the basic knowledge of Java network programming and Java Thread Programming and let's coding.

SECTION 2. CODING
First we prepare that all we need. In this time, we will use NetBeans as IDE. Besides JPOS framework and Log4J library that I have mentioned above, we still need:
1. Xerces-Java XML parser library (xercesImpl.jar)
2. Spring framework
3. Jakarta Apache Commons Logging library

Chapter 2.1. ISO 8583 + JPOS + Log4J
In NetBeans, create a new Java application named MyApp. Create a package named com.ndung.iso8583. JPOS framework need a packager to set which ISO 8583 version that will be used. In this time we will use ISO 8583 version 1987. Download first iso87ascii.xml and place it in that package. Create a class as packager factory named PackagerFactory.java.


package com.ndung.iso8583;

import java.io.InputStream;

import org.jpos.iso.ISOException;
import org.jpos.iso.ISOPackager;
import org.jpos.iso.packager.GenericPackager;

public class PackagerFactory {
public static ISOPackager getPackager() {
ISOPackager packager = null;
try {
String filename = "iso87ascii.xml";
InputStream is = PackagerFactory.class.getResourceAsStream(filename);
packager = new GenericPackager(is);
}
catch (ISOException e) {
e.printStackTrace();
}
return packager;
}
}

And then create a class named MessageHandler.java that will be used to handle received message. Download first iso87asciiProperties.xml that will be used to translate bits of ISO message to become a String message that can be read easily.


package com.ndung.iso8583;

import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
import org.apache.log4j.Logger;
import org.jpos.iso.ISOException;
import org.jpos.iso.ISOMsg;
import org.jpos.iso.ISOPackager;

public class MessageHandler {
private static ISOPackager packager = PackagerFactory.getPackager();
private Logger logger = Logger.getLogger( getClass() );
public String process(ISOMsg isomsg) throws Exception {
logger.info("ISO Message MTI is "+isomsg.getMTI());
logger.info("Is ISO message a incoming message? "+isomsg.isIncoming());
logger.info("Is ISO message a outgoing message? "+isomsg.isOutgoing());
logger.info("Is ISO message a request message? "+isomsg.isRequest());
logger.info("Is ISO message a response message? "+isomsg.isResponse());
String message = "";
for (int i=0;i<128;i++){
if (isomsg.hasField(i)){
message += loadXMLProperties().getProperty(Integer.toString(i))+"="+
isomsg.getValue(i)+"\n";
}
}
logger.info(message);
return message;
}

public ISOMsg unpackRequest(String message) throws ISOException, Exception {
ISOMsg isoMsg = new ISOMsg();
isoMsg.setPackager(packager);
isoMsg.unpack(message.getBytes());
isoMsg.dump(System.out, " ");
return isoMsg ;
}

public String packResponse(ISOMsg message) throws ISOException, Exception {
message.dump(System.out, " ");
return new String( message.pack() ) ;
}

public Properties loadXMLProperties(){
Properties prop = new Properties();
try{
FileInputStream input=new FileInputStream("iso87asciiProperties.xml");
prop.loadFromXML(input);
input.close();
}
catch(IOException e){
e.printStackTrace();
}
return prop;
}
}

Chapter 2.2. Java Socket Programming + Log4J
Create a package named com.ndung.socket and then create four classes named ServerConfig.java, SocketServerHandlerFactory.java, SocketServerHandler.java, SocketConnectionServer. Before that create log4j.properties as logging configuration in default package.

# Category Configuration
log4j.rootLogger=INFO,Konsole,Roll
# Console Appender Configuration
log4j.appender.Konsole=org.apache.log4j.ConsoleAppender
log4j.appender.Konsole.layout=org.apache.log4j.PatternLayout
# Date Format based on ISO­8601 : %d
log4j.appender.Konsole.layout.ConversionPattern=%d [%t] %5p %c ­ %m%n
# Roll Appender Configuration
log4j.appender.Roll=org.apache.log4j.RollingFileAppender
log4j.appender.Roll.File=/home/ndung/NetBeansProjects/MyApp/log/myApp.log
log4j.appender.Roll.MaxFileSize=10KB
log4j.appender.Roll.MaxBackupIndex=2
log4j.appender.Roll.layout=org.apache.log4j.PatternLayout
# Date Format based on ISO­8601 : %d
log4j.appender.Roll.layout.ConversionPattern=%d [%t] %p (%F:%L) ­ %m%n


package com.ndung.socket;
public class ServerConfig {
private int port;
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
}


package com.ndung.socket;

import com.ndung.iso8583.MessageHandler;
import java.io.IOException;
import java.net.Socket;

public class SocketServerHandlerFactory {
private MessageHandler messageHandler;
public SocketServerHandlerFactory(MessageHandler messageHandler) {
this.messageHandler = messageHandler;
}
public SocketServerHandler createHandler(Socket socket) throws IOException {
return new SocketServerHandler(socket, messageHandler);
}
}


package com.ndung.socket;

import com.ndung.iso8583.MessageHandler;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import org.apache.log4j.Logger;
import org.jpos.iso.ISOMsg;

public class SocketServerHandler extends Thread{
private Logger logger = Logger.getLogger( getClass() );
private Socket serverSocket ;
private BufferedReader inFromClient;
private DataOutputStream outToClient;
private MessageHandler messageHandler;
private String datafromClient;

public SocketServerHandler(Socket socket, MessageHandler messageHandler) throws IOException {
super("SocketHandler (" + socket.getInetAddress().getHostAddress() + ")");
this.serverSocket = socket ;
this.messageHandler = messageHandler;
this.inFromClient = new BufferedReader(new InputStreamReader(serverSocket.getInputStream()));
this.outToClient = new DataOutputStream(serverSocket.getOutputStream());
}
@Override
public void run() {
try {
logger.info("Server is ready...");
while (true) {
logger.info("There is a client connected...");
outToClient.writeBytes("InfoServer version 0.1\n");
datafromClient = inFromClient.readLine();
logger.info("Data From Client : "+datafromClient);
ISOMsg isomsg = messageHandler.unpackRequest(datafromClient);
outToClient.writeBytes(messageHandler.process(isomsg));
}
}
catch (IOException ioe) {
logger.error("error: " + ioe);
}
catch (Exception e) {
logger.error("error: " + e);
}
finally {
try {
if (inFromClient != null) inFromClient.close();
if (outToClient != null) outToClient.close();
if (serverSocket != null) serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}


package com.ndung.socket;

import java.io.IOException;
import java.net.ServerSocket;

public class SocketConnectionServer {
private ServerConfig config;
private SocketServerHandlerFactory handlerFactory;
private boolean stop;
public SocketConnectionServer(ServerConfig config, SocketServerHandlerFactory handlerFactory) {
this.config = config;
this.handlerFactory = handlerFactory;
}
public void start() throws IOException {
stop = false;
final ServerSocket serverSocket = new ServerSocket(config.getPort());
new Thread(new Runnable() {
public void run() {
while (!stop) {
try {
handlerFactory.createHandler(serverSocket.accept()).start();
}
catch (IOException e) {
e.printStackTrace();
}
}
}
}).start();
}
public void stop() {
stop = true;
}
}

Create a socket server class named MyServer.java. This class also as a main class for our application. And then we will create a socket client class named MyClient.java. Before that create applicationContext.xml in default package as Spring configuration injection for our main class.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">

<beans>
<bean id="socketConnectionServer" class="com.ndung.socket.SocketConnectionServer">
<constructor-arg>
<ref local="config" />
</constructor-arg>
<constructor-arg>
<ref local="socketServerHandlerFactory" />
</constructor-arg>
</bean>

<bean id="config" class="com.ndung.socket.ServerConfig">
<property name="port">
<value>50000</value>
</property>
</bean>

<bean id="socketServerHandlerFactory" class="com.ndung.socket.SocketServerHandlerFactory">
<constructor-arg>
<ref local="messageHandler" />
</constructor-arg>
</bean>

<bean id="messageHandler" class="com.ndung.iso8583.MessageHandler">
</bean>

</beans>


package com.ndung.socket;

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

public class MyServer {

public static void main(String[] args) throws IOException {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
SocketConnectionServer server = (SocketConnectionServer) ctx.getBean("socketConnectionServer");
server.start();
}
}


package com.ndung.socket;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import org.apache.log4j.Logger;

public class MyClient {
private final int MY_PORT=50000;
private final String TargetHost = "localhost";
private final String QUIT = "QUIT";
private Logger logger = Logger.getLogger( getClass() );
public MyClient() {
try {
BufferedReader inFromUser = new BufferedReader(new InputStreamReader(System.in));
Socket clientSocket = new Socket(TargetHost, MY_PORT);
DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());
BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
logger.info(inFromServer.readLine());
boolean isQuit = false;
while (!isQuit) {
System.out.print("Your data : ");
String cmd = inFromUser.readLine();
cmd = cmd.toUpperCase();
if (cmd.equals(QUIT)) {
isQuit = true;
}
outToServer.writeBytes(cmd + "\n");
String message = inFromServer.readLine();
while (message!=null){
logger.info("From Server: " + message);
message = inFromServer.readLine();
}
}
outToServer.close();
inFromServer.close();
clientSocket.close();
}
catch (IOException ioe) {
logger.error("Error:" + ioe);
}
catch (Exception e) {
logger.error("Error:" + e);
}
}
public static void main(String[] args) {
new MyClient();
}
}

Run our application first. It means our main class (MyServer.java) will be run first. And then run client as much that we want. It means MyClient.java will be run twice or more. And then in one of our client application console enter an input data. It means a String of ISO message. As example:
0210723A00010A808400185936001410010999990110000000100000001007021533000001191533
10061007065656561006090102240000000901360020100236C0102240000000
Look in both of our application console either MyServer or MyClient. What do you see?
Btw, Happy Eid Mubarak...

9 comments:

imsuryawan said...

socket programming with java?! hmm... seems nice to try.. :D

mahendra said...

BUAT HOST DAN TEMAN2 BLOG.. SELAMAT TAHUN BARU 2009 YAAAA...
SEMOGA TAMBAH SUKSES!

Saya punya info bagus.
Sebuah bundle informasi yang saya jamin bagus buat anda
Informasi tentang bagaimana membuat bisnis online sendiri, bagaimana agar eksis di search engine

manapun, sampai membuat website profesional dengan wordpress.org (bukan wordpress.com lo ya..) juga

bagaimana script membuat web iklan baris (dapat langsung diaplikasikan sehingga bisa nambah pemasukan)

semuanya ada disini
Ada pasti puassss.
Salam hangat.

Hapi said...

Hello there my friend! I found your blog very interesting so I have added your link in my Blogroll. I hope you'll link me back. Have a nice day! http://hapiblogging.blogspot.com/

Carlos said...

Hi! Care to x-link? I have added you already in my list. Have a nice day! http://carlos-ideas.blogspot.com

Plokmaster's Software Blogs said...

Looking for Reallusion iClone PRO v3.0 ? Download it now @ AriesGames!

Keyword said...

Submit your Blog to our Newest PR 3 Web Directory for Bloggers. Visit KeywordDir.info

Hapi said...

Hi there... want to change your favicon? find out how.. Have a nice tuesday!

Hapi said...

Happy Wednesday! Bloghoppin' here... Hey, I have an interesting tutorial for you that I have written myself. It is about adding Adsense on your Single Post in XML template. I hope you'll like it! God Bless you!

septianw said...

wah kok english semua yang nongol?