I can do PUT but not POST with Spring Data Rest? - spring

I have two simple entity like this:
public class Agent extends BasedEntity {
private String firstname;
private String lastname;
#ManyToOne
#JoinColumn(name="agency_id", nullable=true)
Agency agency;
}
and
public class Agency extends BasedEntity {
private String name;
private String address;
#OneToMany(mappedBy="agency")
private Set<Agent> agents;
}
#RepositoryRestResource
public interface AgencyRespository extends JpaRepository<Agency, Long> {
}
#RepositoryRestResource
public interface AgentsRespository extends JpaRepository<Agent, Long> {
}
When I do a PUT with
https://localhost:8080/api/v1/agents/64/agency
body:https://localhost:8080/api/v1/agencies/50
it goes through but if I do a POST to
https://localhost:8080/api/v1/agents/64/agency
body:https://localhost:8080/api/v1/agencies/50
I get a
org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'POST' not supported

You are using an old version of Spring Data Rest. POST is allowed from 2.3.x.
The latest version is 3.2.x. You should definetely ugrade to a newer version...
----------- Edit
I've just realized that the exception is NOT the inner HttpRequestMethodNotSupportedException from the RepositoryPropertyReferenceController class, but the 'default' org.springframework.web.HttpRequestMethodNotSupportedException.
This exception is never raised directly from the SRD package.
Maybe you have a filter which deny POST request or some kind of security settings.

Related

#CreatedBy becomes null when updating

