The ReflectionUtils can not access a member of class with modifiers “private” exception occurs when the default constructor or method is configured as private in the java bean class. If the class method or properties are configured as private, the java reflection can not access the member of class with the modifiers as private.

In the spring boot method, if a java object is created using a json string, the exception javax.json.bind.JsonbException: Can’t create instance will be thrown. Json binding is a standard that has been implemented for java as part of the JSR 367 standard. If the json binding api is unable to construct an instance of the java class, this exception java.lang.IllegalAccessException: Class org.eclipse.yasson.internal.ReflectionUtils can not access a member of class with modifiers “private” will be thrown.

We’ll see in this article about this exception and how to remedy this exception. The trace of the stack below will be displayed in the console window if the spring boot application throws this exception.



Exception

2020-03-14 22:19:47.417 ERROR 25284 --- [           main] o.eclipse.yasson.internal.Unmarshaller   : Can't create instance
Exception in thread "main" javax.json.bind.JsonbException: Can't create instance
	at org.eclipse.yasson.internal.ReflectionUtils.createNoArgConstructorInstance(ReflectionUtils.java:227)
	at org.eclipse.yasson.internal.serializer.ObjectDeserializer.getInstance(ObjectDeserializer.java:103)
	at org.eclipse.yasson.internal.serializer.AbstractContainerDeserializer.deserialize(AbstractContainerDeserializer.java:65)
	at org.eclipse.yasson.internal.Unmarshaller.deserializeItem(Unmarshaller.java:66)
	at org.eclipse.yasson.internal.Unmarshaller.deserialize(Unmarshaller.java:52)
	at org.eclipse.yasson.internal.JsonBinding.deserialize(JsonBinding.java:59)
	at org.eclipse.yasson.internal.JsonBinding.fromJson(JsonBinding.java:66)
	at com.yawintutor.SpringBootJsonbSimpleApplication.JSONToJavaObject(SpringBootJsonbSimpleApplication.java:66)
	at com.yawintutor.SpringBootJsonbSimpleApplication.main(SpringBootJsonbSimpleApplication.java:19)
Caused by: java.lang.IllegalAccessException: Class org.eclipse.yasson.internal.ReflectionUtils can not access a member of class com.yawintutor.Student with modifiers "private"
	at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:102)
	at java.lang.reflect.AccessibleObject.slowCheckMemberAccess(AccessibleObject.java:296)
	at java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:288)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:413)
	at org.eclipse.yasson.internal.ReflectionUtils.createNoArgConstructorInstance(ReflectionUtils.java:225)
	... 8 more


Root Cause

The json binding api is used to convert a java object to a json string. In the same way, json binding api will convert a json string to a java object. If a json string is passed as an input, json binding api generates a java object and assigns all values to the respective fields.

When a json binding api is unable to construct an instance of a java object due to a variety of reasons, the exception will be thrown. The internal stack trace of the exception will reveal the real reason for the failure.



How to reproduce this issue

Build a Java Bean class without the default configuration in the spring boot program. The json binding api attempts to build a java object using the default constructor. As the default constructor is not available, this exception is thrown. The sample of the java bean is shown as below

Student.java

package com.yawintutor;

public class Student {

	private int id;

	private String name;

	private Student() {
		
	}
	
	public static Student getInstance() {
		return new Student();
	}
	
	public int getId() {
		return id;
	}

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

	public String getName() {
		return name;
	}

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

}

The default constructor in the above class is a private function. The default constructor can not be accessed from outside the class. The instance is created using a static method.



Solution 1

The java bean class must have a default constructor available in public to create a class instance. Check the java bean class, make sure that the default instance is created without any error. This will resolve the exception.

Adjust the default constructor in the above example to be available in public. The exception’s internal stack trace will reveal the exact reason for the exception.

Student.java

package com.yawintutor;

public class Student {

	private int id;

	private String name;

	public int getId() {
		return id;
	}

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

	public String getName() {
		return name;
	}

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

}

SpringBootJsonbSimpleApplication.java

package com.yawintutor;

import javax.json.bind.Jsonb;
import javax.json.bind.JsonbBuilder;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringBootJsonbSimpleApplication {

	public static void main(String[] args) {
		SpringApplication.run(SpringBootJsonbSimpleApplication.class, args);

		JSONToJavaObject();
	}

	public static void JSONToJavaObject() {
		String jsonString = "{\"id\":100,\"name\":\"Yawin\"}";

		Jsonb jsonb = JsonbBuilder.create();
		Student st = jsonb.fromJson(jsonString, Student.class);
		System.out.println(st.getId() + " " + st.getName());
	}

}

Output


  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.2.5.RELEASE)

2020-03-14 18:39:01.234  INFO 10439 --- [           main] c.y.SpringBootJsonbSimpleApplication     : Starting SpringBootJsonbSimpleApplication on banl1691b9157 with PID 10439 (/Users/knatarajan2/STS/workspace/SpringBootJsonbSimple/target/classes started by knatarajan2 in /Users/knatarajan2/STS/workspace/SpringBootJsonbSimple)
2020-03-14 18:39:01.236  INFO 10439 --- [           main] c.y.SpringBootJsonbSimpleApplication     : No active profile set, falling back to default profiles: default
2020-03-14 18:39:01.654  INFO 10439 --- [           main] c.y.SpringBootJsonbSimpleApplication     : Started SpringBootJsonbSimpleApplication in 0.66 seconds (JVM running for 3.323)
100 Yawin


Solution 2

More details on how to use json binding api are explained in the links below.



Leave a Reply