By kswaughs | Thursday, September 5, 2024

What is Generative AI

Generative AI refers to a class of artificial intelligence models that can generate new content, such as text, images, music, or even code, based on the patterns and data they have been trained on. These models use techniques from machine learning, particularly deep learning, to create outputs that are similar to the examples they were trained on.

Usefulness for Java Developers

1. Code Generation

Boilerplate Code: Generative AI can help generate repetitive boilerplate code, saving time and reducing errors.

Code Snippets: It can provide code snippets for common tasks, such as database connections, REST API endpoints and more.

2. Code Completion

Intelligent Suggestions: Tools like GitHub Copilot can offer intelligent code completion suggestions, helping developers write code faster and with fewer errors.

3. Documentation

Auto-Generated Documentation: Generative AI can help create documentation for code, including comments, README files, and API documentation.

4. Bug Fixing

Error Detection and Correction: AI can assist in identifying bugs and suggesting possible fixes, improving code quality and reducing debugging time.

5. Learning and Training

Educational Tools: Generative AI can be used to create educational content, tutorials, and examples to help developers learn new concepts and technologies.

6. Testing

Test Case Generation: AI can generate test cases based on the code, ensuring better test coverage and more robust applications.


Example Tools

GitHub Copilot: An AI-powered code completion tool that integrates with IDEs like IntelliJ IDEA, providing real-time code suggestions.

TabNine: An AI code completion tool that supports multiple programming languages, including Java.

Kite: An AI-powered coding assistant that offers code completions and documentation.

Generative AI can significantly enhance productivity, reduce development time, and improve code quality for Java developers.

Recommend this on


By kswaughs | Thursday, August 22, 2024

SOLID Principles Java Example

1. Single Responsibility Principle (SRP)

2. Open/Closed Principle (OCP)

3. Liskov Substitution Principle (LSP)

4. Interface Segregation Principle (ISP)

5. Dependency Inversion Principle (DIP)

1. Single Responsibility Principle (SRP)

A class should have only one reason to change, meaning it should have only one job or responsibility.

Example

// Class responsible for handling user data
public class User {
    private String name;
    private String email;

    // Getters and setters
}

// Class responsible for user persistence
public class UserRepository {
    public void save(User user) {
        // Code to save user to database
    }
}

2. Open/Closed Principle (OCP)

It states that software entities (classes, modules, functions, etc.) should be open for extension but closed for modification. This means that the behavior of a module can be extended without modifying its source code.

Key Points
1. Open for Extension: You should be able to add new functionality to the module.
2. Closed for Modification: You should not change the existing code of the module.

Consider a scenario where you have a `Shape` class and you want to calculate the area of different shapes like `Circle` and `Rectangle`. Initially, you might have a single class with a method that handles all shapes, which violates the Open/Closed Principle.

Bad Example (Violating OCP)

public class Shape {
    public enum Type { CIRCLE, RECTANGLE }

    private Type type;
    private double radius;
    private double width;
    private double height;

    public Shape(Type type, double radius, double width, double height) {
        this.type = type;
        this.radius = radius;
        this.width = width;
        this.height = height;
    }

    public double calculateArea() {
        switch (type) {
            case CIRCLE:
                return Math.PI * radius * radius;
            case RECTANGLE:
                return width * height;
            default:
                throw new UnsupportedOperationException("Shape type not supported");
        }
    }
}

In this example, if you want to add a new shape, you need to modify the `Shape` class, which violates the Open/Closed Principle.

Good Example (Adhering to OCP):

  • Define an abstract `Shape` class with an abstract `calculateArea` method.
  • Create concrete classes for each shape that extend the `Shape` class and implement the `calculateArea` method.
Good Example (Adhering to OCP)

// Abstract Class:

public abstract class Shape {
    public abstract double calculateArea();
}

// Concrete Classes:

public class Circle extends Shape {
    private double radius;

    public Circle(double radius) {
        this.radius = radius;
    }

    @Override
    public double calculateArea() {
        return Math.PI * radius * radius;
    }
}

public class Rectangle extends Shape {
    private double width;
    private double height;

    public Rectangle(double width, double height) {
        this.width = width;
        this.height = height;
    }

    @Override
    public double calculateArea() {
        return width * height;
    }
}

// Usage:

public class Main {
    public static void main(String[] args) {
        Shape circle = new Circle(5);
        Shape rectangle = new Rectangle(4, 6);

        System.out.println("Circle Area: " + circle.calculateArea());
        System.out.println("Rectangle Area: " + rectangle.calculateArea());
    }
}

