How to get the name of the enclosing method

If you ever want to get the name of the enclosing method for logging purpose, then we can follow any one of the below approaches.

Get the method name from the exception stack trace


   private void methodNameFromExceptionTrace() {
        System.out.println("Method Name with Exception class:: " + new Exception().getStackTrace()[0].getMethodName());
    }

The main drawback in the above one is the unnecessary creation of Exception object.

Get the method name from the Thread



    private void methodNameFromCurrentThread() {
 Stream.of(Thread.currentThread().getStackTrace())
       .forEach(System.out::println);
 System.out.println("Method Name with Thread :: " + Thread.currentThread().getStackTrace()[1].getMethodName());     
    }

Refer below the entire code.



import java.util.stream.Stream;

public class Main {

    public static void main(String[] args) {
        Main main = new Main();
        // Get the method name From Exception trace
        main.methodNameFromExceptionTrace();
        // Get the method name From Thread
        main.methodNameFromCurrentThread();
      // Get the method name From Exception trace
        main.getMethodNameWithException();
    }

    private void methodNameFromExceptionTrace() {
        System.out.println("Method Name with Exception class:: " + new Exception().getStackTrace()[0].getMethodName());
    }

    private void methodNameFromCurrentThread() {
Stream.of(Thread.currentThread().getStackTrace()).forEach(System.out::println);
        System.out.println("Method Name with Thread :: " + Thread.currentThread().getStackTrace()[1].getMethodName());

    }

    private void getMethodNameWithException() {
        try {
            throw new Exception("Test");
        }
        catch (Exception e) {
            System.out.println("Exception happened in " + e.getStackTrace()[0].getMethodName());
        }
    }
}

Here in the getMethodNameWithException method, we are throwing an exception and in the catch block, we use that object to get back the method name. But if you call some other method and that method throws that exception, then the e.getStackTrace()[0] will be different so you need to change the index which should be 1. Refer the below example.



 private void getMethodNameWithException() {
        try {
            testMethod();
        }
        catch (Exception e) {
            Stream.of(e.getStackTrace()).forEach(System.out::println);
            System.out.println("Exception happened in " + e.getStackTrace()[1].getMethodName());
        }
    }
    private void testMethod() throws Exception {
        throw new Exception("Test");
    }


Advertisements

Docker container – health check

HEALTHCHECK instruction is used to tell the Docker how to test a container to see if its still working or not.  This is used to detect cases such as a web server that is stuck in an infinite loop and unable to handle new connections, even though the server is still running.

In this post, I am going to show an example how we can add this instruction in the Dockerfile and test this.

Refer my code @java-rest-docker

Here is my Dockerfile


FROM java:8

WORKDIR /opt

ADD hello-rest-${project.version}-jar-with-dependencies.jar /opt/helloRest.jar
ADD bin /opt/bin

RUN chmod +x /opt/helloRest.jar
RUN chmod +x /opt/bin/run.sh

CMD ["/opt/bin/run.sh"]

EXPOSE 8080

HEALTHCHECK --interval=1m --timeout=3s CMD curl -f http://localhost:8080/api/greeting || exit 1

Check the last line of my Dockerfile where I instruct the docker to access localhost:8080/api/greeting in every 1 min and do the health check and fail it if there are any issues. If the exit status 0 when the container is healthy. If it’s 1, then it’s not in healthy status.

My docker CE version is 17.06.2-ce.

Now Build the image and the run the docker container.Then run this command and check the health check output. Here replace the container name “elegant_bartik” with your local container name.


  docker inspect --format "{{json .State.Health }}" elegant_bartik

