#RestController
public class BookController {
#Autowired
BookService bookService;
#PostMapping("/saveBook")
public void postBook(#RequestBody Book book) {
this.bookService.insertBook(book);
}
#GetMapping("/allBooks")
public Result<Record> getBooks(){
return this.bookService.getBooks();
}
}
I am trying to perform a crud operation using jooq+postgresql in spring boot, calling APIs from the postman. But it is not working. Please share some link and your ideas.
I am sending the JSON object from postman but is not convert in the book object.
Related
I would like to do something on every api call to my spring boot app. I use Spring AOP to achieve this. Using:
#Pointcut("within(#org.springframework.stereotype.Controller *)")
public void controller() {
}
#Pointcut("within(#org.springframework.web.bind.annotation.RestController *)")
public void restController() {
}
#After("(controller() || restController())")
public void loggingAdvice(JoinPoint joinPoint) {
// TODO: do something
}
Using that I can get all the event when API is being called. However, I am also using spring rest data for crud mechanism that automatically generate API end point, for example:
#RepositoryRestResource(collectionResourceRel = "users", path = "users")
public interface UserRepository extends PagingAndSortingRepository<User, Long> {
User findByEmail(String email);
}
The question is, can I create a point cut for every API end point that is generated by spring rest data?
Following pointcut will target all the RESTful endpoint calls made at "/users"
Considering the package of UserRepository is rg.so.example.datarest
#Pointcut("execution(* rg.so.example.datarest.UserRepository.*(..))")
public void dataRest() {
}
A more generic pointcut to target all the Repository implementations in a package rg.so.example.datarest would be
#Pointcut("execution(* rg.so.example.datarest..*(..))")
How to remove/handle irrelevant or bad sort parameters from http url using Pageable interface in spring boot?
For e.g. I have a query like
http://localhost:8080/all?sort=firstName,asc&sort=nosuchfield,asc
How can I handle or remove the irrelevant field "nosuchfield"?
Also, how can I limit sort parameters in URL?
If the sorting field doesn't present in the database then below exception will be thrown by Spring JPA.
org.springframework.data.mapping.PropertyReferenceException: No property nosuchfield found for type <TYPE>!
at org.springframework.data.mapping.PropertyPath.<init>(PropertyPath.java:94)
at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:382)
at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:358)
However, the exception can be handled using various types. Ultimately, you can just log it or transform it into any custom exception. As per my requirement, I have transformed it into a custom exception.
Using AOP
#Aspect
#Component
public class UnKnownColumnSortingExceptionHandler {
#AfterThrowing(pointcut = "execution(* com.repositorypackage.*.*(..))", throwing = "exception")
public void executeWhenExceptionThrowninRepository(JoinPoint jp, Throwable ex) {
if (ex instanceof PropertyReferenceException) {
throw new CustomException("Invalid Database operation");
}
}
}
Using #ControllerAdvice(Exception handling in Application wise)
#ControllerAdvice
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {
public GlobalExceptionHandler() {}
#ExceptionHandler({PropertyReferenceException.class})
public ResponseEntity<Void> handleAllExceptions(Exception ex, WebRequest req) {
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
Exception handling in Controller wise
Add the below piece of code to your controller
#ExceptionHandler({PropertyReferenceException.class})
public ResponseEntity<Void> handleAllExceptions(Exception ex, WebRequest req)
{
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
I have created Webservice using Spring boot and in this there is a rest controller which hits the database via vendor based JDBC driver and fetch the records. In this process number of records retrieved are more than 80K records. Due to this when ever we are hitting the the rest endpoint as client , we are getting time out errors.
I have tried setting up the asynchronous calls using the below tutorial.But unfortunately , rest calls are still timing out.
https://howtodoinjava.com/spring-boot2/enableasync-async-controller/
Controller
#RequestMapping(value = "/v1/lr/fullpositionasync", produces = {APPLICATION_JSON_UTF8_VALUE}, method = RequestMethod.GET)
#ResponseBody
public CompletableFuture<List<Position>> retrieveTradePositionsFullAsync(HttpServletRequest request, HttpServletResponse response) throws ExecutionException, InterruptedException {
CompletableFuture<List<Position>> positionList =null;
try {
positionList = positionService.getFullPosition();
}
catch(Exception e){
log.info("Error Occurred in Controller is:"+e.getMessage());
}
CompletableFuture.allOf(positionList).join();
log.info(String.valueOf(positionList.get()));
return positionList;
}
Service
#Service
#Slf4j
public class PositionServiceImpl implements PositionService {
#Autowired
private PositionDao positionDao;
#Async("asyncExecutor")
#Override
public CompletableFuture<List<Position>> getFullPosition() {
List<Position> fullpositionList = null;
log.info("Getting the full Position process started");
fullpositionList = positionDao.retrieveData();
log.info("Total Positions retrieved:"+fullpositionList.size());
try {
log.info("Thread is about to sleep 1000 milliseconds");
Thread.sleep(1000);
}catch(InterruptedException e){
log.info(e.getMessage());
}
log.info("Full Positions retrieval completed");
return CompletableFuture.completedFuture(fullpositionList);
}
}
Configuration
#Configuration
#EnableAsync
#Slf4j
public class AsyncConfiguration
{
#Bean(name = "asyncExecutor")
public Executor asyncExecutor()
{
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(20);
executor.setMaxPoolSize(1000);
executor.setWaitForTasksToCompleteOnShutdown(true);
executor.setThreadNamePrefix("AsynchThreadForEndPoint-");
executor.initialize();
log.info("Executor is :"+executor.toString());
return executor;
}
}
DAO
#Repository
public class PositionDaoImpl implements PositionDao {
#Autowired
private JdbcTemplate jdbcTemplate;
private static final String ALL_POSITION_QUERY = "call AllPositionProcedure()";
public List<Position> retrieveData() {
return jdbcTemplate.query(ALL_POSITION_QUERY, new BeanPropertyRowMapper(Position.class));
// List<Map<String, Object>> mapList = jdbcTemplate.queryForList(sql);
}
You can't perform async operations over the Database by using JDBC. JDBC is blocking, so it will block your thread until the operations will be executed. If you want to execute operations in an async manner, use R2DBC instead of JDBC.
For your use case, the best way to do is convert your application into Reactive Streams (Flux).
A Flux is a Reactive Streams Publisher. it is a fully non-blocking reactive programming foundation for the JVM, with efficient demand management (in the form of managing "backpressure"). It integrates directly with the Java 8 functional APIs, notably CompletableFuture, Stream, and Duration. It offers composable asynchronous sequence APIs Flux (for [N] elements) and Mono (for [0|1] elements), extensively implementing the Reactive Streams specification.
it is very simple to implement in existing app. just change your repository return type Flux instead of List or Future.
For more info, you can take reference Here
I am trying to call spring-boot rest controller but it throws o.s.web.servlet.pagenotfound spring boot, I have seen too many answers here but none of these helped me.
controller class is as below
#RestController
#RequestMapping("/users")
public class UsersController {
#Autowired
private UsersRepository usersRepository;
#GetMapping("/users")
public List<Users> getAllUsers() {
return usersRepository.findAll();
}
}
And application.yml is as below
spring.datasource.url = jdbc:mysql://localhost:3306/mydb?useSSL=false
spring.datasource.username=mine
spring.datasource.password=mine
kindly let me know if any further information required
I had the same problem, there should be a problem with your URL. You must be hitting the wrong URL.
I'm assuming you are using Postman for testing the GET Request.
Check if you are hitting through GET Request, and the format is JSON.
And try the below:
#RestController
#RequestMapping(value = "/")
public class UsersController {
#Autowired
private UsersRepository usersRepository;
#GetMapping("/users")
public List<Users> getAllUsers() {
return usersRepository.findAll();
}
}
Given the following code sample
-- client library code
#FeignClient("string-service")
public interface StringClient {
#RequestMapping(method = RequestMethod.GET, value = "/microservicestring")
public String home();
}
#Service
public class StringHystrixClient {
private final SpringClient springClient;
//....
}
-- service library code
#RestController
public class StringController implements StringClient {
public String home(){
return "World";
}
}
#SpringBootApplication
#EnableHystrix
#EnableEurekaClient
#EnableFeignClients
public class StringApplication { ....}
If the service library references the client library, when the application gets started, through component scanning we will get to a state where in filling the dependencies from StringHystrixClient, the spring container will not know what to do because there are two beans implementing StringClient.
One solution to avoid this would be to not implement the StringClient in the StringController, but the code duplication from the interface and the rest controller would be error prone. Can somebody point out a more elegant solution to this problem?