Web Service Application Level Authentication

In some situations we need to protect our private data, so we may want to use authentication mechanism for our web services. In this writing, I will give you an example to how you can create web service authentication level at application level, and how you can call this kind of web services.

First of all, we need to create a web service. I am not going to deploy the application to a web server like Weblogic or Tomcat. I will use embedded web server in Java, however you can deploy your applications freely to other web servers.

I will give a brief explanation of classes on the top of code and detailed explanations will be inside the code with comments.

Here is the project structure:

Ws Project Structure

Below interface will be used as a web service endpoint interface. Implementation will check this interface for methods.

package com.aykutakin.ws;

import javax.jws.WebMethod;
import javax.jws.WebService;

@WebService
public interface SampleWebService {
	
	@WebMethod
	String getDummy(String msg);
	
}

Below class handles the request. Main implementation will be done in this class. Note that endpointInterface attribute of WebService annotation shows exactly where SampleWebService interface is.

package com.aykutakin.ws;

import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.jws.WebService;
import javax.xml.ws.WebServiceContext;
import javax.xml.ws.handler.MessageContext;

@WebService(endpointInterface = "com.aykutakin.ws.SampleWebService")
public class SampleWebServiceImpl implements SampleWebService {

	// We can get request's message context using WebServiceContext
	@Resource
	private WebServiceContext webServiceContext;

	// This method must be implemented for the interface
	@Override
	public String getDummy(String msg) {

		// Get message context
		MessageContext messageContext = webServiceContext.getMessageContext();

		// Authentication information will be in request header.
		// So we extract the information from message request.
		Map<String, List<String>> reqHeaders = (Map<String, List<String>>) messageContext.get(MessageContext.HTTP_REQUEST_HEADERS);

		// Get header attributes
		String username = reqHeaders.get("Username").get(0);
		String password = reqHeaders.get("Password").get(0);

		// Check validity of information.
		// Probably you will need a proper authentication mechanism rather than hardcoded strings.
		// I used literal string equals method to run away from null check.
		if ("user1".equals(username) && "1111".equals(password)) {
			return "Successful Dummy String With Message: " + msg;
		}

		return "Unknown User!";
	}

}

Finally, we publish our application to server with using below code.

package com.aykutakin.ws;

import javax.xml.ws.Endpoint;

// This class is going to publish our web service to http server
public class SampleWebServiceEndpoint {
	
    public static void main(String[] args) {
	    Endpoint.publish("http://localhost:9999/ws/dummy", new SampleWebServiceImpl());
    }
    
}

After you make ready these classes, run the project. If you made the implementation right, you can see the web service wsdl in browser. Just check this address:

http://localhost:9999/ws/dummy?wsdl

If you see the wsdl then you are ready to call the web service. I created a client jar using this utility. Later that, I wrote below class for web service call.

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.ws.BindingProvider;
import javax.xml.ws.handler.MessageContext;

import com.aykutakin.ws.SampleWebService;
import com.aykutakin.ws.SampleWebServiceImplService;

public class Test {

	public static void main(String[] args) {
		SampleWebServiceImplService service = new SampleWebServiceImplService();
		
		SampleWebService sampleWebService = service.getSampleWebServiceImplPort();

		// Request header is a map that keys are String, values are List
		// Put information to a proper map
		Map<String, List<String>> headers = new HashMap<String, List<String>>();
		headers.put("Username", Arrays.asList(new String[]{"user1"}));
		headers.put("Password", Arrays.asList(new String[]{"1111"}));

		// Put header map to message context's request header parameter
		((BindingProvider) sampleWebService).getRequestContext().put(MessageContext.HTTP_REQUEST_HEADERS, headers);

		System.out.println(sampleWebService.getDummy("HelloWorld"));
	}

}

You should see a message like that when you run the code:
WsSuccessMessage

If you have questions, you can ask me anytime. As soon as I’m available, I will try to reply.

Developers Rock!!!

Posted in Java | Tagged , , , , , , , | Leave a comment

Logging SOAP Web Service Request and Response

