Execute methods inside CRON JOBS - spring

My question is about executing a method inside a Cron Job in Spring boot. I have a class named Task below
#Entity
#Table(name = "task", schema = "public")
public class Task {
#Id
#GeneratedValue
private Long id;
#NotEmpty
private String date;
#NotEmpty
private String startTime;
#NotEmpty
private String stopTime;
#NotEmpty
#Column(length=1000)
private String description;
#ManyToOne
#JoinColumn(name="USER_EMAIL")
private User user;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public String getStartTime() {
return startTime;
}
public void setStartTime(String startTime) {
this.startTime = startTime;
}
public String getStopTime() {
return stopTime;
}
public void setStopTime(String stopTime) {
this.stopTime = stopTime;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public Task(String date, String startTime, String stopTime, String description, User user) {
this.date = date;
this.startTime = startTime;
this.stopTime = stopTime;
this.description = description;
this.user = user;
}
public Task(String date, String startTime, String stopTime, String description) {
this.date = date;
this.startTime = startTime;
this.stopTime = stopTime;
this.description = description;
}
public Task() {
}
}
The task has a stopTime, and I want to delete that task when passes the deadline. The time will checked from a Cron job method as shown below
#Scheduled(cron = "0 * * * * ?")
public void scheduleTaskWithCronExpression() {
logger.info("Cron Task :: Execution Time - {}", dateTimeFormatter.format(LocalDateTime.now()));
}
than in TaskRepository I have created a query to take the time of deadline of all tasks
public interface TaskRepository extends JpaRepository<Task, Long> {
#Modifying
#Query("select stopTime from Task ")
ZonedDateTime showEndTimeTasks(ZonedDateTime stopTime);
}
And here is the delete method
#GetMapping("deleteTask")
public void deleteTask(#RequestParam long id, HttpServletResponse response) throws Exception {
taskService.deleteTask(id);
response.sendRedirect("/profile");
}
With all this things how can I delete automatically all tasks that have passed the deadline?
Thanks in advance!

Why not use something like this:
#Scheduled(cron = "0 * * * * ?")
public void scheduleTaskWithCronExpression() {
DateTime currentT = dateTimeFormatter.format(LocalDateTime.now()));
List<Task> tasks2beDeleted = taskService.expiredTasks(DateTime currentT);
taskService.deleteAll(tasks2beDeleted);
}
Few notes:
Your repository seems weird, it should return expired tasks not time.
You can implement expiredTasks with db's now() method instead
I don't know how, but if it is okey you can implement a procedure inside your db
It seems you made a service layer that uses repository, you can also implement a service method that uses two repository method like taskService.deleteAllExpired(); which seems way better.

Related

Spring boot does not editing record in to mysql

