Getting Mockito can only mock non-private & non-final classes error while running test cases - spring

I'm using Java 11. Tried almost everything, still it's not working. Done Invalidate Cache & restart as well.
[![enter image description here][1]][1]
This is the dependencies, I've added in pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>*emphasized text*
This is the class which is mocking and it's not able to mock, I've some test cases for the UserService.
This is UserServiceImpltest.java
package com.stackroute.keepnote.test.service;
import static org.junit.Assert.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import com.stackroute.keepnote.exceptions.UserNotFoundException;
import com.stackroute.keepnote.service.UserServiceImpl;
import org.junit.Before;
import org.junit.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import com.stackroute.keepnote.exceptions.UserAlreadyExistsException;
import com.stackroute.keepnote.model.User;
import com.stackroute.keepnote.repository.UserRepository;
public class UserServiceImplTest {
#Mock
UserRepository userRepository;
User user;
#InjectMocks
UserServiceImpl userService;
List<User> userList = null;
Optional<User> options;
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
user = new User();
user.setUserAddedDate(new Date());
user.setUserId("John123");
user.setUserMobile("1234567789");
user.setUserName("john");
user.setUserPassword("johnpass");
userList = new ArrayList<>();
userList.add(user);
options = Optional.of(user);
}
This is the User class, which is declare public
#Document
public class User {
/*
* This class should have five fields (userId,userName,
* userPassword,userMobile,userAddedDate). Out of these five fields, the field
* userId should be annotated with #Id (This annotation explicitly specifies the document
* identifier). This class should also contain the getters and setters for the
* fields, along with the no-arg , parameterized constructor and toString
* method.The value of userAddedDate should not be accepted from the user but
* should be always initialized with the system date.
*/
#Id
private String userId;
private String userName;
private String userPassword;
private String userMobile;
private Date userAddedDate;
public User() {
}
public User(String userId, String userName, String userPassword, String userMobile, Date userAddedDate) {
this.userId = userId;
this.userName = userName;
this.userPassword = userPassword;
this.userMobile = userMobile;
this.userAddedDate = userAddedDate;
}
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 getUserPassword() {
return userPassword;
}
public void setUserPassword(String userPassword) {
this.userPassword = userPassword;
}
public String getUserMobile() {
return userMobile;
}
public void setUserMobile(String userMobile) {
this.userMobile = userMobile;
}
public void setUserAddedDate(Date userAddedDate) {
this.userAddedDate = userAddedDate;
}

Based on your "Failed to release mocks" comment, my guess is that you have an older version of the spring-boot-starter-test dependency. If you're not able to update your spring boot version, you can update mockito and byte-buddy, either in <dependencies> or <dependencyManagement>:
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>3.6.28</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy</artifactId>
<version>1.10.19</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy-agent</artifactId>
<version>1.10.19</version>
<scope>test</scope>
</dependency>
I started seeing that "Failed to release mocks" error when I upgraded to Java SE 15:
org.mockito.exceptions.base.MockitoException:
Failed to release mocks
This should not happen unless you are using a third-part mock maker
At the bottom of the stack trace, here's the clue that it's an outdated byte-buddy problem:
Caused by: java.lang.IllegalArgumentException: Unknown Java version: 15
at net.bytebuddy.ClassFileVersion.ofJavaVersion(ClassFileVersion.java:232)
at net.bytebuddy.ClassFileVersion$VersionLocator$ForJava9CapableVm.locate(ClassFileVersion.java:485)
The version of spring-boot-starter-test that I am using has outdated mockito and byte-buddy dependencies that aren't aware of the more recent Java releases. Updating the dependencies should clear up your problem.

If you are using Spring boot, you need to remove all other dependencies (mockito, asm, jaxb-api). This starter spring-boot-starter-test make sure everything you need for your test are already there with the correct version. You can check the pom here.

Related

The request resource is not available - Spring, Hibernate, mvn

If we look into the StudentController, request mapping is #RequestMapping("/rest") for class
and get mapping is #GetMapping("/test").
Hence for url http://localhost:8080/TestHibernate/rest/test, I should get a string 'success', which I am not getting.
On executing url http://localhost:8080/TestHibernate I am getting the content placed in index file.
Please let me know what part I am missing.
Thank you.
Controller class
package com.akshay.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.akshay.dao.StudentDAO;
import com.akshay.entity.Student;
#RestController
#RequestMapping("/rest")
public class StudentController {
#Autowired
private StudentDAO studentDAO;
#PostMapping("/saveStudent")
public String save(#RequestBody Student student) {
studentDAO.saveStudent(student);
return "Saved Successfully";
}
#GetMapping("/test")
public String test() {
return "Success";
}
}
DAO Layer
package com.akshay.dao;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import com.akshay.entity.Student;
#Repository
#Transactional
public class StudentDAO {
#Autowired
private SessionFactory factory;
private Session getSession() {
Session session = factory.getCurrentSession();
if(session == null) {
session = factory.openSession();
}
return session;
}
public void saveStudent(Student student) {
getSession().save(student);
}
}
Entity Layer
package com.akshay.entity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name = "student")
public class Student {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "id")
private int id;
#Column(name = "first_name")
private String firstName;
#Column(name = "last_name")
private String lastName;
#Column(name = "email")
private String email;
public Student() {
}
public Student(String firstName, String lastName, String email) {
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
#Override
public String toString() {
return "Student [id=" + id + ", firstName=" + firstName + ", lastName=" + lastName + ", email=" + email + "]";
}
}
Entry Point
package com.akshay.TestHibernate;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class TestHibernateApplication {
public static void main(String[] args) {
SpringApplication.run(TestHibernateApplication.class, args);
}
}
POM file
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.0</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.akshay</groupId>
<artifactId>TestHibernate</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>TestHibernate</name>
<description>Demo project to test hibernate and mysql</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<!--<scope>provided</scope> -->
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
application.properties
#
# JDBC connection properties
#
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/web_student_tracker
jdbc.user=springstudent
jdbc.password=springstudent
#
# Connection pool properties
#
connection.pool.initialPoolSize=5
connection.pool.minPoolSize=5
connection.pool.maxPoolSize=20
connection.pool.maxIdleTime=3000
#
# Hibernate properties
#
hibernate.dialect=org.hibernate.dialect.MySQLDialect
hibernate.show_sql=true
hibernate.packagesToScan=com.akshay.entity
Introduction
Let's consider the following versions as the current versions:
Spring Boot: 2.7.1.
Analysis
Please, note that the package of the controller class (com.akshay.controller.StudentController) is not the same as the package of the application class (com.akshay.TestHibernate.TestHibernateApplication).
Let's refer to the documentation: Developing with Spring Boot: 6. Using the #SpringBootApplication Annotation:
Many Spring Boot developers like their apps to use auto-configuration, component scan and be able to define extra configuration on their "application class". A single #SpringBootApplication annotation can be used to enable those three features, that is:
#EnableAutoConfiguration: enable Spring Boot’s auto-configuration mechanism
#ComponentScan: enable #Component scan on the package where the application is located (see the best practices)
#SpringBootConfiguration: enable registration of extra beans in the context or the import of additional configuration classes. An alternative to Spring’s standard #Configuration that aids configuration detection in your integration tests.
Please, note:
#ComponentScan: enable #Component scan on the package where the application is located (see the best practices)
Solution
It is necessary to add the controller package to be component-scanned.
For example:
<…>
#SpringBootApplication
#ComponentScan(basePackages="com.akshay.controller")
public class TestHibernateApplication {
<…>
Test the controller method execution by performing an HTTP request:
curl -X GET http://localhost:8080/rest/test
Additional references
Stack Overflow question. java - Spring Boot: Cannot access REST Controller on localhost (404) - Stack Overflow.

Field bookRepository in com.code.service.BookServiceImpl required a bean of type 'com.myAppp.code.respository.BookRepository' that could not be found

I am receiving an error when I try to build/run a SpringBoot application as follows:
Field bookRepository in com.myApp.code.service.BookServiceImpl required a bean of type 'com.myApp.code.respository.BookRepository' that could not be found.
The repository in question is:
package com.myApp.code.respository;
import com.myApp.code.model.Book;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
#Repository
public interface BookRepository extends CrudRepository<Book, Long> {
}
And in the service class I have the following:
package com.myApp.code.service;
import com.myApp.code.model.Book;
import com.myApp.code.respository.BookRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
#Service
public class BookServiceImpl implements BookService {
#Autowired
private BookRepository bookRepository;
#Override
public void list() {
//return bookRepository.findAll();
for (Book book : bookRepository.findAll()) {
System.out.println(book.getTitle());
}
}
In the controller concerned I have:
#Controller
#RequestMapping(value="book")
public class BookController {
#Autowired
private BookService bookService;
#Autowired
private PersonService personService;
#Autowired
private BookValidator bookValidator;
private final Logger LOG = LoggerFactory.getLogger(getClass().getName());
public BookController() {
}
// Displays the catalogue.
#RequestMapping(value="/catalogue", method=RequestMethod.GET)
public String index(Model model) {
LOG.info(BookController.class.getName() + ".catalogue() method called.");
// Populate catalogue.
bookService.list();
// model.addAttribute("books", books);
// Set view.
return "/catalogue";
}
And in the Application.java file I have:
#SpringBootApplication
#EnableJpaRepositories
#ComponentScan(basePackages="com.myApp.code")
public class Application {
private final Logger LOG = LoggerFactory.getLogger(getClass().getName());
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
The Book class is:
#Entity
#Table(name="BOOK")
public class Book implements Serializable {
// Fields.
#Id
#Column(name="id", unique=true, nullable=false)
#GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
#Column(name="AUTHOR", nullable=false, length=50)
private String author;
#Column(name="TITLE", nullable=false, length=100)
private String title;
#Column(name="DESCRIPTION", nullable=false, length=500)
private String description;
#Column(name="ONLOAN", nullable=false, length=5)
private String onLoan;
#ManyToOne(fetch=FetchType.EAGER, targetEntity = Person.class)
#JoinColumn(name="Person_Id", nullable=true)
private Person person;
My Maven POM file is:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derbyclient</artifactId>
<version>10.14.2.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
Can anyone tell me why I get this message? Class BookRepository exists after all.
Spring boot will only look for repositories, entities and components within the same package or a subpackage of the main class (Application). You already added the #ComponentScan to point to the other package, but you should also add the package to both #EntityScan and #EnableJpaRepositories, for example:
#SpringBootApplication
#EnableJpaRepositories("com.myApp.code") // Add this
#EntityScan("com.myApp.code") // Add this
#ComponentScan(basePackages="com.myApp.code")
public class Application {
// ...
}
This is also being mentioned in JpaRepository not implemented/injected when in separate package from componentscan.
Alternatively, as mentioned in the comments, you can put the main class in com.myApp.code itself.
Place your Application class in the com.myApp.code package and not a sub package. – M. Deinum
By doing that, you can remove all three annotations:
#SpringBootApplication // Other annotations can be removed
public class Application {
// ...
}

Spring Data 3.0.5 MongoDB and ElasticSearch Domain Class mixed Annotation

I'm migrating our application from Spring Boot 1.5.9 to version 2.0.0.
In version 1.5.9 we have successfully used mixed Annotations on several Domain Classes e.g:
...
#org.springframework.data.mongodb.core.mapping.Document(collection = "folder")
#org.springframework.data.elasticsearch.annotations.Document(indexName = "folder")
public class Folder {
...
}
The same approach causes probems in Spring Boot 2.0.0. When MongoDB annotatnion #DBRef is used, Spring throws exception while ElasticsearchRepository creation:
java.lang.IllegalStateException: No association found!
Here comes classes and confs
pom.xml
...
<properties>
<java.version>1.8</java.version>
</properties>
<parent>
<groupId>org.springfrsamework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0.RELEASE</version>
</parent>
...
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.18</version>
<scope>provided</scope>
</dependency>
</dependencies>
...
Application.java
...
#EnableMongoRepositories("com.hydra.sbmr.repoMongo")
#EnableElasticsearchRepositories("com.hydra.sbmr.repoElastic")
#SpringBootApplication
public class Application extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Folder.java (Note this #DBRef couses exception)
package com.hydra.sbmr.model;
import lombok.Getter;
import lombok.Setter;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.DBRef;
#org.springframework.data.mongodb.core.mapping.Document(collection = "folder")
#org.springframework.data.elasticsearch.annotations.Document(indexName = "folder")
public class Folder {
#Id
#Getter #Setter private String id;
// Why MongoDB core mapping #DBRef causes java.lang.IllegalStateException: No association found! exception
// while ElasticsearchRepository creation???
#DBRef
#Getter #Setter private Profile profile;
#Getter #Setter private String something;
}
Profile.java
package com.hydra.sbmr.model;
import lombok.Getter;
import lombok.Setter;
import org.springframework.data.annotation.Id;
#org.springframework.data.mongodb.core.mapping.Document(collection = "profile")
public class Profile {
#Id
#Getter #Setter private String id;
#Getter #Setter String blah;
}
FolderElasticRepository.java
package com.hydra.sbmr.repoElastic;
import com.hydra.sbmr.model.Folder;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
public interface FolderElasticRepository extends ElasticsearchRepository<Folder, String> {
}
You can find whole mini project on GitHub: https://github.com/hydraesb/sbmr
My question:
Is there any solution that will work with mixed Annotatnions on Domain Classes (mongo and elastic) in Spring Boot 2.0.0???
I have the same issue and the solution that i found is to extends SimpleElasticsearchMappingContext like this :
package com.mypackage;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.elasticsearch.client.Client;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.EntityMapper;
import org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverter;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import java.io.IOException;
#Configuration
public class ElasticsearchConfiguration {
#Bean
public ElasticsearchTemplate elasticsearchTemplate(Client client, Jackson2ObjectMapperBuilder jackson2ObjectMapperBuilder) {
return new ElasticsearchTemplate(client, new MappingElasticsearchConverter(new CustomElasticsearchMappingContext()),
new CustomEntityMapper(jackson2ObjectMapperBuilder.createXmlMapper(false).build()));
}
public class CustomEntityMapper implements EntityMapper {
private ObjectMapper objectMapper;
public CustomEntityMapper(ObjectMapper objectMapper) {
this.objectMapper = objectMapper;
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
objectMapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
}
#Override
public String mapToString(Object object) throws IOException {
return objectMapper.writeValueAsString(object);
}
#Override
public T mapToObject(String source, Class clazz) throws IOException {
return objectMapper.readValue(source, clazz);
}
}
}
package com.mypackage;
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty;
import org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchMappingContext;
import org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchPersistentEntity;
import org.springframework.data.mapping.model.Property;
import org.springframework.data.mapping.model.SimpleTypeHolder;
public class CustomElasticsearchMappingContext extends SimpleElasticsearchMappingContext {
#Override
protected ElasticsearchPersistentProperty createPersistentProperty(Property property, SimpleElasticsearchPersistentEntity owner, SimpleTypeHolder simpleTypeHolder) {
return new CustomElasticsearchPersistentProperty(property, owner, simpleTypeHolder);
}
}
package com.mypackage;
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty;
import org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchPersistentProperty;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.model.Property;
import org.springframework.data.mapping.model.SimpleTypeHolder;
public class CustomElasticsearchPersistentProperty extends SimpleElasticsearchPersistentProperty {
public CustomElasticsearchPersistentProperty(Property property, PersistentEntity owner, SimpleTypeHolder simpleTypeHolder) {
super(property, owner, simpleTypeHolder);
}
#Override
public boolean isAssociation() {
return false;
}
}
I have faced this problem also and I fixed with solution of #ybouraze
#Bean
fun elasticsearchTemplate(client: JestClient, converter: ElasticsearchConverter, builder: Jackson2ObjectMapperBuilder): ElasticsearchOperations {
val entityMapper = CustomEntityMapper(builder.createXmlMapper(false).build())
val mapper = DefaultJestResultsMapper(converter.mappingContext, entityMapper)
return JestElasticsearchTemplate(client, converter, mapper)
}
#Bean
#Primary
fun mappingContext(): SimpleElasticsearchMappingContext {
return MappingContext()
}
#Bean
fun elasticsearchConverter(): ElasticsearchConverter {
return MappingElasticsearchConverter(mappingContext())
}
inner class CustomEntityMapper(private val objectMapper: ObjectMapper) : EntityMapper {
init {
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
objectMapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true)
}
#Throws(IOException::class)
override fun mapToString(`object`: Any): String {
return objectMapper.writeValueAsString(`object`)
}
#Throws(IOException::class)
override fun <T> mapToObject(source: String, clazz: Class<T>): T {
return objectMapper.readValue(source, clazz)
}
}
inner class MappingContext : SimpleElasticsearchMappingContext() {
override fun createPersistentProperty(property: Property, owner: SimpleElasticsearchPersistentEntity<*>, simpleTypeHolder: SimpleTypeHolder): ElasticsearchPersistentProperty {
return PersistentProperty(property, owner, simpleTypeHolder)
}
}
inner class PersistentProperty(property: Property, owner: SimpleElasticsearchPersistentEntity<*>, simpleTypeHolder: SimpleTypeHolder) : SimpleElasticsearchPersistentProperty(property, owner, simpleTypeHolder) {
override fun isAssociation(): Boolean {
return false
}
}

How to autowire spring-data CrudRepository

A bit of Details
I am having some problem while running the code given below. I am getting the following exception. When i am trying the sample code of [CrudRepository for Spring Data][1].
I have an Interface:
package com.joydeep.springboot;
import org.springframework.data.repository.CrudRepository;
import com.joydeep.springboot.vo.Message;
public interface Test1 extends CrudRepository<Message, String> { }
VO Class:
package com.joydeep.springboot.vo;
import java.util.Date;
import javax.persistence.Entity;
import javax.persistence.Id;
#Entity
public class Message {
#Id
private String id;
private String text;
private String author;
private Date created;
public Message() {
super();
}
public Message(String id, String text, String author, Date created) {
super();
this.id = id;
this.text = text;
this.author = author;
this.created = created;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public Date getCreated() {
return created;
}
public void setCreated(Date created) {
this.created = created;
}
}
Controller class:
package com.joydeep.springboot;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
#RestController
public class HelloCntrl {
#Autowired
Test1 test;
#RequestMapping("/hello")
public String sayHi(){
return "Hi";
}
}
Initializer class:
package com.joydeep.springboot;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class CourseAPIStarter {
public static void main(String[] args) {
SpringApplication.run(CourseAPIStarter.class);
}
}
pom.xml:
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>io.springboot</groupId>
<artifactId>rest-course-api</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>Rest service course API</name>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.2.RELEASE</version>
</parent>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derby</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
</project>
Exception encountered during context initialization - cancelling refresh attempt:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'helloCntrl': Unsatisfied dependency expressed through field 'test'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.joydeep.springboot.Test1' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations {#org.springframework.beans.factory.annotation.Autowired(required=true)}
The example i am referring is from this link.
https://spring.io/guides/gs/accessing-data-jpa/
You don't need to put #Repository annotation on Test1. Put these 3 annotation on your CourseAPIStarter class your application will run like hot knife in butter.
#ComponentScan(basePackages={"com.joydeep.springboot"})
#EntityScan(basePackages={"com.joydeep.springboot.vo"})
#EnableJpaRepositories(basePackages={"com.joydeep.springboot"})
#ComponentScan will scan your objects, and will register them with Spring.
#EnableJpaRepositories will enable all your Spring JPA repositories to be used in your application.
#EntityScan: As you added #Entity annotation on your model object class, Spring will assume that a table will exists with name Message. So to register this class with Spring as Entity you need to use this annotation.
Spring can't find Test1 bean because you forgot to annotate it with #Repository. You can autowire only Spring managed classes (Controller, Component, Repository, Service ecc).
Try with this:
#Repository
public interface Test1 extends CrudRepository<Message, String> { }

Spring Boot JPA repository error

i am try using spring boot with hibernate-mysql for learning
i follow the spring boot youtube tutorial and make some change for jpa hibernate-mysql
When run as "spring boot app", it was working fine.
When run as "maven package" on pom.xml, it was failed on "TESTS"
error:
2015-09-18 10:26:19.599 INFO 8328 --- [ main] demo.DemoApplicationTests : Starting DemoApplicationTests on Noir with PID 8328 (D:\eclipse\project\demo\target\test-classes started by Phane in D:\eclipse\project\demo)
2015-09-18 10:26:19.667 INFO 8328 --- [ main] o.s.w.c.s.GenericWebApplicationContext : Refreshing org.springframework.web.context.support.GenericWebApplicationContext#1d0737c8: startup date [Fri Sep 18 10:26:19 SGT 2015]; root of context hierarchy
2015-09-18 10:26:19.768 WARN 8328 --- [ main] o.s.w.c.s.GenericWebApplicationContext : Exception encountered during context initialization - cancelling refresh attempt
org.springframework.beans.factory.BeanDefinitionStoreException: Failed to read candidate component class: file [D:\eclipse\project\demo\target\classes\filmRental\JpaConfig.class]; nested exception is java.lang.annotation.AnnotationFormatError: Invalid default: public abstract java.lang.Class org.springframework.data.jpa.repository.config.EnableJpaRepositories.repositoryBaseClass()
at org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider.findCandidateComponents(ClassPathScanningCandidateComponentProvider.java:303)
at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.doScan(ClassPathBeanDefinitionScanner.java:248)
at org.springframework.context.annotation.ComponentScanAnnotationParser.parse(ComponentScanAnnotationParser.java:140)
at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:266)
at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:230)
at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:189)
at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:270)
at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:230)
at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:197)
at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:166)
at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:306)
at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:239)
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:254)
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:94)
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:606)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:462)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:686)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:320)
this is the java classes:
DemoApplication.java
package demo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Component;
import filmRental.Staff;
import filmRental.StaffRepository;
import filmRental.StaffServiceImpl;
#SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
#ComponentScan ("filmRental")
#Component
class StaffCommandLineRunner implements CommandLineRunner
{
#Override
public void run(String... arg0) throws Exception
{
for(Staff staff : this.sf.findAll())
{
System.out.println(staff.getStaffID() + " > " + staff.getFirstName());
}
}
#Autowired StaffServiceImpl sf;
}
StaffRestController
package demo;
import java.util.Collection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import filmRental.Staff;
import filmRental.StaffServiceImpl;
#RestController
#ComponentScan ("filmRental")
public class StaffRestController
{
#RequestMapping ("/staff")
public Collection<Staff> listStaff()
{
return sf.findAll();
}
#Autowired StaffServiceImpl sf;
}
StaffServiceImpl.java
package filmRental;
import java.util.List;
import javax.annotation.Resource;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
#Service
#Transactional
public class StaffServiceImpl
{
// #PersistenceContext
// private EntityManager em;
#Resource
private StaffRepository sf;
public List<Staff> findAll()
{
return sf.findAll();
}
}
StaffRepository.java
package filmRental;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.transaction.annotation.Transactional;
#Transactional
public interface StaffRepository extends JpaRepository<Staff, Byte>{}
Staff.java
package filmRental;
import java.sql.Blob;
import java.sql.Timestamp;
import javax.persistence.*;
#Entity
#Table (name ="Staff")
public class Staff
{
private byte staffID;
private String firstName;
private String lastName;
private byte[] picture;
private String email;
private byte storeID;
private boolean active;
private String userName;
private String password;
private Timestamp lastUpdate;
private Address address;
#Id
#Column (name="staff_id")
public byte getStaffID()
{
return staffID;
}
public void setStaffID(byte staffID)
{
this.staffID = staffID;
}
#Column (name = "first_name")
public String getFirstName()
{
return firstName;
}
public void setFirstName(String firstName)
{
this.firstName = firstName;
}
#Column (name = "last_name")
public String getLastName()
{
return lastName;
}
public void setLastName(String lastName)
{
this.lastName = lastName;
}
#Column (name = "picture", columnDefinition="BLOB")
public byte[] getPicture()
{
return picture;
}
public void setPicture(byte[] picture)
{
this.picture = picture;
}
#Column (name = "email")
public String getEmail()
{
return email;
}
public void setEmail(String email)
{
this.email = email;
}
#Column (name = "store_id")
public byte getStoreID()
{
return storeID;
}
public void setStoreID(byte storeID)
{
this.storeID = storeID;
}
#Column (name = "active")
public boolean getActive()
{
return active;
}
public void setActive(boolean active)
{
this.active = active;
}
#Column (name = "username")
public String getUserName()
{
return userName;
}
public void setUserName(String userName)
{
this.userName = userName;
}
#Column (name = "password")
public String getPassword()
{
return password;
}
public void setPassword(String password)
{
this.password = password;
}
#Column (name = "last_update")
public Timestamp getLastUpdate()
{
return lastUpdate;
}
public void setLastUpdate(Timestamp lastUpdate)
{
this.lastUpdate = lastUpdate;
}
#ManyToOne
#JoinColumn(name="address_id")
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
}
JpaConfig.java
package filmRental;
import java.util.Properties;
import javax.annotation.Resource;
import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
import org.hibernate.ejb.HibernatePersistence;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.annotation.EnableTransactionManagement;
#Configuration
#EnableTransactionManagement
#PropertySource("classpath:application.properties")
#EnableJpaRepositories
public class JpaConfig
{
private static final String PROPERTY_NAME_DATABASE_DRIVER = "db.driver";
private static final String PROPERTY_NAME_DATABASE_PASSWORD = "db.password";
private static final String PROPERTY_NAME_DATABASE_URL = "db.url";
private static final String PROPERTY_NAME_DATABASE_USERNAME = "db.username";
private static final String PROPERTY_NAME_HIBERNATE_DIALECT = "hibernate.dialect";
private static final String PROPERTY_NAME_HIBERNATE_SHOW_SQL = "hibernate.show_sql";
private static final String PROPERTY_NAME_ENTITYMANAGER_PACKAGES_TO_SCAN = "entitymanager.packages.to.scan";
#Resource
private Environment env;
#Bean
public DataSource dataSource()
{
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(env.getRequiredProperty(PROPERTY_NAME_DATABASE_DRIVER));
dataSource.setUrl(env.getRequiredProperty(PROPERTY_NAME_DATABASE_URL));
dataSource.setUsername(env.getRequiredProperty(PROPERTY_NAME_DATABASE_USERNAME));
dataSource.setPassword(env.getRequiredProperty(PROPERTY_NAME_DATABASE_PASSWORD));
return dataSource;
}
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory()
{
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
entityManagerFactoryBean.setDataSource(dataSource());
entityManagerFactoryBean.setPersistenceProviderClass(HibernatePersistence.class);
entityManagerFactoryBean.setPackagesToScan(env.getRequiredProperty(PROPERTY_NAME_ENTITYMANAGER_PACKAGES_TO_SCAN));
entityManagerFactoryBean.setJpaProperties(hibProperties());
return entityManagerFactoryBean;
}
private Properties hibProperties()
{
Properties properties = new Properties();
properties.put(PROPERTY_NAME_HIBERNATE_DIALECT, env.getRequiredProperty(PROPERTY_NAME_HIBERNATE_DIALECT));
properties.put(PROPERTY_NAME_HIBERNATE_SHOW_SQL, env.getRequiredProperty(PROPERTY_NAME_HIBERNATE_SHOW_SQL));
return properties;
}
#Bean
public JpaTransactionManager transactionManager()
{
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
return transactionManager;
}
}
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>`enter code here`
<groupId>org.test</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.2.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.7</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-ws</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>persistence-api</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.0.1.Final</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>1.9.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Please help, thanks.
You are using Spring Boot then use Spring Boot also the #ComponentScan should go on your application class. (remove it from your command line runner and controller).
#SpringBootApplication
#ComponentScan ({"demo","filmRental"})
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
#Component
class StaffCommandLineRunner implements CommandLineRunner {
#Autowired StaffServiceImpl sf;
#Override
public void run(String... arg0) throws Exception {
for(Staff staff : this.sf.findAll()) {
System.out.println(staff.getStaffID() + " > " + staff.getFirstName());
}
}
}
Next in your pom remove the spring-data-jpa, hibernate and persistence-api dependencies and replace with spring-boot-starter-data-jpa
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-ws</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
</dependencies>
Now you have dependencies that work together instead of trying to figure out a working combination.
Spring Boot already does auto configuration for you remove your JpaConfig and put the following properties in your application.properties (automatically loaded by Spring Boot!).
spring.datasource.url=<datasource-url>
spring.datasource.driver-class-name=<driver-class-name>
spring.datasource.username=<username>
spring.datasource.password=<password>
spring.jpa.database-platform=<hibernate-dialect>
spring.jpa.show-sql=<show-sql>
For the entity scan use #EntityScan on the application class.
#SpringBootApplication
#ComponentScan ({"demo","filmRental"})
#EntityScan("filmRental")
public class DemoApplication { ... }
Spring Boot now auto configures the DataSource, EntityManagerFactory, transactions, detects Spring Data JPA and enables repositories. I would suggest moving the DemoApplication and everything else in the filmRental package that way you can remove the #ComponentScan and #EntityScan from the DemoApplication.

Resources