Output:
{“Status”:”healthy”,”FailingStreak”:0,”Log”:[{“Start”:”2017-09-19T18:23:54.612256172-04:00″,”End”:”2017-09-19T18:23:54.652678939-04:00″,”ExitCode”:0,”Output”:” % Total % Received % Xferd Average Speed Time Time Time Current\n Dload Upload Total Spent Left Speed\n\r 0 0 0 0 0 0 0 0 –:–:– –:–:– –:–:– 0\r100 11 100 11 0 0 1022 0 –:–:– –:–:– –:–:– 1100\nHello World”},{“Start”:”2017-09-19T18:24:54.652833383-04:00″,”End”:”2017-09-19T18:24:54.696685407-04:00″,”ExitCode”:0,”Output”:” % Total % Received % Xferd Average Speed Time Time Time Current\n Dload Upload Total Spent Left Speed\n\r 0 0 0 0 0 0 0 0 –:–:– –:–:– –:–:– 0\r100 11 100 11 0 0 842 0 –:–:– –:–:– –:–:– 916\nHello World”},{“Start”:”2017-09-19T18:25:54.696867514-04:00″,”End”:”2017-09-19T18:25:54.748451647-04:00″,”ExitCode”:0,”Output”:” % Total % Received % Xferd Average Speed Time Time Time Current\n Dload Upload Total Spent Left Speed\n\r 0 0 0 0 0 0 0 0 –:–:– –:–:– –:–:– 0\r100 11 100 11 0 0 814 0 –:–:– –:–:– –:–:– 846\nHello World”},{“Start”:”2017-09-19T18:26:54.74862166-04:00″,”End”:”2017-09-19T18:26:54.798137953-04:00″,”ExitCode”:0,”Output”:” % Total % Received % Xferd Average Speed Time Time Time Current\n Dload Upload Total Spent Left Speed\n\r 0 0 0 0 0 0 0 0 –:–:– –:–:– –:–:– 0\r100 11 100 11 0 0 663 0 –:–:– –:–:– –:–:– 687\nHello World”},{“Start”:”2017-09-19T18:27:54.798446904-04:00″,”End”:”2017-09-19T18:27:54.845142125-04:00″,”ExitCode”:0,”Output”:” % Total % Received % Xferd Average Speed Time Time Time Current\n Dload Upload Total Spent Left Speed\n\r 0 0 0 0 0 0 0 0 –:–:– –:–:– –:–:– 0Hello World\r100 11 100 11 0 0 991 0 –:–:– –:–:– –:–:– 1100\n”}]}

JAX-RS – How to bind Filters to JAX-RS resources with Name Binding

In my earlier post, I have given an example to know how to bind the Filters to JAX-RS resources with Dynamic Binding.

Refer it @ JAX-RS Dynamic Binding

In this post, I am going to show how we can do that with Name Binding.

Follow the below steps to do that.

1. Create a custom annotation which uses @NameBinding annotation.


package com.resource;

import javax.ws.rs.NameBinding;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@NameBinding
@Target({ ElementType.METHOD, ElementType.TYPE})
@Retention(value = RetentionPolicy.RUNTIME)
public @interface AppKeyVerifier {}

2. Create a filter and implement the app key verification logic. Then apply the custom annotation to it.


package com.resource;

import com.model.AppError;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.Provider;
import java.io.IOException;

@Provider
@AppKeyVerifier
public class AppKeyVerifierFilter implements ContainerRequestFilter {

    private final static Logger LOGGER = LoggerFactory.getLogger(AppKeyVerifierFilter.class);

    private final static String APP_KEY = "994f4fe4-APP-KEY-f3d5af27e1ee";

    @Context
    private HttpServletRequest httpServletRequest;

    @Override
    public void filter(ContainerRequestContext requestContext) throws IOException {

        String appKeyValueFromHeader = requestContext.getHeaderString("APP-KEY");
        LOGGER.info("APP Key:{}", appKeyValueFromHeader);
        if (!StringUtils.equals(APP_KEY, appKeyValueFromHeader) ) {
            requestContext.abortWith(Response.status(Response.Status.UNAUTHORIZED)
                                             .entity(new AppError("APP-KEY is not available or wrong"))
                                             .build());

        }
    }
}

3. Then apply the custom annotation to the target resource classes or methods.


package com.resource;

import com.model.User;
import com.service.UserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.inject.Inject;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import java.util.List;

@AppKeyVerifier
@Path("users")
public class UserResource {

    private final static Logger LOGGER = LoggerFactory.getLogger(UserResource.class);

    @Inject
    UserService userService;

    @GET
    @Path("get/{id}")
    @Produces(MediaType.APPLICATION_JSON)
    public User get(@PathParam("id") String id) throws Exception {
        LOGGER.debug("get method is called with id:{}", id);
        return userService.get(id);
    }
    @GET
    @Path("getAll")
    @Produces(MediaType.APPLICATION_JSON)
    public List getAll() throws Exception {
        LOGGER.debug("getAll method is called");
        return userService.getAll();
    }

    @POST
    @Path("add")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public String save(User user) throws Exception {
        LOGGER.debug("save method is called with user:{}", user);
        return userService.save(user);
    }

    @DELETE
    @Path("delete/{id}")
    @Produces(MediaType.TEXT_PLAIN)
    public String remove(@PathParam("id") String id) throws Exception {
        LOGGER.debug("remove method is called with id:{}", id);
        return userService.remove(id);
    }

    @POST
    @Path("update")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public String update(User user) throws Exception {
        LOGGER.debug("update method is called with user:{}", user);
        return userService.update(user);
    }
}