In this refactored example, the `Shape` class is open for extension (you can add new shapes by creating new subclasses) but closed for modification (you don't need to change the existing `Shape` class to add new shapes).

3. Liskov Substitution Principle (LSP)

It states that objects of a superclass should be replaceable with objects of a subclass without affecting the correctness of the program. In other words, if class `S` is a subclass of class `T`, then objects of type `T` should be replaceable with objects of type `S` without altering the desirable properties of the program (correctness, task performed, etc.).

Key Points
1. Subtypes must be substitutable for their base types: Derived classes must be substitutable for their base classes.
2. Behavioral compatibility: Subtypes must behave in a way that does not violate the expectations established by the base type.

Consider a scenario where you have a base class `Bird` and a subclass `Ostrich`. According to LSP, the `Ostrich` class should be able to replace the `Bird` class without causing issues.

Bad Example (Violating LSP)
// Base Class:

public class Bird {
    public void fly() {
        System.out.println("Bird is flying");
    }
}


// Subclass Violating LSP:

public class Ostrich extends Bird {
    @Override
    public void fly() {
        throw new UnsupportedOperationException("Ostrich can't fly");
    }
}

In this example, the `Ostrich` class violates the Liskov Substitution Principle because it changes the expected behavior of the `fly` method. To adhere to LSP, we should design our classes in a way that does not violate the expectations of the base class.

Good Example (Adhering to LSP)

//Base Class:

public abstract class Bird {
    public abstract void move();
}

// Subclass:

public class FlyingBird extends Bird {
    @Override
    public void move() {
        System.out.println("Bird is flying");
    }
}

public class Ostrich extends Bird {
    @Override
    public void move() {
        System.out.println("Ostrich is running");
    }
}

// Usage:

public class BirdWatcher {
    public void watchBird(Bird bird) {
        bird.move();
    }

    public static void main(String[] args) {
        BirdWatcher watcher = new BirdWatcher();
        Bird flyingBird = new FlyingBird();
        Bird ostrich = new Ostrich();

        watcher.watchBird(flyingBird); // Output: Bird is flying
        watcher.watchBird(ostrich);    // Output: Ostrich is running
    }
}

In this refactored example, both `FlyingBird` and `Ostrich` adhere to the Liskov Substitution Principle by providing their own implementation of the `move` method, which does not violate the expectations of the `Bird` class.

4. Interface Segregation Principle (ISP)

It states that no client should be forced to depend on methods it does not use. This means that larger interfaces should be split into smaller, more specific ones so that clients only need to know about the methods that are of interest to them.

Key Points
1. Clients should not be forced to implement interfaces they do not use: This avoids "fat" interfaces.
2. Interfaces should be client-specific: Each interface should be tailored to the specific needs of a client.

Consider a scenario where you have an interface `Worker` that has methods for different types of workers.

Bad Example (Violating ISP)

public interface Worker {
    void work();
    void eat();
}

public class HumanWorker implements Worker {

    @Override
    public void work() {
        System.out.println("Human is working");
    }

    @Override
    public void eat() {
        System.out.println("Human is eating");
    }
}

public class RobotWorker implements Worker {

    @Override
    public void work() {
        System.out.println("Robot is working");
    }

    @Override
    public void eat() {
        // Robot does not eat, but forced to implement this method
        throw new UnsupportedOperationException("Robot does not eat");
    }
}

In this example, the 'RobotWorker' class is forced to implement the `eat` method, which it does not need, violating the Interface Segregation Principle.

Good Example (Adhering to ISP)
public interface Workable {
    void work();
}

public interface Eatable {
    void eat();
}

public class HumanWorker implements Workable, Eatable {
    @Override
    public void work() {
        System.out.println("Human is working");
    }

    @Override
    public void eat() {
        System.out.println("Human is eating");
    }
}

public class RobotWorker implements Workable {
    @Override
    public void work() {
        System.out.println("Robot is working");
    }
}

In this refactored example, the 'Worker interface is split into 'Workable' and 'Eatable' interfaces. Now, 'RobotWorker' only implements the 'Workable' interface, adhering to the Interface Segregation Principle.

5. Dependency Inversion Principle (DIP)

It states that high-level modules should not depend on low-level modules. Both should depend on abstractions. Additionally, abstractions should not depend on details. Details should depend on abstractions.

Consider a scenario where you have a `Light` class and a `Switch` class. The `Switch` class directly depends on the `Light` class, which violates the Dependency Inversion Principle.

Bad Example (Violating DIP)

public class Light {
    public void turnOn() {
        System.out.println("Light is turned on");
    }

    public void turnOff() {
        System.out.println("Light is turned off");
    }
}

public class Switch {
    private Light light;

    public Switch(Light light) {
        this.light = light;
    }

    public void operate(String command) {
        if (command.equalsIgnoreCase("ON")) {
            light.turnOn();
        } else if (command.equalsIgnoreCase("OFF")) {
            light.turnOff();
        }
    }
}

In this example, the `Switch` class directly depends on the `Light` class, which is a low-level module.

1. Define an abstraction for the `Switchable` interface. 2. Implement the `Switchable` interface in the `Light` class. 3. Modify the `Switch` class to depend on the `Switchable` interface.

Good Example (Adhering to DIP)

// Abstraction
public interface Switchable {
    void turnOn();
    void turnOff();
}

//Low-level Module
public class Light implements Switchable {

    @Override
    public void turnOn() {
        System.out.println("Light is turned on");
    }

    @Override
    public void turnOff() {
        System.out.println("Light is turned off");
    }
}

//High-level Module
public class Switch {
    private Switchable device;

    public Switch(Switchable device) {
        this.device = device;
    }

    public void operate(String command) {
        if (command.equalsIgnoreCase("ON")) {
            device.turnOn();
        } else if (command.equalsIgnoreCase("OFF")) {
            device.turnOff();
        }
    }
}

In this refactored example, the `Switch` class depends on the `Switchable` interface, which is an abstraction. The `Light` class implements the `Switchable` interface. This way, the high-level module (`Switch`) does not depend on the low-level module (`Light`), adhering to the Dependency Inversion Principle.

Recommend this on


By kswaughs | Monday, June 22, 2020

Java CompleteableFuture Example

CompleteableFuture is an extension to Java's Future API that allows us to write a non-blocking code.

It runs a task on a separate thread and notifies the main thread about its completion or failure.

ForkJoinPool.commonPool() is the default thread pool that runs the task.

CompleteableFutureExample.java
package com.kswaughs.examples;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.TimeUnit;

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

import com.kswaughs.model.Book;

public class CompleteableFutureExample {

    private static Logger log = LoggerFactory.getLogger("CompleteableFutureExample");

    public static void main(String[] args) {

        CompletableFuture<Book> resultbook = CompletableFuture.supplyAsync(() -> {
            log.info("I am Taking 3 secs to return a book");
            // Sleep for 3 seconds..
            sleep(3000);
            return getBook();
        });

        resultbook.thenAccept(book -> {
            log.info("Book received: \n {}", book);
        });

        log.info("I am not waiting for the book object");
        log.info("I will continue with other work..");

        // To prevent this program from terminating prematurely
        ForkJoinPool.commonPool().awaitQuiescence(10, TimeUnit.SECONDS);
    }

    private static Book getBook() {

        Book book = new Book();

        book.setBookId(123);
        book.setAuthor("John Grisham");
        book.setTitle("A Painted House");

        log.info("Returning book object");

        return book;
    }

    private static void sleep(int waitTime) {
        try {
            Thread.sleep(waitTime);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

Output

21:01:42.742 [main] INFO CompleteableFutureExample - I am not waiting for the book object
21:01:42.742 [ForkJoinPool.commonPool-worker-1] INFO CompleteableFutureExample - I am Taking 3 secs to return a book
21:01:42.744 [main] INFO CompleteableFutureExample - I will continue with other work..
21:01:45.745 [ForkJoinPool.commonPool-worker-1] INFO CompleteableFutureExample - Returning book object
21:01:45.745 [main] INFO CompleteableFutureExample - Book received: 
 Book [bookId=123, title=A Painted House, author=John Grisham]

Recommend this on


By kswaughs | Tuesday, May 5, 2020

How to get previous or next item of list in Java using Streams

Basically Java Streams does not provide any in-built operators to get previous or next item while processing current item of the list.

But we can achieve this by using reduce operator properly as per our needs.

In this example, we have list of transactions and each transaction has 'id' and 'currentBalance' fields. Now we will populate 'previousBalance' field of each transaction from previous transaction object.

TransactionExample.java
package com.kswaughs.example;

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

import com.kswaughs.model.Transaction;

public class TransactionExample {

    public static void main(String[] args) {
        
        List<Transaction> items = new ArrayList<>();
        items.add(new Transaction(1, 100.0));
        items.add(new Transaction(2, 200.0));
        items.add(new Transaction(3, 300.0));
        items.add(new Transaction(4, 400.0));

        items.stream().reduce((a,b) -> {
            b.setPrviousBalance(a.getCurrentBalance());
            return b;
        });
        
        System.out.println(items);
    }
}

Model class

Transaction.java
package com.kswaughs.model;

public class Transaction {

    private int id;
    
    private double currentBalance;
    
    private double prviousBalance;
    
    public Transaction(int id, double currentBalance) {
        this.id = id;
        this.currentBalance = currentBalance;
    }

    public int getId() {
        return id;
    }

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

    public double getCurrentBalance() {
        return currentBalance;
    }

    public void setCurrentBalance(double currentBalance) {
        this.currentBalance = currentBalance;
    }

    public double getPrviousBalance() {
        return prviousBalance;
    }

    public void setPrviousBalance(double prviousBalance) {
        this.prviousBalance = prviousBalance;
    }

    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();
        builder.append("Transaction [id=").append(id)
            .append(", currentBalance=").append(currentBalance)
            .append(", prviousBalance=").append(prviousBalance)
            .append("]\n");
        return builder.toString();
    }
}

Output

[Transaction [id=1, currentBalance=100.0, prviousBalance=0.0]
, Transaction [id=2, currentBalance=200.0, prviousBalance=100.0]
, Transaction [id=3, currentBalance=300.0, prviousBalance=200.0]
, Transaction [id=4, currentBalance=400.0, prviousBalance=300.0]
]

Recommend this on


By kswaughs | Thursday, March 10, 2016

How to call multiple methods in parallel with different return types.

In a multi-thread programming applications development, Java concurrency API provides an ExecutorService interface that represents an asynchronous execution mechanism which is capable of executing multiple tasks in the background. This mechanism separates the task creation and its execution. With an executor, we only have to implement the Runnable objects and send them to the executor. ExecutorService takes care of their execution, instantiation, and running with necessary threads.

In this example, I am not only explaining how to use this ExecutorService, But also how to design your java classes like tasks, data models that will be used in real time applications.

The requirement is to write a processor that takes userId as an input and call two different back-end methods to get personal and employee information simultaneously. Read those response objects and build an user data object and send it as an output.

Step 1 : Create below data model classes

PersonalData - To hold user personal data returned by personal back-end method

PersonalData.java
package com.kswaughs.concurrency.beans;

public class PersonalData {

    private String userId;
    
    private String userName;
    
    private String homeAddress;

    public String getUserId() {
        return userId;
    }

    public void setUserId(String userId) {
        this.userId = userId;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getHomeAddress() {
        return homeAddress;
    }

    public void setHomeAddress(String homeAddress) {
        this.homeAddress = homeAddress;
    }
}

EmployeeData - To hold user employee data returned by employee back-end method

EmployeeData.java
package com.kswaughs.concurrency.beans;

public class EmployeeData {

    private String userId;
    
    private String designation;
    
    private String officeAddress;

    public String getUserId() {
        return userId;
    }
    
    public void setUserId(String userId) {
        this.userId = userId;
    }

    public String getDesignation() {
        return designation;
    }

    public void setDesignation(String designation) {
        this.designation = designation;
    }

    public String getOfficeAddress() {
        return officeAddress;
    }

    public void setOfficeAddress(String officeAddress) {
        this.officeAddress = officeAddress;
    }
}

UserData - To hold user data that includes personal and employee data returned by our application

UserData.java
package com.kswaughs.concurrency.beans;

public class UserData {
    
    private String userId;
    
    private String userName;
    
    private String homeAddress;

    private String designation;
    
    private String officeAddress;
    
    public UserData(String userId) {
        this.userId = userId;
    }

    public String getUserId() {
        return userId;
    }

    public void setUserId(String userId) {
        this.userId = userId;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getHomeAddress() {
        return homeAddress;
    }

    public void setHomeAddress(String homeAddress) {
        this.homeAddress = homeAddress;
    }

    public String getDesignation() {
        return designation;
    }

    public void setDesignation(String designation) {
        this.designation = designation;
    }

    public String getOfficeAddress() {
        return officeAddress;
    }

    public void setOfficeAddress(String officeAddress) {
        this.officeAddress = officeAddress;
    }

    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();
        builder.append("UserData [userId=");
        builder.append(userId);
        builder.append(", userName=");
        builder.append(userName);
        builder.append(", homeAddress=");
        builder.append(homeAddress);
        builder.append(", designation=");
        builder.append(designation);
        builder.append(", officeAddress=");
        builder.append(officeAddress);
        builder.append("]");
        return builder.toString();
    }

}

TaskResult - To hold the output returned by each back-end method and is used by ExecutorService

TaskResult.java
package com.kswaughs.concurrency.beans;

public class TaskResult {

    private String taskName;
    
    private Object result;
    
    public TaskResult(String taskName) {
        this.taskName = taskName;
    }

    public String getTaskName() {
        return taskName;
    }

    public Object getResult() {
        return result;
    }

    public void setResult(Object result) {
        this.result = result;
    }    

}

Step 2 : Create below task classes to process the request.

PersonalDataTask - This class implements Callable interface and is responsible to get personal data from a back-end method and builds PersonalData object return it in TaskResult.

PersonalDataTask.java
package com.kswaughs.concurrency.tasks;

import java.util.concurrent.Callable;

import com.kswaughs.concurrency.beans.PersonalData;
import com.kswaughs.concurrency.beans.TaskResult;

public class PersonalDataTask implements Callable<TaskResult> {

    private String id;
    
    public PersonalDataTask(String id) {
        this.id = id;
    }
    
    @Override
    public TaskResult call() throws Exception {
        
        System.out.println("PROCESSING PERSONAL_DATA : calling back-end method");
        
        PersonalData data = getPersonalData(id);
        
        TaskResult result = new TaskResult("PERSONAL_DATA");
        result.setResult(data);
        
        Thread.sleep(1000); // waiting for a second
        
        System.out.println("PROCESSING PERSONAL_DATA : received data successfully");

        return result;
    }
    
    
    private PersonalData getPersonalData(String id) {
        
        PersonalData data = new PersonalData();
        data.setUserId(id);
        data.setUserName("kswaughs");
        data.setHomeAddress("Banjara Hills-Hyderabad");
        
        return data;
        
    }

}

EmployeeDataTask - This class implements Callable interface and is responsible to get employee data from a back-end method and builds EmployeeData object return it in TaskResult.

EmployeeDataTask.java
package com.kswaughs.concurrency.tasks;

import java.util.concurrent.Callable;

import com.kswaughs.concurrency.beans.EmployeeData;
import com.kswaughs.concurrency.beans.TaskResult;

public class EmployeeDataTask implements Callable<TaskResult> {

    private String id;
    
    public EmployeeDataTask(String id) {
        this.id = id;
    }
    
    @Override
    public TaskResult call() throws Exception {
 
        System.out.println("PROCESSING EMPLOYEE_DATA : calling back-end method");
        
        EmployeeData data = getEmployeeData(id);
        
        TaskResult result = new TaskResult("EMPLOYEE_DATA");
        result.setResult(data);
        
        Thread.sleep(1000); // waiting for a second
        
        System.out.println("PROCESSING EMPLOYEE_DATA : received data successfully");
        
        return result;
    }
    
    
    private EmployeeData getEmployeeData(String id) {
        
        EmployeeData data = new EmployeeData();
        data.setUserId(id);
        data.setDesignation("Manager");
        data.setOfficeAddress("Madhapur-Hyderabad");
        
        return data;
        
    }
    
}

Step 3 : Create a main processor class.

UserDataProcessor - This class takes userid as input and process the above two functionalities in parallel using ExecutorService. After getting the response from each back-end methods, aggregate the two responses into one single response object.

UserDataProcessor.java
package com.kswaughs.concurrency;

import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

import com.kswaughs.concurrency.beans.EmployeeData;
import com.kswaughs.concurrency.beans.PersonalData;
import com.kswaughs.concurrency.beans.TaskResult;
import com.kswaughs.concurrency.beans.UserData;
import com.kswaughs.concurrency.tasks.EmployeeDataTask;
import com.kswaughs.concurrency.tasks.PersonalDataTask;

public class UserDataProcessor {

    public UserData getUserData(String userId) 
        throws InterruptedException, ExecutionException {
        
        UserData userData = new UserData(userId);
        
        ExecutorService svc = Executors.newFixedThreadPool(2);
        
        Set<Callable<TaskResult>> callables = new HashSet<Callable<TaskResult>>();
        
        callables.add(new PersonalDataTask(userId));
        callables.add(new EmployeeDataTask(userId));
        
        System.out.println("PROCESSING USER_DATA : Calling tasks parallely");
        
        List<Future<TaskResult>> futures = svc.invokeAll(callables);

        for(Future<TaskResult> future : futures){
            
            processResult(userData, future);
        }
        
        svc.shutdown();
        
        System.out.println("PROCESSING USER_DATA : Finished processing the tasks");
        
        return userData;
        
    }

    private void processResult(UserData userData, Future<TaskResult> future)
            throws InterruptedException, ExecutionException {
        
        TaskResult result = future.get();
        
        if("PERSONAL_DATA".equals(result.getTaskName())) {
            
            buildPersonalData(userData, result);
        
        } else {
            
            buildEmployeeData(userData, result);
        }
    }

    private void buildPersonalData(UserData userData, TaskResult result) {
        
        PersonalData personalData = (PersonalData) result.getResult();
        
        userData.setUserName(personalData.getUserName());
        userData.setHomeAddress(personalData.getHomeAddress());
        
    }
    
    private void buildEmployeeData(UserData userData, TaskResult result) {
        
        EmployeeData empData = (EmployeeData) result.getResult();
        
        userData.setDesignation(empData.getDesignation());
        userData.setOfficeAddress(empData.getOfficeAddress());
        
    }
    
}

Step 4 : Testing

UserApplication.java
package com.kswaughs.concurrency;

import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

import com.kswaughs.concurrency.beans.UserData;

public class UserApplication {

    public static void main(String[] args) 
        throws InterruptedException, ExecutionException {
        
        UserDataProcessor processor = new UserDataProcessor();
        
        UserData data = processor.getUserData("251514");
        
        System.out.println(data);
    }
}

Console Output

PROCESSING USER_DATA : Calling tasks parallely
PROCESSING PERSONAL_DATA : calling back-end method
PROCESSING EMPLOYEE_DATA : calling back-end method
PROCESSING PERSONAL_DATA : received data successfully
PROCESSING EMPLOYEE_DATA : received data successfully
PROCESSING USER_DATA : Finished processing the tasks
UserData [userId=251514, userName=kswaughs, homeAddress=Banjara Hills-Hyderabad, designation=Manager, officeAddress=Madhapur-Hyderabad]

Recommend this on


By kswaughs | Wednesday, January 27, 2016

log4j 2 custom log level example

Creating custom log levels have become common in enterprise applications for various business purposes. In this article I am explaining you how to create and use them with log4j 2.3 version. In log4j 1.x version, we have to create a new class that extends Level class where as with log4j 2.3 version, we dont require any new java class creations.

In the below example, we will see how to create a log level 'VERIFY' whose priority is greater than INFO level.

Step 1: Configure custom Level VERIFY in log4j.xml

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" strict="true">
    <!-- Define custom levels before using them for filtering below. -->
    <CustomLevels>
        <CustomLevel name="VERIFY" intLevel="190" />
    </CustomLevels>
    <Appenders>
        <RollingFile name="RollingFile" fileName="D:/logs/log.out" 
        filePattern="D:/logs/log-%d{yyyy-MM-dd}-%i.log">
            <PatternLayout>
                <pattern>%d{MM-dd-yyyy HH:mm:ss,SSS}|%p|%m%n</pattern>
            </PatternLayout>
            <Policies>
                <SizeBasedTriggeringPolicy size="5 MB" />
            </Policies>
            <DefaultRolloverStrategy max="180"/>
        </RollingFile>
    </Appenders>
    <Loggers>
        <Root level="info">
            <AppenderRef ref="RollingFile" level="info"/>
        </Root>
    </Loggers>
</Configuration>

Step 2: Use this VERIFY log level in application

In log4j 1.x versions, Log4j framework used to look up log4j.xml or log4j.properties in classpath for configuration. But log4j 2.x versions, we have to pass configuration file path as system property "log4j.configurationFile". This also provides place holder based logging.

Log4JTest class
package com.kswaughs;

import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class Log4JTest {

    static {
        System.setProperty("log4j.configurationFile", "props/log4j-dev.xml");
    }

    static Logger logger = LogManager.getLogger();

    public static void main(String[] args) {

        logger.debug("This is a debug message");
        logger.info("This is an info message");
        logger.log(Level.getLevel("VERIFY"), "This is a sample verify message");
  
        String user = "kswaughs";
        String role = "Java Developer";
  
        logger.info("My name is '{}' and I am a {}", user, role);
    }
}

Output is:

01-27-2016 17:42:57,681|INFO|This is an info message
01-27-2016 17:42:57,682|VERIFY|This is a sample verify message
01-27-2016 17:42:57,683|INFO|My name is 'kswaughs' and I am a Java Developer

Use Below maven dependency in your pom.xml to get this log4j framework

<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.3</version>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-api</artifactId>
    <version>2.3</version>
</dependency> 

Useful Links

Create custom log level with log4j 1.x

Recommend this on


By kswaughs | Monday, December 21, 2015

How to create custom Log Level in log4J

Log4J provides different log levels like DEBUG, INFO, WARN, ERROR, TRACE which are helpful in debugging the applications. Sometimes we might need some custom log levels for various other business purposes. Log4J provides the flexibility of adding new custom log levels.

In the below example, we will see how to create a log level 'VERIFY' whose priority is greater than INFO level.

Step 1 : Create a new class VerifyLevel that extends org.apache.log4j.Level and override toLevel() methods of its class.

VerifyLevel class
 
package com.kswaughs.levels;

import org.apache.log4j.Level;

public class VerifyLevel extends Level {

    private static final long serialVersionUID = 8935350210797995740L;

    public static final int VERIFY_INT = Level.INFO_INT + 10;

    public static final Level VERIFY = new VerifyLevel(VERIFY_INT, "VERIFY", 7);
 
    protected VerifyLevel(int arg0, String arg1, int arg2) {
        super(arg0, arg1, arg2);
    }
 
    public static Level toLevel(String sArg) {
  
        if("VERIFY".equalsIgnoreCase(sArg)) {
            return VERIFY;
        }
        return (Level) toLevel(sArg, Level.DEBUG);
    }
 
    public static Level toLevel(int val) {
 
        if (val == VERIFY_INT) {
            return VERIFY;
        }
        return (Level) toLevel(val, Level.DEBUG);
    }
 
    public static Level toLevel(int val, Level defaultLevel) {
  
        if (val == VERIFY_INT) {
            return VERIFY;
        }
        return Level.toLevel(val, defaultLevel);
    }

    public static Level toLevel(String sArg, Level defaultLevel) {
  
        if("VERIFY".equalsIgnoreCase(sArg)) {
            return VERIFY;
        }
        return Level.toLevel(sArg, defaultLevel);
    }
}

Step 2: Configure VerifyLevel in log4j.properties

# Root logger option
log4j.rootLogger=debug, file, stdout

# Direct log messages to a log file
log4j.appender.file=org.apache.log4j.RollingFileAppender

log4j.appender.file.File=D:/logs/log.out
log4j.appender.file.MaxFileSize=10MB
log4j.appender.file.MaxBackupIndex=10
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n

# Direct log messages to stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n

log4j.category.VERIFY=VERIFY#com.kswaughs.levels.VerifyLevel

Step 3: Use this VERIFY log level in application

Log4JTest class
package com.kswaughs;

import org.apache.log4j.Logger;

import com.kswaughs.levels.VerifyLevel;

public class Log4JTest {

    static Logger logger = Logger.getLogger(Log4JTest.class.getName());
   
    public static void main(String[] args) {
   
        logger.debug("This is a debug message");
        logger.info("This is an info message");
        logger.log(VerifyLevel.VERIFY, "This is a sample verify message");
    }
}

Output is:

2015-12-22 11:09:25 DEBUG Log4JTest:14 - This is a debug message
2015-12-22 11:09:25 INFO  Log4JTest:15 - This is an info message
2015-12-22 11:09:25 VERIFY Log4JTest:16 - This is a sample verify message

Use Below maven dependency in your pom.xml to get this log4j framework

<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency> 

Recommend this on


By kswaughs | Thursday, December 10, 2015

Java socket programming

Java Socket programming is used to communicate between the applications that are running on different machines. A server program runs on a server machine listening with a provided port number. A client program connects to the server program through java.net.Socket class by providing IpAddress and port. Once the connection is established, client sends the message to the server and server receives the message. The communication can be happen either one-way or two-way.

Below are the examples of Server and Client programs for both ways of communication.

  • One way communication : Client -> Server
  • Two way communication : Client <-> Server

One way communication

Server program which keeps listening to receive the messages on a specific port.

Server.java
package com.kswaughs.socket;

import java.io.DataInputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;

public class Server extends Thread {

    private ServerSocket serverSocket;
 
    public Server(int port) throws IOException {
        serverSocket = new ServerSocket(port);
    }

    public void run() {
        while (true) {
            try {
    
                System.out.println("I am Server, Waiting for a client request on port " 
                    + serverSocket.getLocalPort());
    
                Socket server = serverSocket.accept();
    
                // Read input message from client
                DataInputStream in = new DataInputStream(server.getInputStream());
                String inputData = in.readUTF();
                System.out.println("Request Data:"+ inputData);
    
                server.close();
 
            } catch (SocketTimeoutException s) {
                System.out.println("Socket timed out!");
                break;
            } catch (IOException e) {
                e.printStackTrace();
                break;
            } finally {
                System.out.println("\n********** end **********\n");
            }
        }
    }

    public static void main(String[] args) {

        try {
            Thread t = new Server(1234);
            t.start();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Client program which sends message to a server.

Client.java
package com.kswaughs.socket;

import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;

public class Client {

    public static void main(String[] args) {

        try {
            String serverName = InetAddress.getLocalHost().getHostAddress();
            int port = 1234;

            Socket client = new Socket(serverName, port);

            // Send message to server
            OutputStream outToServer = client.getOutputStream();
            DataOutputStream out = new DataOutputStream(outToServer);
            out.writeUTF("Hello Server, This is my first request..");

            client.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Server logs:

I am Server, Waiting for a client request on port 1234
Request Data:Hello Server, This is my first request..

********** end **********

I am Server, Waiting for a client request on port 1234

Two way communication

Server program which keeps listening to receive the messages on a specific port and acknowledges back with the status of the request.

Server.java
package com.kswaughs.socket;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;

public class Server extends Thread {

    private ServerSocket serverSocket;
 
    public Server(int port) throws IOException {
        serverSocket = new ServerSocket(port);
    }

    public void run() {
        while (true) {
            try {

                System.out.println("I am Server, Waiting for a client request on port " 
                    + serverSocket.getLocalPort());
    
                Socket server = serverSocket.accept();
    
                // Read input message from client
                DataInputStream in = new DataInputStream(server.getInputStream());
                String inputData = in.readUTF();
                System.out.println("Request Data:"+ inputData);
    
                // Send output message to client
                OutputStream outToServer = server.getOutputStream();
                DataOutputStream out = new DataOutputStream(outToServer);
                out.writeUTF("Your request processed successfully");
    
                server.close();
 
            } catch (SocketTimeoutException s) {
                System.out.println("Socket timed out!");
                break;
            } catch (IOException e) {
                e.printStackTrace();
                break;
            } finally {
                System.out.println("\n********** end **********\n");
            }
        }
    }

    public static void main(String[] args) {

        try {
            Thread t = new Server(1234);
            t.start();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Client program which sends message to a server and receives the acknowledgement from the server.

Client.java
package com.kswaughs.socket;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;

public class Client {

    public static void main(String[] args) {

        try {
            String serverName = InetAddress.getLocalHost().getHostAddress();
            int port = 1234;

            Socket client = new Socket(serverName, port);

            // Send message to server
            OutputStream outToServer = client.getOutputStream();
            DataOutputStream out = new DataOutputStream(outToServer);
            out.writeUTF("Hello Server, This is my second request..");
   
            // Receive message from server
            DataInputStream in = new DataInputStream(client.getInputStream());
            String respData = in.readUTF();
            System.out.println("Response Data:"+ respData);

            client.close();
   
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

server logs

I am Server, Waiting for a client request on port 1234
Request Data:Hello Server, This is my second request..

********** end **********

I am Server, Waiting for a client request on port 1234

client logs

Response Data:Your request processed successfully

Recommend this on


By kswaughs | Wednesday, December 2, 2015

How to get IBM DB2 database connection in Java

In Java, java.sql.Connection object is used to perform several database operations.
Following are the different ways of creating the connection object of IBM DB2 database.

1) Using DriverManager
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class IBMDB2Connection {

    public Connection createConnection() {

        Connection con = null;
 
        try {

            Class.forName("com.ibm.db2.jcc.DB2Driver").newInstance();
            String url = "jdbc:db2://servername:portnumber/databasename";
            String userId = "username_value";
            String password = "password_value";

            con = DriverManager.getConnection(url, userId, password);

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return con;
    }
}

2) Using DataSource provided by IBM DB2
import java.sql.Connection;
import java.sql.SQLException;

import com.ibm.db2.jcc.DB2SimpleDataSource;

public class IBMDB2DataSourceConnection {

    public Connection createConnection() {
  
        Connection con = null;
        DB2SimpleDataSource db2ds = new DB2SimpleDataSource();
        db2ds.setDatabaseName("databasename");
        db2ds.setUser("username_value");
        db2ds.setPassword("password_value");
        db2ds.setPortNumber(portnumber);
  
        try {
            con = db2ds.getConnection();
        } catch (SQLException e) {
            e.printStackTrace();
        }

        return con;
    } 
} 

When you are done with SQL operations on above Connection object, Below is the method to close the connection object.

Method to close the connection
public void closeConnection(Connection con) {
    try {
        con.close();
    } catch (SQLException e) {
        e.printStackTrace();
    }
}

Recommend this on


By kswaughs | Thursday, November 26, 2015

How to read headers from REST response with Apache CXF

In my previous post, I have explained how to pass headers to RESTful services using Apache CXF.

CXF Rest client passing headers to request

For the same example, we will see how to read/parse headers from the REST response.

There are two ways to read/parse the headers from REST response

  • Example 1 - Using getHeaderString method of Response object to read a single header value
  • Example 1 - Using MultivaluedMap to read all header values

Using getHeaderString method of Response

Example 1
package com.example.cxfrs;

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

import javax.ws.rs.core.Response;

import com.example.cxfrs.beans.UserRequest;
import com.example.cxfrs.beans.UserResponse;
import org.apache.cxf.jaxrs.client.WebClient;
import org.codehaus.jackson.jaxrs.JacksonJsonProvider;

public class CXFRestPostClient {

 public static void main(String[] args) {

  // Adding JacksonJsonProvider to convert JSON String to Java object
  List<Object> providers = new ArrayList<Object>();
  providers.add(new JacksonJsonProvider());

  // Build REST request
  UserRequest req = new UserRequest();
  req.setId("1234578");
  req.setName("kswaughs");

  // Create WebClient 
  WebClient client = WebClient.create(
    "http://127.0.0.1:8080/camel-rest-0.0.1-SNAPSHOT/user/add",
    providers);

  // Adding headers
  client = client.accept("application/json").type("application/json")
    .header("consumer_id", "StandAloneRestClient")
    .header("consumer_location", "US");

  // Call the REST service
  Response r = client.post(req);
  
  //Read/parse the response headers
  System.out.println("date:"+ r.getHeaderString("Date"));
  
  // Read/parse the response
  UserResponse resp = r.readEntity(UserResponse.class);
  
  System.out.println(resp);
 }

Server log - Response

ID: 5
Response-Code: 200
Content-Type: application/json
Headers: {Content-Type=[application/json], Date=[Fri, 27 Nov 2015 06:50:34 GMT]}
Payload: {"id":"1234578","status":"Success"}

Output is

date:Fri, 27 Nov 2015 06:50:34 GMT
UserResponse [status=Success, id=1234578]

Using MultivaluedMap to read all header values

Example 2
package com.example.cxfrs;

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

import javax.ws.rs.core.MultivaluedHashMap;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;

import com.example.cxfrs.beans.UserRequest;
import com.example.cxfrs.beans.UserResponse;
import org.apache.cxf.jaxrs.client.WebClient;
import org.codehaus.jackson.jaxrs.JacksonJsonProvider;

public class CXFRestPostClient {

 public static void main(String[] args) {

  // Adding JacksonJsonProvider to convert JSON String to Java object
  List<Object> providers = new ArrayList<Object>();
  providers.add(new JacksonJsonProvider());

  // Build REST request
  UserRequest req = new UserRequest();
  req.setId("1234578");
  req.setName("kswaughs");

  // Create WebClient 
  WebClient client = WebClient.create(
    "http://127.0.0.1:8080/camel-rest-0.0.1-SNAPSHOT/user/add",
    providers);

  // Adding headers
  MultivaluedMap<String, String> reqHeaders = new MultivaluedHashMap<String, String>();
  reqHeaders.add("consumer_id", "StandAloneRestClient");
  reqHeaders.add("consumer_location", "US");
  
  client = client.accept("application/json")
                 .type("application/json")
                 .headers(reqHeaders);

  // Call the REST service
  Response r = client.post(req);
  
  //Read/parse the response headers
  MultivaluedMap<String, String> respHeaders = r.getStringHeaders();
  System.out.println("respHeaders:\n" + respHeaders);
  
  // Read/parse the response
  UserResponse resp = r.readEntity(UserResponse.class);
  
  System.out.println(resp);
 }
}

Output is

respHeaders:
{content-type=[application/json], Date=[Fri, 27 Nov 2015 07:13:16 GMT], Server=[Apache-Coyote/1.1], transfer-encoding=[chunked], Content-Type=[application/json]}

UserResponse [status=Success, id=1234578]

Recommend this on


How to pass headers to REST request with Apache CXF

In my previous posts, I have explained how to call RESTful services using Apache CXF.

CXF Rest client to call POST method using WebClient

CXF Rest client to call GET method using WebClient

For the same example, we will see how to add custom headers to the REST request.

There are two ways to add the headers.

  • Example 1 - Chained method calls of header(key, value) on WebClient object
  • Example 1 - Using MultivaluedMap to pass multiple headers

Using header(key, value) method on WebClient object

Example 1
package com.example.cxfrs;

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

import javax.ws.rs.core.Response;

import com.example.cxfrs.beans.UserRequest;
import com.example.cxfrs.beans.UserResponse;
import org.apache.cxf.jaxrs.client.WebClient;
import org.codehaus.jackson.jaxrs.JacksonJsonProvider;

public class CXFRestPostClient {

 public static void main(String[] args) {

  List<Object> providers = new ArrayList<Object>();
  providers.add(new JacksonJsonProvider());

  UserRequest req = new UserRequest();
  req.setId("1234578");
  req.setName("kswaughs");

  WebClient client = WebClient.create(
          "http://127.0.0.1:8080/camel-rest-0.0.1-SNAPSHOT/user/add",
          providers);

  client = client.accept("application/json").type("application/json")
    .header("consumer_id", "StandAloneRestClient")
    .header("consumer_location", "US");

  Response r = client.post(req);
  UserResponse resp = r.readEntity(UserResponse.class);

  System.out.println(resp);
 }
}

Using MultivaluedMap to pass multiple headers

Example 2
package com.example.cxfrs;

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

import javax.ws.rs.core.MultivaluedHashMap;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;

import com.example.cxfrs.beans.UserRequest;
import com.example.cxfrs.beans.UserResponse;
import org.apache.cxf.jaxrs.client.WebClient;
import org.codehaus.jackson.jaxrs.JacksonJsonProvider;

public class CXFRestPostClient {

 public static void main(String[] args) {

  List<Object> providers = new ArrayList<Object>();
  providers.add(new JacksonJsonProvider());
  
  UserRequest req = new UserRequest();
  req.setId("1234578");
  req.setName("kswaughs");

  WebClient client = WebClient.create(
       "http://127.0.0.1:8080/camel-rest-0.0.1-SNAPSHOT/user/add", 
       providers);
  
  MultivaluedMap<String, String> headers = 
       new MultivaluedHashMap<String, String>();
  
  headers.add("consumer_id", "StandAloneRestClient");
  headers.add("consumer_location", "US");
  
  client = client.accept("application/json").
                  type("application/json").
                  headers(headers);
  
  Response r = client.post(req);
  UserResponse resp = r.readEntity(UserResponse.class);

  System.out.println(resp);
 }
}

In the server console, See the passed header values highlighted in bold

ID: 1
Address: http://127.0.0.1:8080/camel-rest-0.0.1-SNAPSHOT/user/add
Encoding: ISO-8859-1
Http-Method: POST
Content-Type: application/json
Headers: {Accept=[application/json], cache-control=[no-cache], connection=[keep-alive], consumer_id=[StandAloneRestClient], consumer_location=[US], Content-Length=[34], content-type=[application/json], host=[127.0.0.1:8080], pragma=[no-cache], user-agent=[Apache CXF 3.1.2]}
Payload: {"id":"1234578","name":"kswaughs"}

Recommend this on


By kswaughs | Wednesday, November 25, 2015

CXF Rest Client to call POST method

I have a sample REST service with POST method running in my local system. This method is used to add user details.

The URL is 'http://127.0.0.1:8080/camel-rest-0.0.1-SNAPSHOT/user/add'

Request is

{ "id" : "12346" , "name":"kswaughs" }

Response is

{
   "id": "12346",
   "status": "Success"
}

Create a POJO class to send the request

Request Object - UserRequest
package com.example.cxfrs.beans;

public class UserRequest {

 private String id;

 private String name;

 public String getId() {
  return id;
 }

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

 public String getName() {
  return name;
 }

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

Create a POJO class to parse the JSON response into java object

Response Object - UserResponse
package com.example.cxfrs.beans;

public class UserResponse {

 private String status;

 private String id;

 public String getStatus() {
  return status;
 }

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

 public String getId() {
  return id;
 }

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

 @Override
 public String toString() {
  StringBuilder builder = new StringBuilder();
  builder.append("UserResponse [status=");
  builder.append(status);
  builder.append(", id=");
  builder.append(id);
  builder.append("]");
  return builder.toString();
 }
}

A simple stand-alone client code using WebClient and JacksonJsonProvider.

Sample Client code to call POST Method
package com.example.cxfrs;

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

import javax.ws.rs.core.Response;

import com.example.cxfrs.beans.UserRequest;
import com.example.cxfrs.beans.UserResponse;
import org.apache.cxf.jaxrs.client.WebClient;
import org.codehaus.jackson.jaxrs.JacksonJsonProvider;

public class CXFRestPostClient {

 public static void main(String[] args) {

  List<Object> providers = new ArrayList<Object>();
  providers.add(new JacksonJsonProvider());
  
  UserRequest req = new UserRequest();
  req.setId("1234578");
  req.setName("kswaughs");

  WebClient client = WebClient
    .create("http://127.0.0.1:8080/camel-rest-0.0.1-SNAPSHOT/user/add", providers);
  
  client = client.accept("application/json").type("application/json");
  
  Response r = client.post(req);
  UserResponse resp = r.readEntity(UserResponse.class);
  System.out.println(resp);
 }
}

Output is

UserResponse [status=Success, id=1234578]

Use Below maven dependency in your pom.xml to use CXF Client

<!-- To use WebClient API -->
<dependency>
 <groupId>org.apache.cxf</groupId>
 <artifactId>cxf-rt-rs-client</artifactId>
 <version>3.1.2</version>
</dependency>
<!-- To parse JSON String to Java objects --> 
<dependency>
 <groupId>org.codehaus.jackson</groupId>
 <artifactId>jackson-jaxrs</artifactId>
 <version>1.9.0</version>
</dependency> 

If you dont provide JacksonJsonProvider to WebClient, You will get below JSON parsing error.

 
org.apache.cxf.jaxrs.utils.JAXRSUtils logMessageHandlerProblem
SEVERE: No message body writer has been found for class org.example.cxfrs.beans.UserRequest, ContentType: application/json
Nov 25, 2015 3:00:48 PM org.apache.cxf.phase.PhaseInterceptorChain doDefaultLogging
WARNING: Interceptor for {http://127.0.0.1:8080/camel-rest-0.0.1-SNAPSHOT/user/add}WebClient has thrown exception, unwinding now
org.apache.cxf.interceptor.Fault: No message body writer has been found for class org.example.cxfrs.beans.UserRequest, ContentType: application/json
 at org.apache.cxf.jaxrs.client.WebClient$BodyWriter.doWriteBody(WebClient.java:1227)
 at org.apache.cxf.jaxrs.client.AbstractClient$AbstractBodyWriter.handleMessage(AbstractClient.java:1052)
 at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:308)
 at org.apache.cxf.jaxrs.client.AbstractClient.doRunInterceptorChain(AbstractClient.java:636)
 at org.apache.cxf.jaxrs.client.WebClient.doChainedInvocation(WebClient.java:1091)
 at org.apache.cxf.jaxrs.client.WebClient.doInvoke(WebClient.java:894)
 at org.apache.cxf.jaxrs.client.WebClient.doInvoke(WebClient.java:865)
 at org.apache.cxf.jaxrs.client.WebClient.invoke(WebClient.java:331)
 at org.apache.cxf.jaxrs.client.WebClient.post(WebClient.java:340)
 at org.example.cxfrs.CXFRestPostClient.main(CXFRestPostClient.java:30)
Caused by: javax.ws.rs.ProcessingException: No message body writer has been found for class org.example.cxfrs.beans.UserRequest, ContentType: application/json
 at org.apache.cxf.jaxrs.client.AbstractClient.reportMessageHandlerProblem(AbstractClient.java:754)
 at org.apache.cxf.jaxrs.client.AbstractClient.writeBody(AbstractClient.java:485)
 at org.apache.cxf.jaxrs.client.WebClient$BodyWriter.doWriteBody(WebClient.java:1222)
 ... 9 more

Exception in thread "main" javax.ws.rs.ProcessingException: org.apache.cxf.interceptor.Fault: No message body writer has been found for class org.example.cxfrs.beans.UserRequest, ContentType: application/json
 at org.apache.cxf.jaxrs.client.WebClient.doResponse(WebClient.java:1147)
 at org.apache.cxf.jaxrs.client.WebClient.doChainedInvocation(WebClient.java:1092)
 at org.apache.cxf.jaxrs.client.WebClient.doInvoke(WebClient.java:894)
 at org.apache.cxf.jaxrs.client.WebClient.doInvoke(WebClient.java:865)
 at org.apache.cxf.jaxrs.client.WebClient.invoke(WebClient.java:331)
 at org.apache.cxf.jaxrs.client.WebClient.post(WebClient.java:340)
 at org.example.cxfrs.CXFRestPostClient.main(CXFRestPostClient.java:30)
Caused by: org.apache.cxf.interceptor.Fault: No message body writer has been found for class org.example.cxfrs.beans.UserRequest, ContentType: application/json
 at org.apache.cxf.jaxrs.client.WebClient$BodyWriter.doWriteBody(WebClient.java:1227)
 at org.apache.cxf.jaxrs.client.AbstractClient$AbstractBodyWriter.handleMessage(AbstractClient.java:1052)
 at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:308)
 at org.apache.cxf.jaxrs.client.AbstractClient.doRunInterceptorChain(AbstractClient.java:636)
 at org.apache.cxf.jaxrs.client.WebClient.doChainedInvocation(WebClient.java:1091)
 ... 5 more
Caused by: javax.ws.rs.ProcessingException: No message body writer has been found for class org.example.cxfrs.beans.UserRequest, ContentType: application/json
 at org.apache.cxf.jaxrs.client.AbstractClient.reportMessageHandlerProblem(AbstractClient.java:754)
 at org.apache.cxf.jaxrs.client.AbstractClient.writeBody(AbstractClient.java:485)
 at org.apache.cxf.jaxrs.client.WebClient$BodyWriter.doWriteBody(WebClient.java:1222)
 ... 9 more

Related Links
Apache Camel SOAP Service Client
Apache CXF Rest Client to call GET method

Recommend this on


CXF Rest Client to call REST service - GET method

I have a sample REST service with GET method running in my local system. This method is used to fetch user details..

The URL is 'http://127.0.0.1:8080/camel-rest-0.0.1-SNAPSHOT/user/details/123'

Response is

{
   "status": "Success",
   "id": "123",
   "name": "kswaughs"
}

Create a model object to parse JSON response into java object.

Response Object - User
package com.example.cxfrs.beans;

public class User {

 private String status;

 private String id;

 private String name;

 public String getStatus() {
  return status;
 }

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

 public String getId() {
  return id;
 }

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

 public String getName() {
  return name;
 }

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

 @Override
 public String toString() {
  StringBuilder builder = new StringBuilder();
  builder.append("User [status=");
  builder.append(status);
  builder.append(", id=");
  builder.append(id);
  builder.append(", name=");
  builder.append(name);
  builder.append("]");
  return builder.toString();
 } 
}

A simple stand-alone client code using WebClient and JacksonJsonProvider.

Sample Client code to call get Method
package com.example.cxfrs;

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

import com.example.cxfrs.beans.User;
import org.apache.cxf.jaxrs.client.WebClient;
import org.codehaus.jackson.jaxrs.JacksonJsonProvider;

public class CXFRestClient {

 public static void main(String[] args) {

  List<Object> providers = new ArrayList<Object>();
  providers.add(new JacksonJsonProvider());

  WebClient client = WebClient
    .create("http://127.0.0.1:8080/camel-rest-0.0.1-SNAPSHOT/user/details", providers);
  
  User user = client.accept("application/json").type("application/json")
    .path("123").get(User.class);

  System.out.println(user);
 }
}

Output is

User [status=Success, id=123, name=kswaughs]

Use Below maven dependency in your pom.xml to use CXF Client

<!-- To use WebClient API -->
<dependency>
 <groupId>org.apache.cxf</groupId>
 <artifactId>cxf-rt-rs-client</artifactId>
 <version>3.1.2</version>
</dependency>
<!-- To parse JSON String to Java objects --> 
<dependency>
 <groupId>org.codehaus.jackson</groupId>
 <artifactId>jackson-jaxrs</artifactId>
 <version>1.9.0</version>
</dependency> 

If you dont provide JacksonJsonProvider to WebClient, You will get below error while parsing the JSON response.

 
org.apache.cxf.jaxrs.utils.JAXRSUtils logMessageHandlerProblem
SEVERE: No message body reader has been found for class com.example.cxfrs.beans.User, ContentType: application/json
Exception in thread "main" javax.ws.rs.client.ResponseProcessingException: No message body reader has been found for class org.apache.camel.example.cxfrs.beans.User, ContentType: application/json
 at org.apache.cxf.jaxrs.impl.ResponseImpl.reportMessageHandlerProblem(ResponseImpl.java:433)
 at org.apache.cxf.jaxrs.impl.ResponseImpl.doReadEntity(ResponseImpl.java:384)
 at org.apache.cxf.jaxrs.client.AbstractClient.readBody(AbstractClient.java:512)
 at org.apache.cxf.jaxrs.client.WebClient.handleResponse(WebClient.java:1173)
 at org.apache.cxf.jaxrs.client.WebClient.doResponse(WebClient.java:1156)
 at org.apache.cxf.jaxrs.client.WebClient.doChainedInvocation(WebClient.java:1092)
 at org.apache.cxf.jaxrs.client.WebClient.doInvoke(WebClient.java:894)
 at org.apache.cxf.jaxrs.client.WebClient.doInvoke(WebClient.java:865)
 at org.apache.cxf.jaxrs.client.WebClient.invoke(WebClient.java:428)
 at org.apache.cxf.jaxrs.client.WebClient.get(WebClient.java:611)
 at com.example.cxfrs.CXFRestClient.main(CXFRestClient.java:21)

Recommend this on


By kswaughs | Thursday, November 19, 2015

FreeMarker Java Template Engine

FreeMarker is a Java based template engine to generate text output based on templates and changing data. The text output can be HTML web pages, e-mails, configuration files, source code, etc. Basically, Three components are involved based on the below activities.

1. Text format - How the data should look like [ Template ]
2. Data - what is the data to be generated in the required format [ Data Model ]
3. Output Generator - Read the template, pass the data model and get the text output [ Freemarker library ]

Templates are written in the FreeMarker Template Language (FTL), which is a simple, specialized language. Data Model is Simple Java objects to hold the chaging data. Freemarker library has set of predefined java classes which we use to get the output.

Lets go with a sample example, we have a banking customer who spends his card at several merchants and he wants to receive the list of transactions summary on weekly basis. Below steps show how to design the data model, template and how to use Freemarker library to get the output.

1. Create a Data Model Objects to hold Customer & its Transaction details.

Customer class
package com.poc.template;

import java.util.List;

public class Customer {
 
 private String name;
 
 private String cardNumber;
 
 private String dateRange;
 
 private List transList;

 public String getName() {
  return name;
 }

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

 public String getCardNumber() {
  return cardNumber;
 }

 public void setCardNumber(String cardNumber) {
  this.cardNumber = cardNumber;
 }

 public String getDateRange() {
  return dateRange;
 }

 public void setDateRange(String dateRange) {
  this.dateRange = dateRange;
 }

 public List getTransList() {
  return transList;
 }

 public void setTransList(List transList) {
  this.transList = transList;
 }
}
Transaction Class
package com.poc.template;

public class Transaction {
 
 private String type;
 
 private String merchant;
 
 private String amount;

 public String getType() {
  return type;
 }

 public void setType(String type) {
  this.type = type;
 }

 public String getMerchant() {
  return merchant;
 }

 public void setMerchant(String merchant) {
  this.merchant = merchant;
 }

 public String getAmount() {
  return amount;
 }

 public void setAmount(String amount) {
  this.amount = amount;
 }
}

Design your template 'transSummaryTemplate.ftl'

Dear ${name},

Below are your card transaction details for the week '${dateRange}'.

Account Number : ${cardNumber}

============================================
S.No    Merchant            Type     Amount
============================================
<#list transList as trans>
${trans_index  + 1}.    ${trans.merchant}      ${trans.type}      ${trans.amount}
</#list>

First Load the template object from Freemarker Configuration object. Build the customer object with the transaction details. In this example the output content is generated as file as well as String content. When you are saving as some HTML file, you can directly display into some web page. When you generate as String, You can pass this string as email content to some Email System which will take care of sending process.

FreeMarkerExample
package com.cog.template;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.List;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;

public class FreeMarkerExample {

 public static void main(String[] args) {

  // Freemarker configuration object
  Configuration cfg = new Configuration();
  try {
   // Load template from source folder
   Template template = cfg
     .getTemplate("src/resources/templates/transSummaryTemplate.ftl");

   // Build the data-model
   Customer customer = new Customer();

   // Build customer details
   customer.setCardNumber("232487899767001");
   customer.setName("kswaughs");
   customer.setDateRange("Nov 16 2015 - Nov 22 2015");

   // Build transaction details
   List trans = buildTransactions();
   customer.setTransList(trans);

   // File output
   Writer file = new FileWriter(new File(
     "src/resources/templates/customer.html"));
   template.process(customer, file);
   file.flush();
   file.close();

   // String Output
   StringWriter strOut = new StringWriter();
   template.process(customer, strOut);
   strOut.flush();
   System.out.println(strOut.toString());
   // send strOut object as content to Send Email System. 

  } catch (IOException e) {
   e.printStackTrace();
  } catch (TemplateException e) {
   e.printStackTrace();
  }
 }

 private static List buildTransactions() {
  List trans = new ArrayList();
  // First transaction
  Transaction atmTrans = new Transaction();
  atmTrans.setMerchant("SBI ATM, Gajuwaka");
  atmTrans.setType("ATM");
  atmTrans.setAmount("3000");
  trans.add(atmTrans);

  // Second transaction
  Transaction cardTrans = new Transaction();
  cardTrans.setMerchant("IMAX, Hyderabad");
  cardTrans.setType("SWIPE");
  cardTrans.setAmount("500");
  trans.add(cardTrans);
  
  return trans;
 }
}

Output is

Dear kswaughs,

Below are your card transaction details for the week 'Nov 16 2015 - Nov 22 2015'.

Account Number : 232487899767001

============================================
S.No    Merchant            Type     Amount
============================================
1.    SBI ATM, Gajuwaka      ATM      3000
2.    IMAX, Hyderabad      SWIPE      500

Use Below maven dependency in your pom.xml to get this Freemarker template

<dependency>
 <groupId>org.freemarker</groupId>
 <artifactId>freemarker</artifactId>
 <version>2.3.20</version>
</dependency>  

Recommend this on


By kswaughs | Monday, November 9, 2015

Java Preferences - Read, Write, Import and Export

1. To write user data into user preferences

Sample code to write user preferences
public void write() throws Exception {
  
 Preferences user1Prefs = Preferences.userRoot().node("user1");
  
 user1Prefs.put("name", "Srinivas K");
 user1Prefs.put("designation", "Manager");
}

2. To read user data from user preferences

Sample code to read user preferences
public void read() throws Exception {
  
 Preferences user1Prefs = Preferences.userRoot().node("user1");
  
 System.out.println("*** user 1 details ***");
  
 System.out.println(user1Prefs.get("name", "def name val"));
 System.out.println(user1Prefs.get("designation", "def designation val"));
 System.out.println(user1Prefs.get("salary", "def salary val"));
}
Output :
*** user 1 details ***
Srinivas K
Manager
def salary val

3. To export user preferences into a XML file

Sample code to export user preferences
public void exportToFile() throws Exception {
  
 Preferences user1Prefs = Preferences.userRoot().node("user1");
  
 // To export the preferences into an xml file.
 OutputStream stream = new FileOutputStream(
   "src/resources/xml/users.xml");
 user1Prefs.exportNode(stream);
}
Output XML File :
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE preferences SYSTEM "http://java.sun.com/dtd/preferences.dtd">
<preferences EXTERNAL_XML_VERSION="1.0">
  <root type="user">
    <map/>
    <node name="user1">
      <map>
        <entry key="name" value="Srinivas K"/>
        <entry key="designation" value="Manager"/>
      </map>
    </node>
  </root>
</preferences>

4. To import user preferences from a XML file

Sample code to import user preferences
public void importFromFile() throws Exception {
  
 FileInputStream fis = new FileInputStream("src/resources/xml/users.xml");
 Preferences.importPreferences(fis);
  
    // Lets check new user2 details 
 Preferences user2Prefs = Preferences.userRoot().node("user2");
  
 System.out.println("*** user 2 details ***");
 System.out.println(user2Prefs.get("name", "def name val"));
 System.out.println(user2Prefs.get("designation", "def designation val"));

 // Lets check previous user1 details 
 Preferences user1Prefs = Preferences.userRoot().node("user1");
 
 System.out.println("*** user 1 details ***");
 System.out.println(user1Prefs.get("name", "def name val"));
 System.out.println(user1Prefs.get("designation", "def designation val"));
}
Input XML File with both users:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE preferences SYSTEM "http://java.sun.com/dtd/preferences.dtd">
<preferences EXTERNAL_XML_VERSION="1.0">
  <root type="user">
    <map/>
    <node name="user1">
      <map>
        <entry key="name" value="Srinivas K"/>
        <entry key="designation" value="Manager"/>
      </map>
    </node>
     <node name="user2">
      <map>
        <entry key="name" value="Praveen G"/>
        <entry key="designation" value="Sr Manager"/>
      </map>
    </node>
  </root>
</preferences>
Output :
*** user 2 details ***
Praveen G
Sr Manager
*** user 1 details ***
Srinivas K
Manager

Recommend this on


By kswaughs | Monday, June 8, 2015

How to read file into String in Java

Use Apache commons FileUtils class.

This is one of the best ways to read the contents of a file and store into String object.
It is a two lines statement code and it makes your application code more readable and better understandable.
Two static methods of FileUtils class are used and hence no object creation is required.

File file = FileUtils.getFile("path_to_file");
String content= FileUtils.readFileToString(file);

To use this class in your applications, You have to download the commons-io jar of Apache Commons Group.

Download the jar from below link.
https://commons.apache.org/proper/commons-io/download_io.cgi

To download the jar from Maven, Use below configuration in your project pom.xml file.

<dependency>
	<groupId>commons-io</groupId>
	<artifactId>commons-io</artifactId>
	<version>2.4</version>
</dependency>

Recommend this on


By kswaughs | Thursday, May 14, 2015

How to read content between xml tags

In Java,we have many xml parsers to read the xml string and convert into java objects.
But when we want to read or extract a small portion from xml string then no need to use those parsers.

Simply Use apache commons StringUtils.

String inputXml = "<name>Srinivas</name><city>Hyderabad</city>";
String userName = StringUtils.substringBetween(inputXml, "<name>", "</name>");

The String variable userName will have the value "Srinivas".

To use this class in your applications, You have to download the commons-lang jar of Apache Commons Group.

Download the jar from below link.
https://commons.apache.org/proper/commons-lang/download_lang.cgi

To download the jar from Maven, Use below configuration in your project pom.xml file.

<dependency>
	<groupId>commons-lang</groupId>
	<artifactId>commons-lang</artifactId>
	<version>2.6</version>
</dependency>

Recommend this on