when i updating the records via postman record not updating it will create a new record i don't know why.i attached screenshot below along with code what i tried so far.i have attched the controller,service,
entity,repository.
i am tring this since yesterday problem not solved please some one will help me to solve
enter image description here
EmployeeController
#PutMapping("/edit/{id}")
private Employee update(#RequestBody Employee employees,#PathVariable(name = "id") long id)
{
Employee emp = services.get(id);
services.saveOrUpdate(emp);
return employees;
}
Services
//updating a record
//updating a record
public void update(Employee employees, int id)
{
repo.save(employees);
}
Repository
#Repository
public interface EmployeeRepository extends CrudRepository<Employee,Long> {
}
Entity
#Entity
#Table(name="Records")
public class Employee {
#Id
#Column(name="id")
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#Column(name="fname")
private String fname;
#Column(name="lname")
private String lname;
#Column(name="city")
private String city;
#Column(name="phone")
private String phone;
#Column(name="salary")
private String salary;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getFname() {
return fname;
}
public void setFname(String fname) {
this.fname = fname;
}
public String getLname() {
return lname;
}
public void setLname(String lname) {
this.lname = lname;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getSalary() {
return salary;
}
public void setSalary(String salary) {
this.salary = salary;
}
}
This an example of UPDATE and it worked for me.
//HTTP PUT
#PutMapping("/owners/{id}")
public void updateOwner(#RequestBody Owner owner, #PathVariable int id) {
owner.setId(id);
ownerRepos.save(owner);
}
I used the CrudRepository too.
Also I notice that you call services.saveOrUpdate(emp) but at the same time you showed us "public void update(Employee employees, int id)" below. If'd better if you could show the definition of the method saveOrUpdate()
SaveOrUpdate uses the ID of the object to determine if the object is the same or new. When updating, you're not considering the ID of the employee. You should first fetch the Object from DB and update the same object. The updates should take place on a persistent object

Null value in primary key of hibernate entity

I faced with problem of null value in PK.
Here's an entity:
#Entity
#Table(name="space")
public class Space implements Serializable {
#Id
#GeneratedValue
#Column(nullable = false, unique = true)
private Long id;
#ManyToOne(fetch = FetchType.LAZY)
#JoinColumn(name="user_id")
private UserAccount user;
private String name;
private String description;
private Date createdTime;
private Date modifiedTime;
#OneToMany(mappedBy="space")
private Set<SpaceAccess> spaceAccesses = new HashSet<>();
public Set<SpaceAccess> getSpaceAccesses() {
return spaceAccesses;
}
public void setSpaceAccesses(Set<SpaceAccess> spaceAccesses) {
this.spaceAccesses = spaceAccesses;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Space() {}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public UserAccount getUser() {
return user;
}
public void setUser(UserAccount user) {
this.user = user;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Date getCreatedTime() {
return createdTime;
}
public void setCreatedTime(Date createdTime) {
this.createdTime = createdTime;
}
public Date getModifiedTime() {
return modifiedTime;
}
public void setModifiedTime(Date modifiedTime) {
this.modifiedTime = modifiedTime;
}
}
I wrote strategy to generate PK properly but I always get Null in id field when I create new instance of the Space:
Space space = new Space();
Here's content of the object:
What i should do to generate id of instance properly using hibernate/spring mechanisms?
application.properties:
spring.datasource.url="some_url"
spring.datasource.username=name
spring.datasource.password=password
spring.jpa.generate-ddl=true
P.S. I use spring-boot-starter-data-jpa with version: 2.3.4.RELEASE.
Use:
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}

No converter found capable of converting from type to type #2

I know it's another similar question, but I can't answer it myself, that's why I'm writing to you for help.
I try to create my own #Query and returns a conversion error on two occasions. My guess is there is a problem with the service, but this is where my knowledge ends.
Here is my code:
Main entity
#Data
#Entity
#Table(name = "users")
public class User {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String name;
private String city;
private Date startDate;
private boolean stat;
public User() {
}
public User(String name, String city, Date startDate, boolean stat) {
this.name = name;
this.city = city;
this.startDate = startDate;
this.stat = stat;
}
}
2.Second model
public class UserName {
private String firstname;
public UserName() {
}
public UserName(String firstname) {
this.firstname = firstname;
}
public String getFirstname() {
return firstname;
}
public void setFirstname(String firstname) {
this.firstname = firstname;
}
}
3.Third model
public class UserCount {
private String city;
private int count;
public UserCount() {
}
public UserCount(String city, int count) {
this.city = city;
this.count = count;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
}
Repository
#Repository
public interface UserRepository extends JpaRepository<User, Long> {
#Query("select p from User p") //1.it's work
List<User> getAll();
#Query("select u from User u where u.name like %?1") //2.it's work
List<User> findByFirstnameEndsWith(String firstname);
#Query("select u.name from User u ") //3. don't work
List<UserName> getNameUsers();
// this SQL working in database console H2
// SELECT city, count(*) FROM USERS WHERE stat = true GROUP BY city
#Query("select u.city, count (u) from User u where u.stat = true group by u.city") //3. don't work
List<UserCount> getOwnQuery();
}
Service
#Service
public class UserService {
#Autowired
private UserRepository repo;
public List<UserName> getN (){
return repo.getNameUsers();
}
public List<UserCount> getC(){
return repo.getOwnQuery();
}
}
Controller
#Controller
public class MyController {
#Autowired
private UserRepository repo;
#Autowired
private UserService repoService;
#GetMapping("/") //1.it's work
ResponseEntity<List<User>> getAllCity(Pageable page){
return ResponseEntity.ok(repo.getAll());
}
#GetMapping("/s") //2.it's work
ResponseEntity<List<User>> getAllUsers(Pageable page){
return ResponseEntity.ok(repo.findByFirstnameEndsWith("Seba"));
}
#GetMapping("/f") ///3.don't work
ResponseEntity<List<UserName> >getUsersName(Pageable page){
return ResponseEntity.ok(repoService.getN());
}
#GetMapping("/c") ///4.don't work
ResponseEntity<List<UserCount> >getUsersCount(Pageable page){
return ResponseEntity.ok(repoService.getC());
}
}
It also adds source code on GitHub
sorry i didn't add the error code
Use constructor with NEW keyword in #Query to get List<UserName>
#Query("select NEW com.sub.model.UserName(u.name) from User u ")
List<UserName> getNameUsers();
And do the same for List<UserCount>
#Query("select NEW com.sub.model.UserCount(u.city, count(u)) from User u where u.stat = true group by u.city")
List<UserCount> getOwnQuery();

Convert String to LocalDateTime

I have an error in registration of tasks because the time must be converted from String to LocalDateTime and I don't know how to convert.
Below is my Task class:
#Entity
#Table(name = "task", schema = "public")
public class Task {
#Id
#GeneratedValue
private Long id;
#NotEmpty
private String date;
#NotEmpty
private LocalDateTime startTime;
#NotEmpty
private LocalDateTime stopTime;
#NotEmpty
#Column(length = 1000)
private String description;
#ManyToOne
#JoinColumn(name = "USER_EMAIL")
private User user;
public Task() {
}
public Task(String date, LocalDateTime startTime, LocalDateTime stopTime, String description, User user) {
this.date = date;
this.startTime = startTime;
this.stopTime = stopTime;
this.description = description;
this.user = user;
}
public Task(String date, LocalDateTime startTime, LocalDateTime stopTime, String description) {
this.date = date;
this.startTime = startTime;
this.stopTime = stopTime;
this.description = description;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public LocalDateTime getStartTime() {
return startTime;
}
public void setStartTime(LocalDateTime startTime) {
this.startTime = startTime;
}
public LocalDateTime getStopTime() {
return stopTime;
}
public void setStopTime(LocalDateTime stopTime) {
this.stopTime = stopTime;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
In TaskController class I have that function to register Tasks in the database:
#PostMapping("/addTask")
public String addTask(#Valid Task task,
BindingResult bindingResult,
HttpSession session,
#RequestParam("datetime")
#DateTimeFormat(pattern = "dd.MM.yyyy HH:mm:ss.SSSZ") LocalDateTime dateAndTime) {
if (bindingResult.hasErrors()){
return "views/taskForm";
}
String email = (String) session.getAttribute("email");
taskService.addTask(task, userService.findOne(email));
return "redirect:/users";
}
And in TaskService is the function for adding tasks in TaskController:
public void addTask(Task task, User user) {
task.setUser(user);
taskRepository.save(task);
}
Please can someone resolve this error:
Failed to convert property value of type java.lang.String to required
type java.time.LocalDateTime for property startTime; nested exception
is org.springframework.core.convert.ConversionFailedException: Failed
to convert from type [java.lang.String] to type
[#org.hibernate.validator.constraints.NotEmpty
java.time.LocalDateTime] for value 09:00; nested exception is
java.lang.IllegalArgumentException: Parse attempt failed for value
[09:00]
and this:
Failed to convert property value of type java.lang.String to required
type java.time.LocalDateTime for property stopTime; nested exception
is org.springframework.core.convert.ConversionFailedException: Failed
to convert from type [java.lang.String] to type
[#org.hibernate.validator.constraints.NotEmpty
java.time.LocalDateTime] for value 18:00; nested exception is
java.lang.IllegalArgumentException: Parse attempt failed for value
[18:00]
I have spent many days and I cannot resolve this.
Thanks in advance!
You can write a converter to convert from a String to LocalDateTime and vice versa.
#Converter(autoApply = true)
public class LocalDateTimeConverter implements AttributeConverter<LocalDateTime, String> {
private final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
#Override
public String convertToDatabaseColumn(LocalDateTime locDate) {
return (locDate == null ? null : formatter.format(locDate));
}
#Override
public LocalDateTime convertToEntityAttribute(String dateValue) {
return (dateValue == null ? null : LocalDateTime.parse(dateValue, formatter));
}
}
If you want to define a converter for each variable use
#Convert(converter = LocalDateTimeConverter.class)
private LocalDateTime stopTime;
Use below to convert the time from String to LocalDateTime, but make sure you are getting the time in String form.
String str = "2018-12-10 12:30";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
LocalDateTime dateTime = LocalDateTime.parse(str, formatter);

How to combine two DAOs in generic way with only one method in Service layer in Spring Boot

Is it possible to combine two DAOs into one Service method?
I want to create a generic method which will choose correct DAO based on the input parameter. What for now I came up with is the method which will accept Dao from the outside the service object. But this requires to initialize appropriate Dao in the Controller which is a little bit ugly...
Measurement is just an interface for Temperature.java and Humidity.java entities with separate tables on PostgreSQL.
#Service
public class MeasurementService {
#Autowired
private TemperatureDao temperatureDao;
#Autowired
private HumidityDao humidityDao;
public<T extends PagingAndSortingRepository<Measurement, Long>> void insertMeasurementForUser(String username, List<Measurement> measurements, T dao) {
dao.saveAll(measurements);
}
}
TemperatureDao.java
#Repository
public interface TemperatureDao extends PagingAndSortingRepository<Temperature, Long> {
#Query("select u from Temperature u where u.owner = ?1 order by u.id desc")
List<Temperature> findLatestTemperatureForUser(User user, Pageable pageable);
}
HumidityDao.java
#Repository
public interface HumidityDao extends PagingAndSortingRepository<Humidity, Long> {
#Query("select u from Humidity u where u.owner = ?1 order by u.id desc")
List<Humidity> findLatestHumidityForUser(User user, Pageable pageable);
}
Temperature.java
#Entity
#Table(name = "temperature")
public class Temperature implements Measurement {
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.SEQUENCE)
private Long id;
#Column(name = "th1value")
private Float th1Value;
#Column(name = "timestamp")
#NotNull
private LocalDateTime timestamp;
#ManyToOne
#JoinColumn(name = "user_id")
#NotNull
private User owner;
public Temperature() {
}
public Temperature(Float th1Value, LocalDateTime timestamp, User owner) {
this.th1Value = th1Value;
this.timestamp = timestamp;
this.owner = owner;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
#JsonDeserialize(using = LocalDateTimeDeserializer.class)
public LocalDateTime getTimestamp() {
return timestamp;
}
#JsonSerialize(using = LocalDateTimeSerializer.class)
public void setTimestamp(LocalDateTime timestamp) {
this.timestamp = timestamp;
}
#Override
public User getOwner() {
return owner;
}
#Override
public void setOwner(User owner) {
this.owner = owner;
}
}
Humidity.java
#Entity
#Table(name = "humidity")
public class Humidity {
#Id
#Column(name = "id")
#GeneratedValue(strategy = GenerationType.SEQUENCE)
private Long id;
#Column(name = "hum1value")
private Float hum1Value;
#Column(name = "timestamp")
#NotNull
private LocalDateTime timestamp;
#ManyToOne
#JoinColumn(name = "user_id")
#NotNull
private User owner;
public Humidity() {
}
public Humidity(Float hum1Value, LocalDateTime timestamp, User owner) {
this.hum1Value = hum1Value;
this.timestamp = timestamp;
this.owner = owner;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
#JsonDeserialize(using = LocalDateTimeDeserializer.class)
public LocalDateTime getTimestamp() {
return timestamp;
}
#JsonSerialize(using = LocalDateTimeSerializer.class)
public void setTimestamp(LocalDateTime timestamp) {
this.timestamp = timestamp;
}
public User getOwner() {
return owner;
}
public void setOwner(User owner) {
this.owner = owner;
}
}
Any ideas?
You could write a Resolver pattern to return needed dao based on your conditions. You service will use the resolver to get the correct dao.
public HellDao implements BaseDao {
public void save();
}
public ByeDao implements BaseDao {
public void save();
}
public DaoResolver {
#Autowired
private helloDao;
#Autowired
private byeDao;
public BaseDao resolve(Object input) {
//based on input return the correct dao
BaseDao resolvedDao = null;
switch(input.enum) {
case Hello:
resolvedDao = helloDao;
break;
case Hello:
resolvedDao = byeDao;
break;
default:
//decide something for default
}
return resolvedDao;
}
}
public class MyService {
#Autowired
private DaoResolver daoResolver;
public Object doSomething() {
BaseDao dao = daoResolver.resolve(someObject);
//you will get HelloDao or ByeDao based on the input
dao.save();
}
}
You can check for the type of measurements using instanceof so you could do it without generics.
public void insertMeasurementForUser(String username, List<Measurement> measurements) {
if(measurements.get(0) instanceof Temperature)
temperatureDao.saveAll(measurements);
else if(measurements.get(0) instanceof Humidity)
humidityDao.saveAll(measurements);
}

Resources