Spring can't map MultiValueMap to bean - java

Posting x-www-form-urlencode data to Spring.
This works:
#RequestMapping(method = RequestMethod.POST, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
public void sumbitFUD(#RequestBody final MultiValueMap<String, String> formVars) {
}
This on the other hand, gives an exception:
Content type 'application/x-www-form-urlencoded;charset=UTF-8' not
supported
#RequestMapping(method = RequestMethod.POST, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
public void sumbitFUD(#RequestBody Fud fud) {
}
And this results in all fields on the bean being null:
#RequestMapping(method = RequestMethod.POST, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
public void sumbitFUD(Fud fud) {
//not using #RequestBody
}
FUD:
public class Fud {
public String token_id;
public String team_doamin;
public String channel_id;
public String user_id;
public String user_name;
public String command;
public String text;
public String response;
}
Form data:
token%abc=&team_id%3DT0001=&team_domain%3Dexample=&channel_id%3DC2147483705=&channel_name%3Dtest=&user_id%3DU2147483697=&user_name%3DSteve=&command%3D%2Fweather=&text%3D94070=&response_url%3Dhttps=%2F%2Fhooks.slack.com%2Fcommands%2F1234%2F5678
POM:
<dependencies>
<dependency>
<groupId>net.gpedro.integrations.slack</groupId>
<artifactId>slack-webhook</artifactId>
<version>1.3.0</version>
</dependency>
<!-- Spring Frameworks for Web, MVC and Mongo -->
<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.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<scope>test</scope>
</dependency>
<!-- JUnit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>

I see two problems here.
The use of the #RequestBody annotation. It, or more precisely its handler - a subclass of the HttpMessageConverter, can't handle these cases. You should deal with the #ModelAttribute instead.
The absence of setters. Spring can't set values, that come in, to a target instance without setters. I do not know whether there is a property to operate directly with fields, but I would recommend avoiding that. Make the fields private.

Related

SpringBoot + WebFlux + GraphQL - Expected source object to be an instance of 'com.example.MyObject' but instead got 'reactor.core.publisher.FluxJust'