I have this entity:
#Entity
#EntityListeners( AuditingEntityListener.class )
public class Employee {
#Id
#GeneratedValue
int id;
private String name;
...
#LastModifiedBy
private String modifiedBy;
#CreatedBy
private String createdBy;
}
And i have this config class:
#Configuration
#EnableJpaAuditing
public class DataConfig {
#Bean
public AuditorAware<String> auditorAware() {
return () ->
SecurityContextHolder.getContext().getAuthentication().getName();
}
}
The problem is:
When updating entity, the created_by becomes null.
Any help please.
I'd suggest to you to ensure if your spring boot app is scanning the DataConfig class.
In addition, well in case of having a REST Service (I don't know because that info is not added to the question) but bear in mind a REST Service is Stateless, and you need fetch the Authorization from the request to add it to the spring security context BEFORE executing the request.
But if your spring boot app is just a Spring MVC one with basic Authorization, be sure you have an open session once the data is updated/created

Mapping API response to another client DTO

[solved]
update: I was using lombok for getter/setters, and forgot to add #Data annotation on that class. Now fixed.
I am calling endpoint of a REST controller from where my Response class has entity like this:
public class Response{
private Long userId;
private Long anotherId;
private Collection<UserInfo> userInfo;
private List<Map<String, List<AnotherDto>>> anotherDto;
//setters and getters
};
Here,
public class UserInfo implements MyInterface{
private Long id;
private String name;
//and #override methods
//setters and getters
}
Now, In my client app,
The DTO I am mapping to the API call response is same like I have described above, except, my UserInfo class does n't implement any interface in client side.
When I make API call, from service side, I have checked that I got all the data as expected, but in client side, I get all except the userInfo for which UserInfo class doesn't implement the interface as I did on service side.
What is the issue here? Any help please.

Auto generate Spring Rest-Controller

currently I have the Task to create a REST api onto an existing service layer in Spring.
This is the Setup:
#Entity
public class Example{
#Id
public Long id;
...
}
public interface ExampleRepository extends CrudRepository<Example, Long> {}
#Service
public class ExampleService{
#Autowired
private ExampleRepository repo;
public List<Example> findAll(){
//do some businesslogic
return repo.findAll();
}
}
#RestController
#RequestMapping("/exampleService/*")
public class ExampleController{
#Autowired
private ExampleService service;
#GetMapping
public List<Example>findAll(){
return service.findAll();
}
}
The controller is only boilerplate to me and I would really like to find a way to generate it automatically because we are talking about a lot of services and even more functions.
I know there is a way to expose the repositories as REST-Endpoints using spring-data-rest but that is not what I want. I want the services to be exposed as REST-Endpoints. Could you please give me a hint on how to do that?
You should write a Generic Rest Controller which then calls your inner services.
You can achieve this by using external resource file for storing the class details and Java Reflection API .

Spring Boot JPA #Transactional #Service does not update, but #Transactional in controller does

I have a very basic Spring Boot/JPA stack app, with a controller, service layer, and repository that does not persist updates as I understand it should.
A trivial Entity:
#Entity
public class Customer {
#Id
#GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
private String name;
protected Customer() {}
public Customer(String name) { this.name = name; }
// standard getters,setters //
}
A trivial Repository:
#Repository
public interface CustomerRepository extends CrudRepository<Customer, Long> {}
A simple Service layer:
// If the service is #Transactional and the controller is not, the update does NOT occur
#Transactional
#Service
public class CustomerService {
private static final Logger LOG = getLogger(CustomerService.class);
#Autowired
private CustomerRepository customerRepository;
boolean updateCustomerName(Long id, String name) {
Customer customer = customerRepository.findOne(id);
if (customer == null) { return false; }
// Modifies the entity
customer.setName(name);
// No explicit save()
return true;
}
}
And a REST controller that uses it all:
// If the controller is #Transactional and the service is not, the update occurs
#RestController
#RequestMapping("/mvc")
public class CustomerController {
#Autowired
private CustomerService customerService;
#RequestMapping(path = "{id}", method = RequestMethod.PUT)
public ResponseEntity updateCustomerName(#PathVariable Long id, #RequestParam("name") String name) {
customerService.updateCustomerName(id,name);
return ResponseEntity.noContent().build();
}
}
These are wired together with a simple one-liner SpringBootApplication
I have SQL debug logs enabled and see the selects, update, etc.
With the code above: When the service method is invoked by the controller, the modified entity is not persisted. SQL logs show the select of the entity but no update.
There is also no update if nothing is marked #Transactional
However, simply by moving the #Transactional annotation from the service class to the controller class, the SQL update does occur.
If I add an explicit customerRepository.save(customer) to the service method, the update also occurs. But my understanding is that the ORM should automatically save modified persistent entities.
I'm sure the issue has something to do with the EntityManager lifecycle in the web request, but I'm puzzled. Do I need to do additional configuration?
Complete example at https://github.com/monztech/SO-41515160
EDIT: This was solved, see below. Per the Spring spec #Transactional does not work in package-private methods and mistakenly did not make the update service method public.
The update will occur if the method is public and the service class has the #Transactional annotation.
I do have another question, however. Why is the #Transactional annotation necessary? (the update does not occur without it) Shouldn't the entity manager still persist the object because of the open session in view mechanism that Spring uses, independent of any transaction?
Make your updateCustomerName method public.

generic service and controller spring

package com.lhoussaine.springjsfjpa.entities;
#Table(name="address")
#Entity
public class Address {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private String streetNumber;
private String streetName;
private String city;
getter/setter
}
and I Have 30 entities.
Now repositories:
package com.lhoussaine.springjsfjpa.repositories;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.rest.repository.annotation.RestResource;
import com.lhoussaine.springjsfjpa.entities.Address;
#RestResource(rel="address", path="address")
public interface AddressRepository extends JpaRepository<Address,Integer> {
}
Here I dont need to implemente CRUD operation! thanks to spring-data-jpa! And I want same standard for controller and services:
public interface IAddressService {
}
package com.lhoussaine.springjsfjpa.services.generic;
import java.util.List;
public abstract class GenericService<T,K> {
public abstract T create(T saved);
public abstract void remove(T deleted);
public abstract T findById(K id) ;
public abstract List<T> findAll();
public abstract T removeById(K id);
}
package com.lhoussaine.springjsfjpa.services.impl;
#Service
#Transactional
public class AddressService extends GenericService<Address, Integer> implements IAddressService {
#Autowired private AddressRepository iaddressRepository;
public Address create(Address saved) {
Address address=saved;
return iaddressRepository.save(address);
}
public void remove(Address deleted) {
iaddressRepository.delete(deleted);
}
public Address findById(Integer id) {
return iaddressRepository.findOne(id);
}
public List<Address> findAll() {
return iaddressRepository.findAll();
}
public Address removeById(Integer id) {
Address addr= iaddressRepository.findOne(id);
if(addr!=null){
iaddressRepository.delete(addr);
}
return addr;
}
}
Now the question is: with controller how I do?
Develop a controller for each class? knowing that I have 30 service classes.
Is there something approaching the same standard such as Spring Data JPA but for services and controller?
As you see with services classes! I'm obliged to make GenericService classes and create an interface for each class that I have in my package entities.
The controllers and the services should not be generic. Although it's understandable that every entity in your app could be created or found by ID, the services should only have the methods needed to implement the business logic of the app.
And the controllers should be created to implement the UI layer of your app. So, once you have a specification (or a clear idea in mind) of how a specific page of your application should look like and work, then implement te controller and the services to implement this page.
If your app is so generic that all it does is create, update and delete rows in tables, then you don't need to implement anything: a generic database web interface like PHPMyAdmin will do.
You can use generic service and controllers only without annotations, i.e with XML configuration. For controllers you also have to set Map<[methodName],org.springframework.web.bind.annotation.RequestMapping> for each controller and extend (override) org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping to use it.
See example https://sites.google.com/site/beigeerp/home/spring-generic-controller

Resources