iank
iank

Reputation: 113

Why IllegalStateException: Failed to load ApplicationContext?

I'm refactoring some controller tests implementing dto instead of the db entity and now ran into this problem. I don't know how but it throws an exception when trying to instantiate the orikaMapperFacade Bean.

java.lang.IllegalStateException: Failed to load ApplicationContext

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean 
with name 'orikaMapperFacade' defined in class path resource 
[net/rakugakibox/spring/boot/orika/OrikaAutoConfiguration.class]: Bean instantiation via 
factory method failed; nested exception is 
org.springframework.beans.BeanInstantiationException: Failed to instantiate 
[ma.glasnost.orika.MapperFacade]: Factory method 'orikaMapperFacade' threw exception; 
nested exception is java.lang.reflect.InaccessibleObjectException: Unable to make 
protected native java.lang.Object java.lang.Object.clone() throws 
java.lang.CloneNotSupportedException accessible: module java.base does not "opens 
java.lang" to unnamed module @67b64c45

So this is the controller tests class:

@RunWith(SpringRunner.class)
@SpringBootTest(classes = BooksApplication.class)
@AutoConfigureMockMvc
class BookControllerTests {
@Autowired
MockMvc mockMvc;

@Autowired
ObjectMapper mapper;
@MockBean
BookController bookController;

@Autowired
private BookConverter converter;

@Test
public void createBook_success() throws Exception {
    Book book = Book.builder().name("Great book").build();
    BookDto dto = converter.toDto(book);

    given(bookController.createBook(dto)).willReturn(dto);

    mockMvc.perform(post("/api/books/")
                    .contentType(MediaType.APPLICATION_JSON).content(asJsonString(book)))
            .andExpect(status().isCreated());
}

@Test
public void getAllBooks_success() throws Exception {

    Book book1 = Book.builder().name("New book").author("Ivan").build();
    Book book2 = Book.builder().name("This book").author("Whatever").build();

    List<Book> bookList = new ArrayList<>(Arrays.asList(book1, book2));

    //bookRepository.save(book);

    Mockito.when(bookController.getAllBooks()).thenReturn(bookList);

    mockMvc.perform(MockMvcRequestBuilders.get("/api/books/")
                    .contentType(MediaType.APPLICATION_JSON))
            .andExpect(status().isOk())
            .andExpect(jsonPath("$", hasSize(2)))
            .andExpect(jsonPath("$[0].name", is("New book")));
}

@Test
public void findByTitle_success() throws Exception {
    Book book = Book.builder().name("New book").author("Ivan").build();

    Mockito.when(bookController.findByTitle(book.getName())).thenReturn(book);

    LinkedMultiValueMap<String, String> requestParams = new LinkedMultiValueMap<>();
    requestParams.add("name", "New book");

    mockMvc.perform(MockMvcRequestBuilders.get("/api/books/").params(requestParams)
                    .contentType(MediaType.APPLICATION_JSON))
            .andExpect(status().isOk());
}
private String asJsonString(final Object obj){
    try{
        return new ObjectMapper().writeValueAsString(obj);
    } catch (Exception e){
        throw new RuntimeException(e);
    }
}
}

This is the POJO:

@Entity
@JsonIgnoreProperties("deleted")
@Table(name="books", uniqueConstraints = {@UniqueConstraint(columnNames = "name")})
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class Book {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="id")
private Integer id;

@Column(name="name")
private String name;

@Column(name="author")
private String author;

@Column(name="publication_year")
@JsonFormat (shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
private LocalDate publicationYear;

@Column(name="pages_number")
private int pagesNumber;

@Column(name="publisher")
private String publisher;

@Column(name="is_deleted")
private Boolean isDeleted;

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

public Integer getId() {return id;}

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

public String getName() {return name;}

public void setAuthor(String author) {this.author = author;}

public String getAuthor() {return author;}

public void setPublicationYear(LocalDate publicationYear) {this.publicationYear = 
publicationYear;}

public LocalDate getPublicationYear() {return publicationYear;}

public void setPagesNumber(int pagesNumber) {this.pagesNumber = pagesNumber;}

public int getPagesNumber() {return pagesNumber;}

public void setPublisher(String publisher) {this.publisher = publisher;}

public String getPublisher() {return publisher;}

public void setDeleted(Boolean deleted) {isDeleted = deleted;}

public Boolean getDeleted() {return isDeleted;}

}

This is the DTO:

public class BookDto {

@NotNull(message = "Name of the book cannot be empty!")
@Size(min = 4, max = 30, message = "Name of the book must be between 4 and 30 characters 
long!")
public String name;

@NotNull(message = "Author of the book cannot be empty!")
@Size(min = 5, max = 35, message = "Author of the book must be between 5 and 35 
characters long!")
public String author;

@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
public String publicationYear;

@NotNull(message = "Pages of the book cannot be null!")
@Digits(integer = 4, fraction = 0)
public int pagesNum;

@NotNull(message = "Publisher of the book cannot be empty!")
@Size(min = 4, max = 30, message = "Publisher of the book must be between 4 and 30 
characters long!")
public String publisher;

}

This is mapping configuration:

@Component
public class BookConverter {

private final MapperFacade mapperFacade;

public BookConverter(MapperFacade mapperFacade) {
    this.mapperFacade = mapperFacade;
}

public MapperFacade getMapperFacade(){
    return mapperFacade;
}

public BookDto toDto(Book entity){
    return mapperFacade.map(entity, BookDto.class);
}

public Book fromDto(BookDto dto){
    return mapperFacade.map(dto, Book.class);
}

}

public class BookMapper extends CustomMapper<Book, BookDto> {

@Override
public void mapBtoA(BookDto bookDto, Book book, MappingContext 
context) {
    super.mapBtoA(bookDto, book, context);
}
}

public class MappingConfig implements OrikaMapperFactoryConfigurer{
@Override
public void configure(MapperFactory orikaMapperFactory) {

    orikaMapperFactory.classMap(Book.class, BookDto.class)
            .customize(new BookMapper())
            .byDefault()
            .register();

    orikaMapperFactory.classMap(Book.class, BookDto.class)
            .byDefault()
            .register();
}
}

This is 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 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.7.0</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.krylosov_books</groupId>
    <artifactId>books</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>books</name>
    <description>books</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-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.24</version>
            <scope>provided</scope>
        </dependency>
        <!-- Junit 5 -->
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-api</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-engine</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.platform</groupId>
            <artifactId>junit-platform-launcher</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- Mockito extension -->
        <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-junit-jupiter</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.junit.vintage</groupId>
            <artifactId>junit-vintage-engine</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.hamcrest</groupId>
                    <artifactId>hamcrest-core</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
            <version>2.7.0</version>
        </dependency>
        <dependency>
            <groupId>ma.glasnost.orika</groupId>
            <artifactId>orika-core</artifactId>
            <version>1.5.4</version>
        </dependency>
        <dependency>
            <groupId>net.rakugakibox.spring.boot</groupId>
            <artifactId>orika-spring-boot-starter</artifactId>
            <version>1.9.0</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>${project.parent.version}</version>
            </plugin>
        </plugins>
    </build>

</project>

Any help please?

Upvotes: 0

Views: 474

Answers (0)

Related Questions