Refer my code @https://github.com/dkbalachandar/java-rest-docker

JAX-RS – How to bind Filters to JAX-RS resources with Dynamic Binding

JAX-RS provides multiple ways using which server side filters and interceptors can be bound to their target components.

By default, JAX-RS filters and interceptors are applied to all the methods of a resource class. This can be overridden with Named Binding or Dynamic binding. In this post, I am going to give an example to show how to do that.

Assume that we have a JAX-RS application which has two end points. They are “greeting” and “users”. Now we want to protect the “users” service from unauthorized access. So we want to intercept all the “users” service request and do some validation and then allow it if it’s valid. Assume that the client has to pass through an APP-KEY in the request header.

Here are my resource classes.

UserResource.java


package com.resource;

import com.model.User;
import com.service.UserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.inject.Inject;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import java.util.List;

@Path("users")
public class UserResource {

    private final static Logger LOGGER = LoggerFactory.getLogger(UserResource.class);

    @Inject
    UserService userService;

    @GET
    @Path("get/{id}")
    @Produces(MediaType.APPLICATION_JSON)
    public User get(@PathParam("id") String id) throws Exception {
        LOGGER.debug("get method is called with id:{}", id);
        return userService.get(id);
    }
    @GET
    @Path("getAll")
    @Produces(MediaType.APPLICATION_JSON)
    public List getAll() throws Exception {
        LOGGER.debug("getAll method is called");
        return userService.getAll();
    }

    @POST
    @Path("add")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public String save(User user) throws Exception {
        LOGGER.debug("save method is called with user:{}", user);
        return userService.save(user);
    }

    @DELETE
    @Path("delete/{id}")
    @Produces(MediaType.TEXT_PLAIN)
    public String remove(@PathParam("id") String id) throws Exception {
        LOGGER.debug("remove method is called with id:{}", id);
        return userService.remove(id);
    }

    @POST
    @Path("update")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public String update(User user) throws Exception {
        LOGGER.debug("update method is called with user:{}", user);
        return userService.update(user);
    }
}

HelloWorldResource.java



package com.resource;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

@Path("/greeting")
public class HelloWorldResource {

    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public Response sayHello(){
        System.out.println("sayHello");
        return Response.ok().entity("Hello World").build();
    }
}

Dynamic binding

It provides a way to add/bind the filters to resource methods/classes programmatically.

We have to add a Feature class which implements the DynamicFeature interface. Then override the configure method and provide our own logic to bind the filers to resource methods.

In my code, I am checking the resource class name with the APP_CLASS_LIST list. If that list contains the class name, then binding the AppRequestFilter to that class. I don’t want to filter the greeting service. Hence the APP_CLASS_LIST contains only the UserResource class name alone.

Refer the below example.


package com.resource;

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

import javax.ws.rs.container.DynamicFeature;
import javax.ws.rs.container.ResourceInfo;
import javax.ws.rs.core.FeatureContext;
import javax.ws.rs.ext.Provider;
import java.util.Arrays;
import java.util.List;

@Provider
public class AppKeyFeature implements DynamicFeature {


    private final static Logger LOGGER = LoggerFactory.getLogger(AppKeyFeature.class);

    private static final List APP_CLASS_LIST = Arrays.asList(UserResource.class);

    @Override
    public void configure(ResourceInfo resourceInfo, FeatureContext context) {
        LOGGER.info("resourceInfo.getResourceClass():{}", resourceInfo.getResourceClass());
        if (APP_CLASS_LIST.contains(resourceInfo.getResourceClass())) {
            context.register(AppRequestFilter.class);
        }
    }
}

Refer below my filter code. This filter will validate the APP_KEY available in the request header with the default one. If it does not match, then it will abort the request and throw an error message. Make sure that you should not add @provider annotation for AppRequestFilter.


package com.resource;

import com.model.AppError;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import java.io.IOException;

public class AppRequestFilter implements ContainerRequestFilter {

    private final static Logger LOGGER = LoggerFactory.getLogger(AppRequestFilter.class);

    private final static String APP_KEY = "994f4fe4-APP-KEY-f3d5af27e1ee";

    @Context
    private HttpServletRequest httpServletRequest;

    @Override
    public void filter(ContainerRequestContext requestContext) throws IOException {

        String appKeyValueFromHeader = requestContext.getHeaderString("APP-KEY");
        LOGGER.info("APP Key:{}", appKeyValueFromHeader);
        if (!StringUtils.equals(APP_KEY, appKeyValueFromHeader) ) {
            requestContext.abortWith(Response.status(Status.UNAUTHORIZED)
                                             .entity(new AppError("APP-KEY is not available or wrong"))
                                             .build());

        }
    }
}