In this writing, I will talk about how to log soap request and response xml’s in Java. I used a free weather webservice as a sample for this post. I created a GlobalWeather.jar using JAX-WS from this wsdl. If you don’t know how to create client jar, you can check this post (You need to change the root folder from ‘com’ to ‘net’).

To log the webservice requests and responses, we need to change the handler resolver to our custom one. We are going to add our SOAPHandler implementation to the chain and that way, our logging handler will work before we send request and after we get response. During this times, we can easily log necessary information.

Firstly, I will show you the logging handler. We simply implement SOAPHandler interface for this purposes. There are 4 methods we need to implement:

  • close: This method will be called lastly. If we use some resources, we can return them to system in this method.
  • handleFault: If we face with a problem during the service call, we can log it in this method.
  • handleMessage: If there is no problem during the service call, this method will be called naturally. Both request text and response text will be handled in this method. We can discriminate outbound message with MessageContext.MESSAGE_OUTBOUND_PROPERTY property.
  • getHeaders: It returns the QNames of the outer element of each SOAP header that the handler understands.

Below there is an implementation of SOAPHandler. Note that, handling methods return ‘true’ as a parameter. If you return ‘false’, you will face with an exception.

package com.webservicecaller;

import java.io.IOException;
import java.util.Set;

import javax.xml.namespace.QName;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPMessage;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;

public class JaxWsLoggingHandler implements SOAPHandler<SOAPMessageContext> {

	@Override
	public void close(MessageContext arg0) {
	}

