Reputation: 560
I have been experimenting with spring-data-rest (SDR) and am really impressed with how quickly I can build a rest api. My application is based around the following repository which gives me GET /attachements and POST /attachements
package com.deepskyblue.attachment.repository;
import java.util.List;
import org.springframework.data.repository.Repository;
import com.deepskyblue.attachment.domain.Attachment;
public interface AttachmentRepository extends Repository<Attachment, Long> {
List<Attachment> findAll();
Attachment save(Attachment attachment);
}
One thing I am confused about though is how I add custom business logic. SDR seems great if I just want a rest API to my data, however a traditional Spring application would normally have a service tier where I can have business logic. Is there a way of adding this business logic with SDR?
Upvotes: 22
Views: 7587
Reputation: 45593
A good answer at : https://www.reddit.com/r/java/comments/90wk5y/spring_rest_business_logic/
If your future service might have any of business logic, even simple, you should not use Spring Data Rest.
Spring Data Rest is perfectly suits case when you only need basic control of entities(think CRUD).
With the case one could start with spring web, rest controllers and use JSON representation as your views.
The Events
and Validator
can help if your logic deals with One entity.
Don't get me wrong, in a normal project you can find many places which there are not heavy logic and the Spring Data Rest fits quit well and can save lots of time.
Upvotes: 3
Reputation: 137
To add custom logic in Spring-Data-Rest you have to register your Interceptor to receive request before it goes to repository. Here is how you can do that
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;
import static java.lang.String.format;
public class MyInterceptor extends HandlerInterceptorAdapter {
@Autowired
private MyRepository myRepository;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// Simple check to see if database object exists for requesting urls otherwise
// throw runtime exception to be picked up by handler for error response
Map pathVariables = getUrlPathVariables(request);
String myId = (String) pathVariables.get("myId"); // e.g. /rest/path/${myParam}
if (myId != null && myRepository.findById(myId) == null) {
throw new RuntimeException("My Object not found");
}
return true;
}
private Map getUrlPathVariables(HttpServletRequest request) {
return (Map) request.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
}
}
Source: https://gist.github.com/m-x-k/03a87252d2458010e1d69f37e35af6f1
For better details: https://www.baeldung.com/spring-mvc-handlerinterceptor
Upvotes: 0
Reputation: 1154
I ended up creating a custom Aspect that's around repository method. Something like this (groovy):
@Aspect
@Component
@Slf4j
class AccountServiceAspect {
@Around("execution(* com.test.accounts.account.repository.AccountRepository.save*(..))")
Object saveAccount(ProceedingJoinPoint jp) throws Throwable {
log.info("in aspect!")
Object[] args = jp.getArgs()
if (args.length <= 0 || !(args[0] instanceof Account))
return jp.proceed()
Account account = args[0] as Account
account.active = true
jp.proceed(account)
}
}
Not ideal but you can modify model before saving it without writing spring data rest controllers from scratch.
Upvotes: 4
Reputation: 1194
There are many possibilities.
Validators (http://docs.spring.io/spring-data/rest/docs/current/reference/html/#validation) for validating received objects.
Event Handlers http://docs.spring.io/spring-data/rest/docs/current/reference/html/#events) that will be called when validation was okay.
Custom Controllers (http://docs.spring.io/spring-data/rest/docs/current/reference/html/#customizing-sdr.overriding-sdr-response-handlers) when you manually want to handle the request.
Upvotes: 7
Reputation: 19640
I guess you are talking about the 3 tier architecture business tier, presentation tier and persistence tier.
I usually follow this to group my code together presentation tier will be the one that has all the classes [@RestController] Rest annotations and methods that is directly interacting with the post and get calls by the front end .
These classes will in turn Autowire the business tier and Service tier for getting data from the database or adding some business logic before fetching from the database.
Even ou can make use of RepositoryRestController
. To take advantage of Spring Data REST’s settings, message converters, exception handling, and more,
Hope this is what you were looking at.
Upvotes: 1