time format in spring boot - spring-boot

Spring is returning a different time format in swagger from what I have in MYSQL database. I don't know what I did wrongly.
I need help on how to solve it.
I think that my db and the project is not using the same time zone and I don't know how to fix it
model class
#Entity
#NoArgsConstructor
#Data
public class TransactionType {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private Date transactionDate;
private double amount;
private double currentBalance;
private String transactionType;
private String description;
private String depositorOrWithDrawalName;
#ManyToOne
#JoinColumn(name = "account_id")
private BankAccount bankAccount;
}
I have this method that save the information in my Service
public ResponseEntity<TransactionResponse> deposit(TransactionTypeDto transactionTypeDto, String accountNumber) throws DataNotFoundException, DataNotAcceptableException {
BankAccount bankAccount = bankAccountService.getAccountByAccountNumber(accountNumber);
double currentBalance = bankAccount.getCurrentBalance();
TransactionType transactionType = new TransactionType();
if (transactionTypeDto.getAmount()<=0){
throw new DataNotAcceptableException("Amount must be greater than zero");
}
double newBalance = currentBalance+transactionTypeDto.getAmount();
transactionType.setAmount(transactionTypeDto.getAmount());
transactionType.setBankAccount(bankAccount);
transactionType.setCurrentBalance(newBalance);
transactionType.setTransactionType("CREDIT");
transactionType.setTransactionDate(new Date());
transactionType.setDescription(transactionTypeDto.getDescription());
transactionType.setDepositorOrWithDrawalName(transactionTypeDto.getDepositorOrWithDrawalName());
bankAccountService.updateAccountBalance(bankAccount,newBalance,accountNumber);
transactionTypeRepository.save(transactionType);
return new ResponseEntity<>(new TransactionResponse("Deposit","Successful","Your Account "+bankAccount.getAccountNumber()+
" has been credited with "+transactionTypeDto.getAmount()+" at "+transactionType.getTransactionDate()+" by " +
transactionTypeDto.getDepositorOrWithDrawalName()+", your current balance is #"+newBalance), HttpStatus.OK);
}
this is the date in MYSQL database and it's the correct time
2022-12-25 04:09:30
but when I retrieved the information in swagger, I got this as the time.
"transactionDate": "2022-12-25T04:09:30.000+00:00",

Related

How to correctly describe entities with many-to-many relationship, Spring Boot JPA

I have those entities:
#Entity
#Getter
#Setter
#AllArgsConstructor
#NoArgsConstructor
public class Tender {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(nullable = false, updatable = false)
private Long id;
private String source;
private String sourceRefNumber;
private String link;
private String title;
#Column(columnDefinition="TEXT")
private String description;
private String field;
private String client;
private LocalDate date;
private LocalDate deadline;
#ManyToMany
private List<Cpv> cpv;
}
And CPV:
#Entity
#Getter
#Setter
#AllArgsConstructor
#NoArgsConstructor
public class Cpv {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String code;
private String description;
}
Each Tender can have list of Cpv-s.
In my DB I have already list of all CPV codes with description, so when I add new Tender to DB, it should add record to tender_cpv table with tender_id and cpv_id.
But when I'm using this method in my TenderServiceImpl to set Cpv id-s from DB I got error after that when try to save Tender:
#Override
public Tender addNewTender(Tender tender) {
if(tender.getCpv() != null) {
for(Cpv cpv : tender.getCpv()) {
cpv = cpvRepository.findCpvByCode(cpv.getCode());
}
}
tenderRepository.save(tender);
return tender;
}
org.springframework.dao.InvalidDataAccessApiUsageException: org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.supportportal.domain.Cpv;
I understand that somewhere in the description of the entities a mistake was made, because earlier I did not have a database with all the CPV codes and before saving the tender I saved all the CPVs, but now I need to redo the logic to use the existing CPV database.
Please advise how can I change the entity description.
addNewTender method changes solved my problem:
#Override
public Tender addNewTender(Tender tender) {
if(tender.getCpv() != null) {
List<Cpv> dbCpvs = new ArrayList<>();
for(Cpv cpv : tender.getCpv()) {
dbCpvs.add(cpvRepository.findCpvByCode(cpv.getCode()));
}
tender.setCpv(dbCpvs);
}
tenderRepository.save(tender);
return tender;
}
In order for the existing entities from the database to bind to the new object, we had to first get each of them from the database and bind to the new entity.