	@Override
	public boolean handleFault(SOAPMessageContext arg0) {
		SOAPMessage message = arg0.getMessage();
		try {
			message.writeTo(System.out);
		} catch (SOAPException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return true;
	}

	@Override
	public boolean handleMessage(SOAPMessageContext arg0) {
		SOAPMessage message = arg0.getMessage();
		boolean isOutboundMessage = (Boolean) arg0.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
		if (isOutboundMessage) {
			System.out.println("OUTBOUND MESSAGE\n");

		} else {
			System.out.println("INBOUND MESSAGE\n");
		}
		try {
			message.writeTo(System.out);
		} catch (SOAPException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return true;
	}

	@Override
	public Set<QName> getHeaders() {
		return null;
	}

}

And below, you can find our Handler Resolver and how we add our logging handler to chain.

package com.webservicecaller;

import java.util.ArrayList;
import java.util.List;

import javax.xml.ws.handler.Handler;
import javax.xml.ws.handler.HandlerResolver;
import javax.xml.ws.handler.PortInfo;

public class JaxWsHandlerResolver implements HandlerResolver {

	@SuppressWarnings("rawtypes")
	@Override
	public List<Handler> getHandlerChain(PortInfo arg0) {
		List<Handler> hchain = new ArrayList<Handler>();
		hchain.add(new JaxWsLoggingHandler());
		return hchain;
	}

}

Then our main class stands below. As you can see, we set service handler resolver to our custom one at line 10.

package com.webservicecaller;

import net.webservicex.GlobalWeather;
import net.webservicex.GlobalWeatherSoap;

public class Test {

	public static void main(String[] args) {
		GlobalWeather globalWeather = new GlobalWeather();
		globalWeather.setHandlerResolver(new JaxWsHandlerResolver());

		GlobalWeatherSoap globalWeatherSoap = globalWeather.getGlobalWeatherSoap();
		System.out.println(globalWeatherSoap.getWeather("Turkey", "Istanbul / Ataturk"));
	}
}

After we run this code, we can see the result like below in console screen:

Logging Console

EDIT: If you want the output as formatted, you can use below handleMessage method:

    @Override
    public boolean handleMessage(SOAPMessageContext arg0) {
        SOAPMessage message = arg0.getMessage();
        boolean isOutboundMessage = (Boolean) arg0.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
        if (isOutboundMessage) {
            System.out.println("OUTBOUND MESSAGE");
        } else {
            System.out.println("INBOUND MESSAGE");
        }
        try {
            Source source = message.getSOAPPart().getContent();

            Transformer transformer = TransformerFactory.newInstance().newTransformer();
            
            transformer.setOutputProperty(OutputKeys.INDENT, "yes");
            transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
            
            transformer.transform(source, new StreamResult(System.out));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return true;
    }

If you have question, you can ask me anytime. As soon as I’m available, I will try to reply.

Developers Rock!!!

Posted in Java | Tagged , , , , , , , , | 19 Comments

Creating WebService Client with WsImport (Jax-WS)

WsImport is a powerful way to create Java Classes for web services. It is supported by the jdk’s higher than 1.5. We can easily create web service clients using wsimport executable file that comes with jdk installation. Below command create necessary classes for sample wsdl:

"C:\Program Files\Java\jdk1.6.0_45\bin\wsimport" http://domainname/project/sample.wsdl

This is really simple example of wsimport. If you want, you can specify binding parameters, keep real java class files and give target directory as an option. You can find full options from Oracle documentations.

I created a script that takes folder name and wsdl location and then creates client jar file for the service. It uses below binding.xml to control necessary parameters.

<jaxb:bindings version="2.1"
    xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
    xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
    xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <jaxb:globalBindings generateElementProperty="false"/>
</jaxb:bindings>

And written script is below. You can put it into text file and rename it wim.cmd with locating at the same folder with binding.xml. After you run the file and supply necessary parameters, the jar file will be created as ready to use.

@ECHO OFF
SET /P SERVICE_NAME=Please enter service name:
SET /P SERVICE_WSDL=Please enter wsdl address:
if exist %SERVICE_NAME% echo Error, directory %SERVICE_NAME% already exists. && GOTO:EOF
echo.
echo.
echo Generating jar for service %SERVICE_NAME% STARTED
echo.
mkdir %SERVICE_NAME%
echo Getting wsdl: %SERVICE_WSDL%
echo.
call "%JAVA_HOME%\bin\wsimport" -keep -b binding.xml -d %SERVICE_NAME% %SERVICE_WSDL%
IF ERRORLEVEL = 1 echo Error importing WSDL. && rd /s /q %SERVICE_NAME% && GOTO:EOF
cd %SERVICE_NAME%
echo Generating %SERVICE_NAME%.jar
echo.
"%JAVA_HOME%\bin\jar" cf ..\%SERVICE_NAME%.jar com
cd ..
rd /s /q %SERVICE_NAME%
echo Done.
pause

As you see in the code, JAVA_HOME variable must be already set in the system. You can change JAVA_HOME variable with absolute or relative path of the jdk installation to run given code. You may also need to change the root folder while creating jar file at line 17. I just wrote ‘com’ for root folder, but this may change according to service (for example I saw a lot of ‘net’ root folder while looking for free web services).

Developers Rock!!!

Posted in Java | Tagged , , , , , , , , | Leave a comment

XSD to Java Class with XJC

With the jdk version of 1.6 and later, we can easily create java classes from xsd using XJC(xml java compiler). In this post, I will give you a quick example to use ‘xjc’ to create java classes. Below I have a really basic xsd sample and I am going to create java classes using this definitions.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xs:schema version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema">
 
  <xs:element name="employee" type="employee"/>
 
  <xs:complexType name="employee">
    <xs:sequence>
      <xs:element name="name" type="xs:string"/>
      <xs:element name="department" type="department"/>
      <xs:element name="email" type="xs:string" minOccurs="0"/>
      <xs:element name="phone" type="xs:string" minOccurs="0"/>
    </xs:sequence>
    <xs:attribute name="id" type="xs:int" use="required"/>
  </xs:complexType>
 
  <xs:complexType name="department">
    <xs:sequence>
      <xs:element name="name" type="xs:string"/>
      <xs:element name="manager" type="xs:string"/>
      <xs:element name="location" type="xs:string" minOccurs="0"/>
    </xs:sequence>
    <xs:attribute name="id" type="xs:int" use="required"/>
  </xs:complexType>

</xs:schema>

In this example I have an employee class with some basic variables. Employee also has a relation with department, which is an another complex type defined in the xsd.

When I want to create java classes, I simply execute below command:

"C:\Program Files\Java\jdk1.6.0_45\bin\xjc" -d target -p com.myproject.jaxb.beans sample.xsd

I run this command in the folder of ‘sample.xsd’. Because of that, I referred to full path of xjc. ‘xjc.exe’ can be found on where you installed jdk. Optionally, you can add jdk binaries to your path variable to simplify the usage of java built in binaries.

Now I want to mention about the input parameters that I used. ‘-d’ option specifies the output directory. If this directory not exist, command will prompt an error message to console. ‘-p’ is the another optional parameter to create a Java style folder presentation. If you do not use both ‘-d’ and ‘-p’ options, a folder called ‘generated’ will be created and all the files will be in that folder. Otherwise classes will be located according to your parameters.

You can find other options with using ‘-help’. There are some interesting experimental features of xjc that you may want to explore. If you have any question, you can contact with me anytime.

Developers Rock!!!

Posted in Java | Tagged , , , , | Leave a comment

Create Eclipse Dynamic Web Project With Maven – 2

I get a request to post a second way for creating Eclipse dynamic web project with maven. For who interested with first way (create maven project with console, than turn it to Eclipse project) here is the link. In this second method we will create an Eclipse dynamic web project and add Maven capabilities to that project. Let’s begin:

First of all you must install Maven Plugin for Eclipse. You need to restart Eclipse after installation.

After that we must create a new dynamic web project.
Create Dynamic Web Project

Then right click to project and go to configure section. You will see ‘Convert to Maven Project’ option here.
Convert Maven Project

You will see a popup configuration window and you can make necessary configurations from this window. For this example, I just go on with the way its popped out.
Maven Spec

You can see pom.xml after this step and you can add maven dependencies depend to your needs. Your project structure will be like below.
Project Structure

I simply add some spring dependencies to pom.xml like below.
Sample Dependencies

After saving pom.xml, right click the project and go to Maven options then install necessary dependencies from net. You can add new dependencies from Maven options or directly editing pom.xml. You can update output war file from Maven options and work directly with Eclipse integrated web server.

Developers Rock!!!

Posted in Java | Tagged , , , , , , | Leave a comment

Oracle Time Overlaps (WM_OVERLAPS)

Oracle has undocumented and documented functions for time operations. In this writing, I will mention the undocumented ‘overlaps’ and documented ‘wm_overlaps’ functions. Actually, they do the same work, but they have some differences.

Our aim is to find that two different time interval has overlapped at any time. We can do this with OR statements, but Oracle has functions for this operation. Our cases are like below:

Time Overlaps

WM_OVERLAPS: This documented function uses already defined data type that called WM_PERIOD to find time overlap. Here is a samples for every case that we mention above with graphic.

-- A --
SELECT * FROM DUAL
WHERE wm_overlaps(WM_PERIOD(sysdate-5,sysdate+5), WM_PERIOD(sysdate,sysdate+10)) = 1

-- B --
SELECT * FROM DUAL
WHERE wm_overlaps(WM_PERIOD(sysdate-5,sysdate+5),WM_PERIOD(sysdate-3,sysdate+3)) = 1

-- C --
SELECT * FROM DUAL
WHERE wm_overlaps(WM_PERIOD(sysdate,sysdate+5),WM_PERIOD(sysdate-5,sysdate+3)) = 1

-- D --
SELECT * FROM DUAL
WHERE wm_overlaps(WM_PERIOD(sysdate-3,sysdate+3),WM_PERIOD(sysdate-5,sysdate+5)) = 1

But, this function has a bug (I’m not sure actually that is a bug, but this situation works like a charm with overlaps function). If you try to run below query, that will return nothing because of the second part of the function. If you look closely, the time period has kind a negative value. Because first date is larger than second date.

SELECT * FROM DUAL
WHERE wm_overlaps(WM_PERIOD(sysdate-10,sysdate+10), WM_PERIOD(sysdate+10, sysdate-20)) = 1

Below, there is a overlap function usage for every case. Overlap function directly uses Oracle date type for operations.

-- A --
SELECT * FROM DUAL
WHERE (sysdate-5,sysdate+5) overlaps (sysdate,sysdate+10)

-- B --
SELECT * FROM DUAL
WHERE (sysdate-5,sysdate+5) overlaps (sysdate-3,sysdate+3)

-- C --
SELECT * FROM DUAL
WHERE (sysdate,sysdate+5) overlaps (sysdate-5,sysdate+3)

-- D --
SELECT * FROM DUAL
WHERE (sysdate-3,sysdate+3) overlaps (sysdate-5,sysdate+5)

If you try the exceptional case, that I mention, you will see that works perfectly with overlaps function:

SELECT * FROM DUAL
WHERE (sysdate-10,sysdate+10) overlaps (sysdate+10, sysdate-20)

You can find more details in this link.

Developers Rock!!!

Posted in Oracle | Tagged , , , , , | Leave a comment

Logging to Console and File In Python

Python has a great integrated logging mechanism for developers. You don’t have to make complicated stuffs to activate logger and you can easily log to file or console with separating different kinds of log levels. In this writing, I will create a basic initialization method and use it to log my main program. More complicated implications are up to you.

First, I want to give some basic concepts of logger for python. Logger has a 5 different level in python. These are:

  • debug
  • info
  • warning
  • error
  • critical

Every output place is controlled by handlers. For example, if you want to console output, you need to define console related handler. After that, you can handle logging level or logging format via that handler.

Now, I will give you a basic example code for logging. My file structure will be like below:

Logging file structure

There is loggerinitializer.py file:

import logging
import os.path

def initialize_logger(output_dir):
    logger = logging.getLogger()
    logger.setLevel(logging.DEBUG)
    
    # create console handler and set level to info
    handler = logging.StreamHandler()
    handler.setLevel(logging.INFO)
    formatter = logging.Formatter("%(levelname)s - %(message)s")
    handler.setFormatter(formatter)
    logger.addHandler(handler)

    # create error file handler and set level to error
    handler = logging.FileHandler(os.path.join(output_dir, "error.log"),"w", encoding=None, delay="true")
    handler.setLevel(logging.ERROR)
    formatter = logging.Formatter("%(levelname)s - %(message)s")
    handler.setFormatter(formatter)
    logger.addHandler(handler)

    # create debug file handler and set level to debug
    handler = logging.FileHandler(os.path.join(output_dir, "all.log"),"w")
    handler.setLevel(logging.DEBUG)
    formatter = logging.Formatter("%(levelname)s - %(message)s")
    handler.setFormatter(formatter)
    logger.addHandler(handler)

Line 5-6: Get main logger to add new specifications. Then set global log level to debug.

Line 9-13: In this area I add console logging mechanism to logger. In first line I get StreamHandler() and this means console for me. Then I said I only want output for INFO messages or higher level like errors or critical messages. For example Debug messages will not be printed out with this options. Then I give my own output format. There are a lot of options for this format and mine is very very simple. At the end, I add my console handler to my main logger.

Line 16-20: This area is nearly same as above except little differences. This time we get a FileHandler to write a file. In first parameter, we give the path for output file. Then we say we want to ‘write’ to file without any encoding specification. Last parameter puts some magic here. If no message is sent to this handler, no file will be created. The below lines are the same as above except that logger level is set to Error.

Line 23-27: In this area we create a new handler to log every message. We set level to debug, which is minimum, and let file be created every run.

After that, we can test this code with below code:

#!/usr/bin/env python3

from utils.loggerinitializer import *

initialize_logger('/home/aykut/Documents/blog')

logging.debug("debug message")
logging.info("info message")
logging.warning("warning message")
logging.error("error message")
logging.critical("critical message")

If we look at the outputs, we will see below:

Python Logging Outputs

Developers Rock!!!

Posted in Python | Tagged , , , , , , | 1 Comment