Refer my code @https://github.com/dkbalachandar/java-rest-docker

Mockito Tutorial

Mockito is a testing framework and widely used now. Lets see how to use this in this tutorial.

I am going to use Maven + Java 8 + Mockito 2.0.2-beta version for this example.

Assume that we have a class called User Service which does save, get, remove and update operation on DB. So UserService class contains an instance of UserDao class which does all the CRUD operations. Here are those classes.

UserService.java


package com;

import java.util.UUID;

public class UserService {

    private UserDao userDao;

    public UserService(UserDao userDao) {
        this.userDao = userDao;
    }

    public User get(String id) {
        return userDao.get(id);
    }

    public String save(String firstName, String lastName, int age) throws Exception {
        User user = new User();
        user.setAge(age);
        user.setFirstName(firstName);
        user.setLastName(lastName);
        user.setId(UUID.randomUUID().toString());
        return userDao.save(user);
    }

    public String remove(String id) throws Exception {
        return userDao.remove(id);
    }

    public String update(String id, String firstName, String lastName, int age) throws Exception {
        User user = new User();
        user.setAge(age);
        user.setFirstName(firstName);
        user.setLastName(lastName);
        user.setId(id);
        return userDao.update(user);
    }
}

UserDao.java



package com;

public interface UserDao {
    public User get(String id);
    public String save(User user) throws Exception;
    public String remove(String id) throws Exception;
    public String update(User user) throws Exception;
}


UserDaoImpl.java
Its a dummy class only and actual implementation may be different


package com;

public class UserDaoImpl implements UserDao {

    @Override
    public User get(String id) {
        //Dummy implementation
        return null;
    }

    @Override
    public String save(User user) throws Exception {
        return "id";
    }

    @Override
    public String remove(String id) throws Exception {
       return id;
    }

    @Override
    public String update(User user) throws Exception {
        return "id";
    }
}


Now we want to mock the UserDao class and write the unit test cases for the UserService class. Here is my Junit test case


import com.User;
import com.UserDao;
import com.UserService;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;

import java.util.UUID;

import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.times;

public class UserServiceTest {

    UserDao userDao;

    User mockUser;

    UserService userService;

    @Before
    public void setUp() {
        userDao = Mockito.mock(UserDao.class);
        userService = new UserService(userDao);
        mockUser = new User();
        mockUser.setId(UUID.randomUUID().toString());
        mockUser.setFirstName("test");
        mockUser.setLastName("test");
        mockUser.setAge(40);
    }

    @Test
    public void testSave() throws Exception {
        //Using argument captor to test the values passed to the UserDao.save method
        ArgumentCaptor userArgumentCaptor = ArgumentCaptor.forClass(User.class);
        userService.save("bala", "samy", 35);
        Mockito.verify(userDao).save(userArgumentCaptor.capture());
        //Test the method called once
        Mockito.verify(userDao, times(1)).save(any());
        User storedUser = userArgumentCaptor.getValue();
        assertEquals("bala", storedUser.getFirstName());
        assertEquals("samy", storedUser.getLastName());
        assertEquals(35, storedUser.getAge());

    }

    @Test
    public void testGetUsingSpy() throws Exception {
        UserService userService = new UserService(userDao);
        UserService spy = Mockito.spy(userService);
        Mockito.when(spy.get(mockUser.getId())).thenReturn(mockUser);
        assertEquals(mockUser, spy.get(mockUser.getId()));
    }

    @Test
    public void testGetWithMock() throws Exception {
        Mockito.when(userDao.get(mockUser.getId())).thenReturn(mockUser);
        assertEquals(mockUser, userService.get(mockUser.getId()));
    }

    @Test
    public void testSaveWithMock() throws Exception {
        Mockito.when(userDao.save(any())).thenReturn(mockUser.getId());
        String value = userService.save(mockUser.getFirstName(), mockUser.getLastName(), mockUser.getAge());
        assertEquals(mockUser.getId(), value);
    }

    @Test
    public void testRemoveWithMock() throws Exception {
        Mockito.when(userDao.remove(any())).thenReturn(mockUser.getId());
        assertEquals(mockUser.getId(),userService.remove(mockUser.getId()));
    }

}


Argument Captor:

In the testSave method, I have used Argument Captor to capture the arguments that are getting passed to the UserDao.save method. Here we are passing the User Object to that method. So if we want to verify the async call or test the arguments to any class, then we could use Argument Captor.

In all the remaining test methods, I have mocked the methods of UserDao class.

Refer the code @https://github.com/dkbalachandar/mockitoExample