neo4j RelationshipEntity not created

I'm having issues getting a neo4j RelationshipEntity persisted with Spring Boot. I'm using spring-boot-starter-data-neo4j (2.1.0.RELEASE), and the neo4j docker image tagged 3.4.9.
I have a simple NodeEntity, which contains a collection for the RelationshipEntity:
#NodeEntity
public class Book {
#Id
#GeneratedValue
private Long id;
private String name;
public Book() {}
public Book(String name) {
this.name = name;
}
#Relationship(type = "PURCHASED_WITH", direction = "OUTGOING")
private Set<BookPurchase> purchases = new HashSet<>();
// getters and setters follow
}
I have another NodeEntity, which also contains a collection for the relationship entity:
#NodeEntity
public class CreditCard {
#Id
#GeneratedValue
private Long id;
private String number;
#DateString(value = "yyyy-MM-dd")
private Date expiryDate;
public CreditCard() {}
public CreditCard(String number, Date expiryDate) {
this.number = number;
this.expiryDate = expiryDate;
}
#Relationship(type = "PURCHASED_WITH", direction = "INCOMING")
private Set<BookPurchase> purchases = new HashSet<BookPurchase>();
// getters and setters follow
}
I have the RelationshipEntity, which adds references to both NodeEntity classes in the constructor:
#RelationshipEntity(type = "PURCHASED_WITH")
public class BookPurchase {
#Id
#GeneratedValue
private long id;
#DateString("yyyy-MM-dd")
Date purchaseDate;
#StartNode
private Book book;
#EndNode
private CreditCard card;
public BookPurchase(){}
public BookPurchase(CreditCard card, Book book, Date purchaseDate) {
this.card = card;
this.book = book;
this.purchaseDate = purchaseDate;
this.card.getPurchases().add(this);
this.book.getPurchases().add(this);
}
// getters and setters follow
}
And finally I have the Spring controller tying everything together:
#RestController
public class ExamplesController {
#Autowired
CreditCardRepository creditCardRepository;
#PostMapping(value="/purchases")
public String createPurchases() {
CreditCard card = new CreditCard("11111", new GregorianCalendar(2018, Calendar.FEBRUARY, 12).getTime());
Book book1 = new Book("of mice and men");
BookPurchase purchase1 = new BookPurchase(card,book1,new GregorianCalendar(2018, Calendar.MARCH, 15).getTime());
creditCardRepository.save(card);
return "Successfully created entities";
}
}
Whenever I try to curl -X POST http://localhost:8080/purchases, I just see the following in the neo4j browser - the RelationshipEntity is not persisted, only the nodes.
Can anyone assist?
Thanks to Gerrit Meier for answering this one. My RelationshipEntity was using the primitive long instead of the object/wrapper Long. Complete details here: https://community.neo4j.com/t/neo4j-relationshipentity-not-persisted/3039

Return type of JPA Repository 'getOne(id)' Method

