Tuesday, July 8, 2014

Web Service using Spring-WS with HTTP Digest Authentication

We have seen 'A Simple Web Service Using Spring-WS' in the previous post.
Now we need to secure the service from unauthorized access. We are going to apply HTTP Digest Authentication[1][2] for this.

Note that we are not implementing Message Signing or Encryption here. We will only ensure 'Authentication' using Spring XwsSecurityInterceptor[3], so that only authenticated users can access the add service we defined in the previous post.

First modify the ws-servlet.xml file and add the following bean definitions:

  • XwsSecurityInterceptor bean (inside the <sws:interceptors/> tag),
  • callBackHandlerDigest bean definition,
  • userDetailsService




Add a Role enumeration to define User's role:

Add the domain(/model/entity) class:

Now add the dao class (with dummy user population):


We need to create a CustomUserDetailsService which implements UserDetailsService

This is how the project-structure should look like (underlined items are newly added over the project in the previous post):


The project can be downloaded using git from spring-ws-test project (secured_user_auth_digest branch):
git clone https://github.com/tariqmnasim/spring-ws-test.git -b secured_user_auth_digest

References:
[1] HTTP Authentication: Basic and Digest Access Authentication
[2] Wikipedia: Digest access Authentication
[3] Securing your web services using Spring-WS

Friday, June 13, 2014

A Simple Web Service Using Spring-WS

In this post I will describe the way to write a very simple SOAP-based web service that will take as input two numbers and return the sum of those numbers.

Create the Project Structure:
We can start our development based on a Java-Web project using maven. [ See maven web project directory layout  and creating maven webapp project ].


Define Data Contract (XSD):
Spring-WS focuses on Contract-First development style [See Why]. So, we first define the data exchange (reuest-response) format of the web service, i.e. the Data Contract.

Generate Request/Response Models:
You can generate (un-marshal) Java classes using JAXB from the above XSD. You can use XJC for this or you can use features of your IDE to convert XML-to Java. In IntelliJ IDEA, right click on the .xsd file in the project explorer, click "Web Services" --> "Generate Java classes from XML Schema using JAXB". (for eclipse see this).
AddServiceRequest.java, AddServiceResponse.java and ObjectFactory.java will be generated in this case. Put the generated classes in a separate package (e.g. com.test.ws.wsmodels).

Then write the service interfaces and an implementation of the service interface.


Now write the endpoint class.


All the java classes are ready now. We need to configure the spring servlet definition and the web.xml file.



Now the maven configuration.


Now build the file using the maven command:
mvn clean package

Deploy the spring-ws-test.war file in your server (tomcat / glassfish / jboss). If you deploy the application in your localhost, then you can see the wsdl on your browser in the following URL:
http://localhost:8080/spring-ws-test/services/wstest.wsdl

The service can be tested using Soap-UI or other SOAP client.

You can get the whole project from github using git:
git clone https://github.com/tariqmnasim/spring-ws-test.git


References:
JAXB:

Saturday, May 31, 2014

Automatically deploy applications (WAR files) during JBoss AS starting time.

Add a <deployment/> part under <deployments/> tag in the standalone.xml file (<JBoss Installation Directory>/standalone/standalone.xml) to automatically deploy applications (WAR files) during JBoss AS starting time:
<server>
 <!-- ... -->
 <!-- ... -->
 <deployments>
        <deployment name="my.war" runtime-name="my.war">
            <fs-archive path="Path/to/my.war">
        </fs-archive></deployment>
  <deployment name="other.war" runtime-name="other.war">
            <fs-archive path="Path/to/some/other.war">
        </fs-archive></deployment>
    </deployments>
 <!-- ... -->
 <!-- ... -->
</server>

Now, each time you start JBoss AS, application server will try to deploy the wars specified in the standalone.xml file.

Sunday, May 25, 2014

Get first/last date of current Week/Month

import java.util.Calendar;
import java.util.Date;
/**
 * Returns the date of previous Monday
 */
public static Date getFirstDateOfCurrentWeek() {
    Calendar cal = Calendar.getInstance();
    cal.set(Calendar.HOUR_OF_DAY, 0);
    cal.clear(Calendar.MINUTE);
    cal.clear(Calendar.SECOND);
    cal.clear(Calendar.MILLISECOND);
    cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
    return cal.getTime();
}
/**
 * Returns the date of next Sunday.
 */
public static Date getLastDateOfCurrentWeek() {
    Calendar cal = Calendar.getInstance();
    cal.set(Calendar.HOUR_OF_DAY, 0);
    cal.clear(Calendar.MINUTE);
    cal.clear(Calendar.SECOND);
    cal.clear(Calendar.MILLISECOND);
    cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);

    Calendar last = (Calendar) cal.clone();
    last.add(Calendar.DAY_OF_YEAR, 7);
    last.add(Calendar.MILLISECOND, -1);
    return last.getTime();
}
/**
 * Get the first Date ( first millisecond ) of current month
 */
public static Date getFirstDateOfCurrentMonth() {
    Calendar cal = Calendar.getInstance();
    cal.set(Calendar.HOUR_OF_DAY, 0);
    cal.clear(Calendar.MINUTE);
    cal.clear(Calendar.SECOND);
    cal.clear(Calendar.MILLISECOND);
    cal.set(Calendar.DAY_OF_MONTH, 1);
    return cal.getTime();
}
/**
 * Get the last time ( last millisecond ) of current month
 */
public static Date getLastDateOfCurrentMonth() {
    Calendar cal = Calendar.getInstance();
    cal.set(Calendar.HOUR_OF_DAY, 0);
    cal.clear(Calendar.MINUTE);
    cal.clear(Calendar.SECOND);
    cal.clear(Calendar.MILLISECOND);
    cal.add(Calendar.MONTH, 1); // NEXT MONTH
    cal.set(Calendar.DAY_OF_MONTH, 1); // FIRST DAY OF NEXT MONTH
    cal.add(Calendar.MILLISECOND, -1); // Go one Millisecond back, which is the last moment of the last day of current month
    return cal.getTime();
}

Wednesday, May 21, 2014

JBoss Logging Configuration: Write Application Specific Logs in a Different File

In order to write the logs generated from your application into a separate file (not in the default <j-boss-installation-directory>\...\server.log file), follow these steps:

Start JBoss Administrative Console: In your browser hit http://localhost:9990/console/App.html

Configure A File Handler:

  • Go to Profile --> Core --> Logging --> 'Handler' tab --> 'File' sub-tab and Click 'Add' button.
  • In the 'Add File Handlers' pop-up box, enter name, log-level, file-name with extension etc. and 'Save'
  • You may also need to further edit the created handler and set 'Auto Flash' and 'Append' to true.

Add A Log Category:

  • Now go to the 'Log Categories' tab and click 'Add'. Enter the root package of your project in the 'Name' field (e.g. com.mycompany.myproject).
  • Now select (click on) the newly added log-category and click on 'handlers' (under 'Details' section at the bottom).
  • Click 'Add' and add the handler that you created previously.

[You can also configure the handler and Log Category by editing the .../standalone/configuration/standalone.xml file of your server directory.]

Happy Logging:
Now you can log using slf4j from your application like:
private static Logger logger = LoggerFactory.getLogger(MyClass.class);

and all logs of your application will be written to the file-name that you specified for the handler configured above.

I have used EAP 6.2.0 GA (AS 7.3) application server and slf4j (for logging).

Related Links:
JBoss: Configure Logging
slf4j Manual.