I am trying to implement a reactive architecture to my Spring+MongoDB+GraphQL app, have followed some tutorials on that, but whenever I return a Publisher<Page> from my GraphQLQueryResolver - I get this error:
2022-11-17 09:18:56.316 ERROR 14166 --- [nio-8081-exec-1]
g.servlet.DefaultGraphQLErrorHandler : Error executing query
(ExceptionWhileDataFetching): Exception while fetching data (/getPages/id) : Expected
source object to be an instance of 'com.example.jobscraperspringserver.types.Page' but
instead got 'reactor.core.publisher.FluxJust'
I've played with the returned object (tried Flux<Page>, Publisher<List<Page>> and other configurations) as well as a type in the schema.graphqls, but none of them work. Besides, that's what supposed to be working in the majority of tutorials as well as some other SO issues, so I suppose that's either a bug somewhere in my code or an architectural flaw (i.e. some faulty dependency that doesn't support the type convertion).
Here is my code:
PageQuery.java
#Component
public class PageQuery implements GraphQLQueryResolver {
#Autowired
PageService pageService;
public Publisher<Page> getPages() {
return pageService.getPages();
}
}
PageService.java
#Service
public class PageService {
public Flux<Page> getPages() {
return Flux.just(new Page(12));
}
}
schema.graphqls
type Page {
id: Int!
host: String
}
type Query {
getPages: Page
}
pom.xml
...
<dependencies>
<!-- Spring -->
<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>
<!-- GraphQL -->
<dependency>
<groupId>com.graphql-java</groupId>
<artifactId>graphql-spring-boot-starter</artifactId>
<version>5.0.2</version>
</dependency>
<dependency>
<groupId>com.graphql-java</groupId>
<artifactId>graphql-java-tools</artifactId>
<version>5.2.4</version>
</dependency>
<!-- GraphQL subscriptions -->
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-core</artifactId>
</dependency>
<!-- MongoDB -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
<version>2.6.3</version>
</dependency>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver-reactivestreams</artifactId>
</dependency>
<!-- h2 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<!-- JWT -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
<!-- Spring Security -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
<version>2.0.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
</dependency>
<!-- WebFlux -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
<version>2.6.4</version>
</dependency>
</dependencies>
...
UPDATE
Apparently com.graphql-java doesn't handle WebFlux, so I've replaced
<dependency>
<groupId>com.graphql-java</groupId>
<artifactId>graphql-spring-boot-starter</artifactId>
<version>5.0.2</version>
</dependency>
with
<dependency>
<groupId>org.springframework.experimental</groupId>
<artifactId>graphql-spring-boot-starter</artifactId>
<version>1.0.0-M3</version>
</dependency>
but now I am getting a null instead of a Page...
UPDATE 2
I've also tried the
<dependency>
<groupId>com.graphql-java-kickstart</groupId>
<artifactId>graphql-spring-boot-starter</artifactId>
<version>11.1.0</version>
</dependency>
<dependency>
<groupId>com.graphql-java-kickstart</groupId>
<artifactId>graphql-kickstart-spring-webflux</artifactId>
<version>11.1.0</version>
</dependency>
but got the same result. I figured it supports a CompletableFuture<List<Page>>, but this is still blocking and I've seen multiple tutorials on returning Mono/Flux from a graphql resolver...
UPDATE 3
I've updated the all the Spring modules' versions to 2.6.3 to be consistent and I've also removed the spring-boot-starter-web dependency, as the spring-boot-starter-webflux should be sufficient; but neither of those fixes have solved my issue.
UPDATE 4
This is the entity I want to return wrapped in a Flux:
#Document("pages")
public class Page {
#Id
private int id;
private String host;
private String path;
private String jobAnchorSelector;
private String jobLinkContains;
private int numberOfPages;
private int interval;
private Date lastScrapePerformed;
private String userUuid;
public Page() {
}
public Page(int id) {
this.id = id;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public String getJobAnchorSelector() {
return jobAnchorSelector;
}
public void setJobAnchorSelector(String jobAnchorSelector) {
this.jobAnchorSelector = jobAnchorSelector;
}
public String getJobLinkContains() {
return jobLinkContains;
}
public void setJobLinkContains(String jobLinkContains) {
this.jobLinkContains = jobLinkContains;
}
public int getNumberOfPages() {
return numberOfPages;
}
public void setNumberOfPages(int numberOfPages) {
this.numberOfPages = numberOfPages;
}
public String toString() {
return "Page [" + host + path + "]";
}
public int getInterval() {
return interval;
}
public void setInterval(int interval) {
this.interval = interval;
}
public Date getLastScrapePerformed() {
return lastScrapePerformed;
}
public void setLastScrapePerformed(Date lastScrapePerformed) {
this.lastScrapePerformed = lastScrapePerformed;
}
public String getUserUuid() {
return userUuid;
}
public void setUserUuid(String userUuid) {
this.userUuid = userUuid;
}
}
It's a MongoDB document and I'm using a ReactiveMongoRepository to fetch that, however for the sake of simplifying this issue I was trying to return just a Flux.just(new Page(2)).
First of all, if you're using Spring Boot, I would recommend that you use spring-boot-starter-graphql instead of graphql-spring-boot-starter, and you need to add spring-boot-starter-webflux to implement reactive data fetchers. Also if you want to return Flux, you should define returned type as an array in the schema (e.g. getPages: [Page!]!), otherwise, you should return Mono.
This will allow you to implement your query like this:
#Controller
public class PageController {
// ...
#QueryMapping
public Flux<Page> getPages() {
return pageService.getPages();
}
}
But you should note that by default Mono and Flux are adapted to a CompletableFuture where Flux values are aggregated and turned into a List. If you want to stream responses, then you should also use GraphQL subscription instead of a query.

Mockito failing to mock Interface class in SpringBoot

I am trying to test one test case using controller class with service interface and interface impl class. But it's always failing and returning either null pointer exception or not found custom exception even mocking the method to return mock values.
Controller.class
#RestController
public class RestAPIController {
#Autowired
RestAPIService restAPIService;
#PostMapping(path = "list/{id}")
public ResponseEntity<List<Employee>> findByID(#PathVariable(value = "id") String id)
throws RestAPIException {
List<Employee> list = restAPIService.findByID(id);
if (list == null || list.isEmpty()) {
throw new IDNotFoundException(id);
}
return new ResponseEntity<>(list, HttpStatus.OK);
}
Service Interface:
#Service
public interface RestAPIService {
public List<Employee> findByID(#Param("id") String id) throws RestAPIException;
}
Service impl class:
#Service
public class RestAPIServiceImpl implements RestAPIService {
#Override
public List<Employee> findByID(String id) throws RestAPIException {
return serviceUtils.transformationObj(repository.findByID(id));
}
}
Test Class
#Mock
RestAPIService restAPIServiceImpl;
#InjectMocks
RestAPIController restAPIController;
#Test
public void testListByIDController() throws RestAPIException {
Mockito.when(restAPIServiceImpl.findByID("1")).thenReturn(baseDTOData());
ResponseEntity<List<Employee>> expectedList = restAPIController.findByID("1");
assertEquals(1, expectedList.getBody().size());
}
private List<Employee> baseDTOData() {
List<Employee> list = new ArrayList<>();
Employee e = new Employee();
e.setId("2");
list.add(e);
return list;
}
pom.xml (using JUnit5)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<!-- exclude junit 4 -->
<exclusions>
<exclusion>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</exclusion>
</exclusions>
</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 extention -->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
The above code is failing and enters into IDNotFoundException but mock return is not working.
Can anyone please help on this.

How to Unit Test Spring Repositories

I have created a springboot project splitted into three maven modules, the domain layer, the core layer (contains persistence and business logic) and the web layer. I try to unit test my repository ProductRepository (located in the core layer)
#RunWith(SpringRunner.class) // provide bridge between SpringBoot test features and JUnit, for usage of springboot tsting features
#DataJpaTest
class ProductRepositoryTest {
#Autowired
private TestEntityManager em;
#Autowired
private ProductRepository repository;
#Test
void shouldReturnProduct() {
// given
Product p = Product.builder().id(1).designation("Test").reference("TEST").unitPrice(150).build();
this.em.persistAndFlush(p);
// when
Product found = repository.findByReference(p.getReference());
// then
assertThat(found.getReference()).isEqualTo(p.getReference());
}
}
But the repository is always instanciated to null. I run this test as JUnit Test in eclipse and i got a nullpointerexception.
Here is my pom.xml file
<dependencies>
<!--<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId>
</dependency> -->
<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-devtools</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
You say you try to unit test the controller but you use #RunWith(SpringRunner.class), this is used for integration tests. This annotation starts the complete application. And you just want to test the repository. What you can do is create an abstract DAO which you can implement in your unit tests.
public abstract class AbstractRepository<RepositoryType> {
RepositoryType repository;
private DBI dbi;
protected abstract RepositoryType createRepository(final DBI dbi);
#Before
public final void setUpDataSource() throws Exception {
final JdbcDataSource jdbcDataSource = new JdbcDataSource();
// DB_CLOSE_DELAY=-1 ==> h2 will keep its content as long as the vm lives otherwise the content of the database
// is lost at the moment the last connection is closed.
jdbcDataSource
.setURL("jdbc:h2:mem:play;MODE=MySQL;DB_CLOSE_DELAY=-1L;INIT=RUNSCRIPT FROM 'classpath:path/to/file/init_test.sql';");
final Flyway flyway = new Flyway();
flyway.setDataSource(jdbcDataSource);
flyway.setLocations("/path/to/locations");
flyway.migrate();
dbi = new DBI(jdbcDataSource);
runDbScript("/data.sql");
repository = createRepository(dbi);
}
private void runDbScript(final String scriptPath) throws Exception {
try (InputStreamReader reader = new InputStreamReader(AbstractDaoTest.class.getResourceAsStream(scriptPath),
Charsets.UTF_8); Handle h = dbi.open()) {
RunScript.execute(h.getConnection(), reader);
}
}
}
Now you can overwrite the createRepository method in your test class.
public class ProductRepositoryTest() {
#Override
protected ProductRepository createRepository(Dbi dbi) { return new ProductRepository(dbi); }
#Test
public void testGetProductById() {
Product response = repository.getProductById(1);
assertThat(response).isEqualTo(someObject);
}
}
If you need a framework to mock objects you can use Mockito and if you need to mock static or void methods you can use PowerMock.
Hope this helps.
Add these annotations to your test classes.
#SpringBootTest
#TestExecutionListeners({ DependencyInjectionTestExecutionListener.class,
DbUnitTestExecutionListener.class,
TransactionalTestExecutionListener.class })
public class YourTestClass {....
here's a working version of your example - hope this helps. I think you may have some conflicting configuration or dependencies in your own project. https://github.com/tndavidson/springbootjparepositorytest

Jersey test gives NullPointerException when using UriInfo

I am creating a application that should be able to create an account using a REST api. When I wrote the AccountController.java class everything worked fine. I used postman to verify that I got the right response.
So my AccountController.java works correctly but the unit test I wrote with it don't work. When the unit test is executed it returns a NullPointerException which results in a InternalServerError within the REST API. While debugging i found out that if I remove the use of UriInfo in AccountController.java and return Response.ok() instead of created the test is successfull.
So my question is. How do i properly test/mock a method that returns and URI?
Bellow are all relevant classes and dependencies. The Account.java class is in another package. But both the main application as the project that contains Account.java are part of the same parent pom. I am not sure if this is relevant to my question.
AccountController.java
#Stateless
#Path("/accounts")
public class AccountController {
#Inject
private AccountService accountService;
#Context
private UriInfo uriInfo;
#POST
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public Response create(Account account) {
final Account newAccount = accountService.create(account);
System.out.println("Pre uriinfo message");
//Removing this line and returning Response.ok() removes the exception
final URI uri = uriInfo.getAbsolutePathBuilder().path(newAccount.getId() + "").build();
System.out.println("Post uriinfo message");
return Response.created(uri).entity(newAccount).build();
}
}
AccountControllerTest.java
#RunWith(MockitoJUnitRunner.class)
public class AccountControllerTest extends JerseyTest {
#Mock
private AccountService service;
#Override
protected Application configure() {
final ResourceConfig config = new ResourceConfig(AccountController.class);
config.register(new AbstractBinder() {
#Override
protected void configure() {
bind(service).to(AccountService.class);
}
});
return config;
}
#Test
public void createUserTest() throws Exception {
final Account testAccount = new Account("testName", "test#mail.nl");
when(service.create(testAccount))
.thenReturn(testAccount);
System.out.println("Create account test");
//Create a new Account
final Response correctResult = target("/accounts")
.request(MediaType.APPLICATION_JSON)
.post(Entity.json(testAccount));
Assert.assertEquals(HTTP_CREATED, correctResult.getStatus());
Assert.assertEquals(testAccount, correctResult.readEntity(Account.class));
}
}
Account.java
#Entity
#XmlRootElement
public class Account {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#Column(nullable = false)
private String fullName;
#Column(unique = true, nullable = false)
private String mail;
private boolean active;
public Account() { }
public Account(String fullName, String mail) {
this.fullName = fullName;
this.mail = mail;
}
//Contains getters&setters
}
Test dependencies
<!-- jersey version for "Jersey Media Json Jackson" & "Jersey Test Framework Provider Jetty" -->
<properties>
<jersey.version>2.26-b03</jersey.version>
</properties>
<!-- https://mvnrepository.com/artifact/junit/junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.mockito/mockito-core -->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>2.9.0</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.glassfish.jersey.test-framework.providers/jersey-test-framework-provider-jetty -->
<dependency>
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
<artifactId>jersey-test-framework-provider-jetty</artifactId>
<version>${jersey.version}</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.glassfish.jersey.media/jersey-media-json-jackson -->
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>${jersey.version}</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.jboss.resteasy/resteasy-jaxrs -->
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxrs</artifactId>
<version>3.1.4.Final</version>
<scope>test</scope>
</dependency>
So I finally figured it out.
Somewhere on this line in AccountController.java a NullPointerException was thrown:
final URI uri = uriInfo.getAbsolutePathBuilder().path(newAccount.getId() + "").build();
This only happened when using my JerseyUnitTest so i guess Jersey must change some behavior of UriInfo.
Eventually I solved the problem by overriding equals in Account.java.

Exception: No property delete found for type void in Spring Data JPA

I'm using Spring Data Jpa and facing an exception when I deployed the project
I have used findAll() method in service and serviceImpl class and I received an exception, this is my source:
Model:
#Entity
#Table(name="CITY")
public class City {
#Id
#Column(name="ID", nullable = false, unique = true)
#GeneratedValue(strategy=GenerationType.AUTO)
private int id;
#Column(name = "NAME")
private String name;
// get, set method
}
Repository class:
public interface CityJpaRepositoryCustom extends JpaRepository<City, Integer> {
}
Service class:
public interface CityService {
public List<City> findAll();
}
ServiceImpl class:
#Service
public class CityServiceImpl implements CityService {
#Resource
private CityJpaRepositoryCustom cityRepository;
#Override
#Transactional
public List<City> findAll() {
// TODO Auto-generated method stub
return cityRepository.findAll();
}
}
Controller class:
#Controller
public class CityController {
#Autowired
private CityService cityService;
#RequestMapping(value="/list", method=RequestMethod.GET)
public ModelAndView getListCity(HttpServletRequest request,
HttpServletResponse response,
ModelMap model) {
ModelAndView mav = new ModelAndView("manageCity");
List<City> cityList = cityService.findAll();
mav.addObject("cityList", cityList);
return mav;
}
Pom.xml:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.0.1.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-jpa</artifactId>
<exclusions>
<exclusion>
<artifactId>hibernate-entitymanager</artifactId>
<groupId>org.hibernate</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- SOLR -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-solr</artifactId>
<version>${spring-data-solr.verion}</version>
</dependency>
<!-- JSON -->
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.11</version>
</dependency>
<!-- WEB -->
<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>
<!-- Hibernate 4 dependencies -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-c3p0</artifactId>
<version>${hibernate.version}</version>
</dependency>
</dependencies>
Log message:
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'cityJpaRepositoryCustom': Invocation of init method failed; nested exception is org.springframework.data.mapping.PropertyReferenceException: No property delete found for type void!
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1553)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:539)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:304)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:300)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195)
I have found some same topic but it's not get good result for me, How to fix this exception? thank you so much!
Upgrade your version of Spring Boot to the latest (1.5.1.RELEASE).
You're using an ancient version which will in turn be pulling in an old version of Spring Data which may have not supported delete.
If you want to use delete operation but don't want to update Spring Data JPA, you have to write your own delete implementation. Example:
public interface CityJpaRepositoryCustom extends JpaRepository<City, Integer> {
#Modifying
#Query("delete from City where name = :name")
void deleteByName(#Param("name") String name);
}
Related docs:
Using #Query annotation
#Modifying annotation
#Param annotation

Categories

Resources