I'm wondering how can I access an attribute from my entity model class to perform a condition. I need to validate whether a column status
from the database is 0 or 2 before the deleteById()
repository function executes the deletion, as if it is 1, it shouldn't be executed.
My thinking is to put the business login in the service layer, so I'm trying to put the condition right there:
public void delete(int id) {
if (reportRequest.getStatus() != 1) {
log.info("The report request {} was successfully deleted", id);
reportRequestRepository.deleteById(id);
} else {
log.error("It was not possible to delete the selected report as it hasn't been processed yet");
}
}
I'm getting the following error:
Error starting ApplicationContext. To display the conditions report re-run your
application with 'debug' enabled.
2022-10-25 18:44:38.538 ERROR 2328 --- [ main]
o.s.b.d.LoggingFailureAnalysisReporter :
***************************
APPLICATION FAILED TO START
***************************
Description:
Parameter 0 of constructor in com.ssc.test.cb3.service.ReportRequestService required a
bean of type 'com.ssc.test.cb3.model.ReportRequest' that could not be found.
The injection point has the following annotations:
- @org.springframework.beans.factory.annotation.Autowired(required=true)
Action:
Consider defining a bean of type 'com.ssc.test.cb3.model.ReportRequest' in your
configuration.
2022-10-25 18:44:38.543 ERROR 2328 --- [ main]
o.s.test.context.TestContextManager : Caught exception while allowing
TestExecutionListener
[org.springframework.test.context.web.ServletTestExecutionListener@7d446ed1] to prepare
test instance [com.ssc.test.cb3.Cb3ApplicationTests@1f72fbd1]
java.lang.IllegalStateException: Failed to load ApplicationContext
Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 4.735 s <<< FAILURE! -
in com.ssc.test.cb3.Cb3ApplicationTests
contextLoads Time elapsed: 0.001 s <<< ERROR!
java.lang.IllegalStateException: Failed to load ApplicationContext
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error
creating bean with name 'reportRequestController': Unsatisfied dependency expressed
through field 'reportRequestService'; nested exception is
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean
with name 'reportRequestService' defined in file
At the end of the error it is the following, I attach an image as somehow I cannot paste it here:
No qualifying bean of type 'com.ssc.test.cb3.model.ReportRequest' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
This is my current code:
Model class ReportRequest:
package com.ssc.test.cb3.model;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* Class that models the entity report request table of the database
* @author ssc
*/
@Entity
@Table(name = "report_request")
@Data
public class ReportRequest {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "seq_id")
private int id;
@Column(name = "request_date", insertable = false, nullable = true)
private String requestDate;
@Column(name = "request_userid")
private int requestUserId;
@Column(name = "request_email")
private String requestEmail;
@Column(name = "start_date")
private String startDate;
@Column(name = "end_date")
private String endDate;
@Column(name = "report_type")
private int reportType; // 0 === cliente, 1 === proveedor
@Column(name = "contact_id")
private int contactId;
@Column(name = "contact_id_customer") // Id from the client or provider chosen
private int contactIdCustomer;
@Column(name = "contact_id_provider") // Id from the provider or provider chosen
private int contactIdProvider;
private String rgids;
private int status; // 0 === active, 1 === inactive
@Column(name = "process_start")
private String processStart;
@Column(name = "process_finish")
private String processFinish;
@Column(name = "call_filter") // 0 === Answered calls, 1 === Not answered, 2 === both
private int callQuery;
@Column(name = "file_name")
private String fileName;
}
Repository class:
package com.ssc.test.cb3.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import com.ssc.test.cb3.model.ReportRequest;
/**
* Class that extends to the repository for database management queries with
* table report_request
*
* @author ssc
*/
@Repository
public interface ReportRequestRepository extends JpaRepository<ReportRequest, Integer> {
}
Service class:
package com.ssc.test.cb3.service;
import com.ssc.test.cb3.repository.ReportRequestRepository;
import org.springframework.stereotype.Service;
import com.ssc.test.cb3.model.ReportRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
/**
* Class to prepare the services to be dispatched upon request.
*
* @author ssc
*/
@Service
@RequiredArgsConstructor
@Slf4j
public class ReportRequestService {
@Autowired
private ReportRequest reportRequest;
private final ReportRequestRepository reportRequestRepository;
/**
* Function to delete a report from the database
*
* @param id from the report request objet to identify what is the specific
* report
*/
// public void delete(int id) {
// log.info("The report request {} was successfully deleted", id);
// reportRequestRepository.deleteById(id);
// }
public void delete(int id) {
if (reportRequest.getStatus() != 1) {
log.info("The report request {} was successfully deleted", id);
reportRequestRepository.deleteById(id);
} else {
log.error("It was not possible to delete the selected report as it hasn't been processed yet");
}
}
}
Class controller:
package com.ssc.test.cb3.controller;
import com.ssc.test.cb3.model.ReportRequest;
import com.ssc.test.cb3.service.ReportRequestService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* Class to handle REST services and APIs for the download Report's class
*
* @author ssc
*/
@RestController
@RequestMapping("/v1/reportRequest")
@CrossOrigin(origins = "http://localhost:3000")
public class ReportRequestController {
@Autowired
private ReportRequestService reportRequestService;
/**
* Method to delete a report request by its id number, it will call the service method and passed the id captured
* @param id
*/
@DeleteMapping("/delete/{id}")
public void deleteReport(@PathVariable int id) {
reportRequestService.delete(id);
}
}
I would appreciate so much if someone can guide me on how to achieve this task.
CodePudding user response:
You're trying to inject an entity class into the service class:
@Autowired
private ReportRequest reportRequest;
That line is throwing the exception because that entity is not managed by Spring.
I guess you´re trying to get a specific record, in that way you have to use the repository.
Try this:
public void delete(int id) {
ReportRequest reportRequest = reportRequestRepository.findById(id).orElse(null);
if (reportRequest == null || reportRequest.getStatus() == 1) {
log.error("It was not possible to delete the selected report as it hasn't
been processed yet");
} else {
reportRequestRepository.deleteById(id);
log.info("The report request {} was successfully deleted", id);
}
}
I'll also recommend you throw an exception and use @ControllerAdvice to handle the exception to be sent to front-end.
CodePudding user response:
Try to add (guess may be missed) @ComponentScan in your @Configuration class / SpringBoot starter. For Example :
@Configuration
@ComponentScan("com.my.package")
public class MyRootConfigurationClass
CodePudding user response:
Despite is possible to externalize the values used to define what can be deleted or should not, as correctly pointed by an earlier answer, I assume that your logic does not require an extreme flexibility. Consequently a simpler and cleaner approach may implement an enum class for the status.
public enum Status {
STATUS_PROCESSED_TYPE_ONE(0),
STATUS_UNPROCESSED(1),
STATUS_PROCESSED_TYPE_TWO(2);
private int value;
Status(int status) {
this.value = status;
}
public int getValue() {
return value;
}
}
This class does not require any Spring "magic" and helps to externalize the specific values (0,1,2) from your logic which may be then implemented in your service class as
boolean isDeletable(int value) {
return Status.STATUS_PROCESSED_TYPE_ONE.getValue() == value
|| Status.STATUS_PROCESSED_TYPE_TWO.getValue() == value;
}