I have the following Spring boot service for an object of type Report -
#Service
public class ReportService {
#Autowired
private ReportRepository reportRepository;
#Autowired
private UserRepository userRepository;
/*get all reports */
public List<Report> getAllReports(){
return reportRepository.findAll();
}
/*get a single report */
public Report getReport(Long id){
return reportRepository.getOne(id);
}
//other similar methods....
}
The problem arises while retrieving a single Report. If a report ID is send which doesn't exist, the following error is generated...
DefaultHandlerExceptionResolver : Failed to write HTTP message:
org.springframework.http.converter.HttpMessageNotWritableException: Could not
write JSON: Unable to find com.interact.restapis.model.Report with id 16;
nested exception is com.fasterxml.jackson.databind.JsonMappingException:
Unable to find com.interact.restapis.model.Report with id 16 (through
reference chain:
com.interact.restapis.model.Report_$$_jvst83c_1["fromUserId"])
Below is the code for my Report Controller
#RestController
public class ReportController {
#Autowired
private ReportService reportService;
//Get all reports
#GetMapping("/interactions")
public List<Report> getAllReports() {
return reportService.getAllReports();
}
//Get single report
#GetMapping("/interactions/{id}")
public ResponseEntity<Report> getReport(#PathVariable Long id) {
if(reportService.getReport(id) == null)
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
return new ResponseEntity<>(reportService.getReport(id), HttpStatus.OK);
}
#PostMapping("/interactions")
public ResponseEntity<Report> addReport(#RequestBody Report report) {
Report report1 = reportService.addReport(report);
if(report1 == null)
return new ResponseEntity<>(report, HttpStatus.NOT_FOUND);
return new ResponseEntity<>(report1, HttpStatus.OK);
}
//Other request methods...
}
Below is the code for my Report Model class -
#Entity
#Table (name = "report")
#EntityListeners(AuditingEntityListener.class)
#JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
public class Report {
#Id
#Column (name = "id")
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
#Column(name = "from_user_id")
private Long fromUserId;
#Column(name = "to_user_id")
private Long toUserId;
#Column(name = "to_user_email")
private String toUserEmail;
#Column(name = "from_user_email")
private String fromUserEmail;
#Temporal(TemporalType.DATE)
#JsonFormat(pattern = "dd-MM-yyyy hh:mm:ss")
#CreatedDate
private Date createdAt;
#Column(nullable = false)
private String observation;
#Column(nullable = false)
private String context;
private String recommendation;
#Column(nullable = false)
private String eventName;
#Temporal(TemporalType.DATE)
#JsonFormat(pattern = "dd-MM-yyyy hh:mm:ss")
#Column(nullable = false)
private Date eventDate;
private boolean isAnonymous;
#Temporal(TemporalType.DATE)
#JsonFormat(pattern = "dd-MM-yyyy hh:mm:ss")
private Date acknowledgementDate;
#OneToMany(cascade = CascadeType.ALL, targetEntity = Action.class)
#JoinColumn(name = "report_id")
private List<Action> actionList;
#Value("${some.key:0}")
private int rating; //Range 0 to 4
private int type;
/*
Getter and setter methods...
*/
}
I want to know if reportRepository.getOne(Long id) returns null so that I can actually check if a particular report doesn't exist in the database. If not, how else can I implement the above?
The JpaRepository.getOne with throw EntityNotFoundException if it couldn't find a record with the given id.
You can use CrudRepository.findById (JpaRepository is a subclass of CrudRepository) which will return an Optional<Report> which can be empty if there are no record for the given id. You can use Optional.isPresent() to check whether it a Report is available or not and take actions accordingly.
Create a method in your ReportRepository.
It will return Report by matched id else return null.
public Optional<Report> findById(Long id);
Note: findById(Long id); should match with the property name in your Report entity.
I am assuming your Report entity is as follows:
public class Entity{
private Long id;
...
}

How to code Spring JPA onetomany relation

I am new to Spring programming and trying the below example with one to many relationship between BID and BIDITEM classes. I am not sure whether the BIDITEM data is saved, as when I tried to retrieve the BID, I am getting only BID data and not BIDITEM data. Do we need to have a repository even for BIDITEM class. I can see that complete BID JSON string, along with BIDITEM is received in create method.
Could you please go through it, and let me know what is wrong with it.
#Entity
#Table(name = "bid")
public class Bid {
#Id
private String title;
#Column
private long startDate;
#Column
private long endDate;
#OneToMany(mappedBy = "myBid", cascade = {CascadeType.ALL})
private List<BidItem> bidItems = new ArrayList<BidItem>();
//Constructor, getter and setter methods go here
}
#Entity
#Table(name="biditem")
public class BidItem
{
#Id
private String item;
#Column
private String desc;
#Column
private double minAmt;
#ManyToOne
#JoinColumn(name = "title")
private Bid myBid;
//Constructor, getter and setter methods go here
}
public interface BidRepository extends CrudRepository<Bid, String> {
//Tried even JpaRepository
}
public class BidService {
ObjectMapper mapper = new ObjectMapper();
#Autowired
private BidRepository bidRepo;
public Bid create(String bidJson) throws JsonParseException, JsonMappingException, IOException
{
Bid bid = mapper.readValue(bidJson, Bid.class);
// bidJson string has below string
// {"bidItems":[{"item":"item1","desc":"item1","minAmt":"999"}],
// "title":"bid1","startDate":"D1","endDate":"D5"}
Bid savedBid = bidRepo.save(bid);
return savedBid;
}
public Bid findByID(String title)
{
Bid bid = bidRepo.findOne(title);
return bid;
}
}

converting URI to entity with custom controller in spring data rest?

i have an jpa entity like this.
#Entity
#Table(name = "location")
#Data
public class Location {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
#Column(name = "LOCATION_ID", unique = true)
#NotEmpty(message = "Please Enter Location ID")
private String name;
#Column(name = "LOCATION_DESCRIPTION")
#NotEmpty(message = "Please Enter Location Description")
private String description;
#ManyToOne
#NotNull(message = "Please Choose a Building")
Building building;
#Version
Long version;
}
and the repository like this.
public interface LocationRepository extends PagingAndSortingRepository<Location, Long> {
Location findByName(#Param("name") String name);
}
i am using spring data rest i am able to create location with rest api by providing the following payload
{
"name":"adminxxxxx","description":"adminxxx" , "building": "http://localhost:8080/buildings/2"
}
now i am trying to write my custom controller which will persist the entity. this is my custom controller
#ExposesResourceFor(Location.class)
#RepositoryRestController
#BasePathAwareController
public class LocationController {
#Autowired
LocationRepository locationDao;
#Autowired
LocationResourceAssembler resourceAssembler;
#Value("${buildings.error.messages.uniqueconstraintviolation}")
String uniqueConstrainMessage;
static final String TAG = LocationController.class.getSimpleName();
#RequestMapping(value="locations",method = org.springframework.web.bind.annotation.RequestMethod.POST)
public ResponseEntity<?> save(#RequestBody #Valid Location location) {
try {
location = locationDao.save(location);
LocationResource b = resourceAssembler.toResource(location);
return ResponseEntity.ok().body(b);
} catch (DataIntegrityViolationException e) {
if (locationAlreadyExists(location.getName()))
throw new LocationAlreadyExistException(uniqueConstrainMessage, location);
else
throw new RuntimeException("Some Error Occured");
}
}
i am getting this error
exception is com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of com.alamdar.model.Building: no String-argument constructor/factory method to deserialize from String value ('http://localhost:8080/buildings/2')
at [Source: java.io.PushbackInputStream#5d468b16; line: 3, column: 60] (through reference chain: com.alamdar.model.Location["building"])</div></body></html>
can anyone please help?
I am not sure why you are writing a custom controller however the issue would appear to be that you do not have a default no args constructor so Jackson cannot instantiate an instance.
This is because you are using Lombok's #Data annotation:
https://projectlombok.org/features/Data.html
You should also annotate you class with #NoArgsConstructor to have a default no-args constructor generated:
#Entity
#Table(name = "location")
#Data
#NoArgsConstructor
public class Location {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
#Column(name = "LOCATION_ID", unique = true)
#NotEmpty(message = "Please Enter Location ID")
private String name;
#Column(name = "LOCATION_DESCRIPTION")
#NotEmpty(message = "Please Enter Location Description")
private String description;
#ManyToOne
#NotNull(message = "Please Choose a Building")
Building building;
#Version
Long version;
}

Resources