Mathematical operations in Java Spring boot with services - java

I want to add two columns and place the result in the third. My table conrains 100+ line.
My model:
My repository:
import java.util.List;
#Repository
public interface OilRepo extends JpaRepository<OilModel,Long> {
}
Controller:
#RestController
#RequestMapping()
public class OilController {
#Autowired
private OilService oilService;
#GetMapping(value = "/all")
public List<OilModel> oilModels() { return oilService.getOilModel();}
#PostMapping(value = "/save")
public List<OilModel> oilModel(#RequestBody List<OilModel> oilModel){
return oilService.saveOil(oilModel); }
}
and Services
import java.util.List;
#Service
public class OilService {
#Autowired
private OilRepo oilRepo;
public List<OilModel> getOilModel() { return oilRepo.findAll(); }
public List<OilModel> saveOil(List<OilModel> oilModels){
oilModels.stream().map(oilModel -> oilModel.average =
oilModel.getO_ai_92()+oilModel.getO_ai_95());
return oilRepo.saveAll(oilModels);
}
}
How can I write the service correctly to make this code work?

You can do it inside getAverage() method as shown below:-
public class OilModel {
#Access(AccessType.PROPERTY)
private double average;
...
...
...
public Double getAverage() {
return get0_ai_92() + get0_ai_95();
}
}
and store the list directly without doing any operations on it.
Note:- make sure to add #Access(AccessType.PROPERTY) on average field to allow jpa access the value from the method, not from the field.

Related

Custom Repository Implementation is not being recognized

I am currently working on a project where I have created the following custom Repository:
public interface ServiceRepository<T extends ServiceEntity> extends JpaRepository<T, UUID>, ServiceRepositoryCustom {
}
public interface ServiceRepositoryCustom {
List<ServiceEntity> findAllContainingName(String query);
}
#Repository("Repo")
public class ServiceRepositoryCustomImpl implements ServiceRepositoryCustom {
private final EntityManager em;
public ServiceRepositoryCustomImpl(EntityManager em) {
System.out.println("I got constructed");
this.em = em;
}
#Override
public List<ServiceEntity> findAllContainingName(String name) {
System.out.println("I got called with: " + name);
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<ServiceEntity> cq = cb.createQuery(ServiceEntity.class);
Root<ServiceEntity> serviceEntity = cq.from(ServiceEntity.class);
List<Predicate> predicates = new ArrayList<>();
if(name != null) {
// predicates.add(cb.equal(serviceEntity.get("name"), name));
predicates.add(cb.like(serviceEntity.get("name"), name + "%"));
}
cq.where(predicates.toArray(predicates.toArray(new Predicate[0])));
return em.createQuery(cq).getResultList();
}
}
The print statement "I got called with: " never gets called. So for whatever reason Spring Boot is not running the method through my custom implementation.
Any suggestions? Any help is much appreciated
Edit:
Here is the code that injects and uses the Repository in question
#Repository
public interface PineappleServiceRepository extends ServiceRepository<PineappleServiceEntity> {
}
#Component("Registry")
#DependsOn({"Context", "Repo"})
public class Registry {
private final List<ServiceRepository<? extends ServiceEntity>> serviceRepositories = new ArrayList<>();
public Registry(PineappleServiceRepository pineappleServiceRepository) {
this.serviceRepositories.add(pineappleServiceRepository);
}
}
Edit 2:
The code prints "I got constructed"
Edit 3:
Class where findAllContainingName is called
#RestController
#RequestMapping("/test")
#DependsOn("Registry")
public class ServiceController {
private final Registry registry;
public ServiceController(#NotNull Registry registry) {
this.registry = registry;
}
#GetMapping("")
List<ServiceEntity> all(#RequestParam("q") String query) {
return getAllServices(query);
}
private #NotNull List<ServiceEntity> getAllServices(String query) {
List<ServiceEntity> response = new ArrayList<>();
for(ServiceRepository<? extends ServiceEntity> repo: this.registry.getServiceRepositories()){
response.addAll(repo.findAllContainingName(query));
}
return response;
}
}
Edit 4:
Here the entities:
#Entity
#Table(name = "services")
public abstract class ServiceEntity {
protected #Id
UUID id = UUID.randomUUID();
protected String name;
// Constructor + Getters and Setters
}
#Entity
public class PineappleServiceEntity extends ServiceEntity {
// Additional Properties, matching Constructors, Getters and Setters
}
So I was able to reproduce your problem and fix it. Issue with your code is that your PineappleServiceRepository is not extending ServiceRepositoryCustom directly. It seems your repository needs to implement it directly if you are accessing custom repository methods from that repository. I got that idea from this post.
So to fix your issue, either remove PineappleServiceRepository(as you don't have any properties in PineappleEntity) and use ServiceRepository to call that custom method or make PineappleServiceRepository extend ServiceRepositoryCustom.
I have pushed changes to GitHub with fix. You can take a look. If you want to keep PineappleServiceRepository and access custom method using this repository, let me know, I can update code.

Spring CrudRepository Update doesn't work

I have a project in spring boot and I'm using CrudRepository, but when I try to update, it doesn't do anything.
#Entity
public class PfmSelection implements Serializable{
#Id
private Integer releaseId;
private String preparedBy;
}
Repositiry
#Repository
public interface IPfmSelectionDao extends CrudRepository<PfmSelection, Integer> {
}
Service
public interface IPfmSelectionService {
public PfmSelection save(PfmSelection pfmSelection);
public PfmSelection findById(Integer id);
}
Service Impl
#Service
public class PfmSelectionService implements IPfmSelectionService {
#Autowired
private IPfmSelectionDao pfmSelectionDao;
#Override
#Transactional
public PfmSelection save(PfmSelection pfmSelection) {
return this.pfmSelectionDao.save(pfmSelection);
}
#Override
#Transactional(readOnly = true)
public PfmSelection findById(Integer id) {
return this.pfmSelectionDao.findById(id).orElse(null);
}
}
Service where I use the other Service
#Autowired
private IPfmSelectionService pfmSelectionService;
private void updatePfm(PushModel pushModel) {
PfmSelection pfm = this.pfmSelectionService.findById(167427);
pfm.setPreparedBy("Rodrige");
pfmSelectionService.save(pfm);
}
I don't receive any error in the console.
You need to take a few steps to know what the problem is
Take the return of pfmSelectionService.save(pfm) and print the saved instance returned like below:
private void updatePfm(PushModel pushModel) {
PfmSelection pfm = this.pfmSelectionService.findById(167427);
pfm.setPreparedBy("Rodrige");
PfmSelection pfm2 = pfmSelectionService.save(pfm);
System.out.println(pfm2.getPreparedBy());
}
Put logger/debugger inside the save method, before and after the save method and check for the entry/exit sop/logger statements in log/console like
#Override
#Transactional
public PfmSelection save(PfmSelection pfmSelection) {
System.out.println("Inside save method");
PfmSelection pfmSelectionSaved =
this.pfmSelectionDao.save(pfmSelection);
System.out.println("Exits save method");
return pfmSelectionSaved;
}
Check for any Aop around advice or any place where the exception is being caught but eaten/not thrown further.
Check if there is any update query fired in the logs at the time of save call.
Also check if the setter method pfm.setPreparedBy("Rodrige"); is Empty?

Efficient way of reusing multiple Services having the same functionality but dealing with different entity

I am dealing with multiple entity classes but they have the same attributes.
It's not a good data structure but according to my use case, I have to deal with two entities having the same attributes. As of now I am using multiple controllers, multiple request/response and multiple interfaces and implementations to do the logic part and save into the two corresponding tables.
Is there any efficient way that I could combine both into a single interface, with the DB operations happening in multiple DBs.
Following is a sample code:
#RestController
..
public class FooController {
#Autowired
private FooService fooService;
#GetMapping
public FooResponse findFoo(
#PathVariable(FOO_CONSTANT.PATH_VARIABLE_FOO_ID) String fooId)
throws FooException {
return fooService.findFoo(fooId));
}
}
public interface FooService{
FooResponse findFoo(String fooId);
}
#Service
public class ProspectAssetServiceImpl implements ProspectAssetService {
#Autowired
private FooRepository fooRepository;
#Override
public FooResponse findFoo(String fooId){
FooEntity fooEntity = fooRepository.findByFooId(fooId));
return convertBomToMessaging(fooEntity);
}
}
public class Foo {
private String fooId;
private String fooName;
//getters and setters
}
#Entity
#Table(name = "foo_table")
public class FooEntity {
private String fooId;
private String fooName;
//getters and setters
}
Second Service:
#RestController
..
public class ZooController {
#Autowired
private ZooService ZooService;
#GetMapping
public ZooResponse findZoo(
#PathVariable(Zoo_CONSTANT.PATH_VARIABLE_Zoo_ID) String ZooId)
throws ZooException {
return ZooService.findZoo(ZooId));
}
}
public interface ZooService{
ZooResponse findZoo(String ZooId);
}
#Service
public class ProspectAssetServiceImpl implements ProspectAssetService {
#Autowired
private ZooRepository ZooRepository;
#Override
public ZooResponse findZoo(String ZooId){
ZooEntity ZooEntity = ZooRepository.findByZooId(ZooId));
return convertBomToMessaging(ZooEntity);
}
}
public class Zoo {
private String ZooId;
private String ZooName;
//getters and setters
}
#Entity
#Table(name = "Zoo_table")
public class ZooEntity {
private String ZooId;
private String ZooName;
//getters and setters
}
Suggest me an efficient way to combine these two together?

Cannot instantiate mock objects using InjectMocks-Mockito

I'm new to TDD and mockito aswell, I'm trying to inject mocks into a class to perform a unit test, the class instantiate its dependencies inside a method depending on some validations, I got an error
test class/method
//Its interface
public interface UserService {
public Debt getCustomerDebt(String id);
}
//validator method
public static boolean isValidId(String id){
if(id != null && !id.isEmpty() && !id.trim().equals("")){
return true;
}
return false;
}
public class UserServiceImpl implements UserService {
private Repository repo;
private WSDLCustomerDebt wsdlCostumerDebt;
public static final int USER_EXIST = 1;
public static final int USER_DOESNOT_EXIST = 0;
public UserServiceImpl(){
}
public Debt getCustomerDebt(String id) {
if(ValidatorHelper.isValidId(id)){
repo = new RepositoryImpl();
int exist = repo.getCustomer(id);
if(exist==USER_EXIST){
wsdlCostumerDebt = new WSDLCustomerDebtImpl();
List<Date> meses = wsdlCostumerDebt.obtenerMeses(id);
if(meses.size()>0){
int totalDebt = 0;
for (Date mes : meses){
totalDebt += wsdlCostumerDebt.obtenerDeuda(mes, id);
}
return new Debt(id, BigDecimal.valueOf(totalDebt));
}else{
return new Debt(id, BigDecimal.valueOf(0));
}
}
}
return null;
}
}
mocked class repositoryimpl
public class RepositoryImpl implements Repository {
public int getCustomer(String id) {
int y = Integer.valueOf(1);
return y;
}
}
wsdl mocked class
//Interface
public interface WSDLCustomerDebt {
public List<Date> obtenerMeses(String customerId);
public Integer obtenerDeuda(Date month, String customerId);
}
public class WSDLCustomerDebtImpl implements WSDLCustomerDebt {
public List<Date> obtenerMeses(String customerId) {
return null;
}
public Integer obtenerDeuda(Date month, String customerId) {
Integer y = Integer.valueOf(11);
return y;
}
}
domain class debt
public class Debt {
private String id;
private BigDecimal debt;
public Debt(String id, BigDecimal debt) {
super();
this.id = id;
this.debt = debt;
}
//Getters and setters ....
}
finally test class
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
public class UserServiceImplTest {
#Mock
private Repository repo;
#Mock
private WSDLCustomerDebt wsdlCustomerDebt;
#InjectMocks
private UserServiceImpl userService;
#Before
public void init(){
//repo=Mockito.mock(Repository.class);
//when(wsdlcustomer.obtenerDeuda(D, customerId))
MockitoAnnotations.initMocks(this);
}
#Test
public void noExistingCustomer(){
//Given:
String id = "123";
//When:
Mockito.when(repo.getCustomer(id)).thenReturn(0);
Debt debt = userService.getCustomerDebt(id);
Mockito.verify(repo.getCustomer(Mockito.any(String.class)));
//Then:
assertNull(debt);
}
}
this is the error I'm getting and I'm trying to avoid using a constructor or any getter/setter and to receive the mocks via parameters, maybe it could be caused by a dummy error but at this point I do not know what I'm doing wrong, in fact i think the problem occurs because of the return statement in mocked classes. I'm using mockito version 1.9.5 btw
org.mockito.exceptions.misusing.NotAMockException:
Argument passed to verify() is of type Integer and is not a mock!
Make sure you place the parenthesis correctly!
See the examples of correct verifications:
verify(mock).someMethod();
verify(mock, times(10)).someMethod();
verify(mock, atLeastOnce()).someMethod();
at com.i2btech.poctest.UserServiceImplTest.noExistingCustomer(UserServiceImplTest.java:51)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
First of all, your service doesn't use the mock you're injecting, since it creates a new one when you call the method. The repo should be an argument of the service constructor.
Second, the proper syntax to verify that a method of a mock has been called is not
verify(mock.method())
but
verify(mock).method()
(as the error message clearly says).
So, the line
Mockito.verify(repo.getCustomer(Mockito.any(String.class)))
must be replaced by
Mockito.verify(repo).getCustomer(Mockito.any(String.class))

How to connect Spring with MySQL database?

I have a simple project, based on this guide. I created a simple REST interface and I want it to use my database. I added Hibernate to the dependencies and created the DAO class. I'm using Spring Tool-Suite for IDE. As far as I understand I should add some beans to tell the classes what to use but I don't understand how. Here are my classes.
Application.java
package com.learnspring.projectfirst;
#SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Marker.java
package com.learnspring.projectfirst;
#Entity
public class Marker {
#Id
#Column
#GeneratedValue(strategy=GenerationType.AUTO)
private long id;
#Column
private double longitude;
#Column
private double latitude;
#Column
private String address;
public Marker() {
// Empty constructor
}
public Marker(long id, double longitude, double latitude, String address) {
this.id = id;
this.longitude = longitude;
this.latitude = latitude;
this.address = address;
}
//Getters and Setters
}
MarkerController.java
package com.learnspring.projectfirst.controller;
#Controller
public class MarkerController {
private Logger logger = Logger.getLogger(MarkerController.class.getName());
#Autowired
private MarkerServiceImplementation markerService;
#RequestMapping(value="/markers", method=RequestMethod.GET)
public #ResponseBody List<Marker> getMarkers(#RequestParam(value="city", defaultValue="") String city) {
return this.markerService.getAllMarkers();
}
#RequestMapping(value="/markers/new", method=RequestMethod.POST)
public #ResponseBody Marker addMarker(#RequestBody Marker marker) {
this.markerService.addMarker(marker);
return marker;
}
}
MarkerDaoImplementation.java
package com.learnspring.projectfirst.dao;
#Repository
public class MarkerDaoImplementation implements MarkerDaoInterface {
#Autowired
private SessionFactory sessionFactory;
#Override
public void addMarker(Marker marker) {
this.sessionFactory.getCurrentSession().save(marker);
}
#Override
public void deleteMarker(int markerId) {
this.sessionFactory.getCurrentSession().delete(this.getMarker(markerId));
}
#Override
public Marker getMarker(int markerId) {
return (Marker) this.sessionFactory.getCurrentSession().get(Marker.class, markerId);
}
#Override
public List<Marker> getAllMarkers() {
return this.sessionFactory.getCurrentSession().createQuery("from Marker").list();
}
}
MarkerServiceImplementation.java
package com.learnspring.projectfirst.service;
#Service
public class MarkerServiceImplementation implements MarkerServiceInterface {
#Autowired
private MarkerDaoImplementation markerDao;
#Transactional
public void addMarker(Marker marker) {
this.markerDao.addMarker(marker);
}
#Transactional
public void deleteMarker(int markerId) {
this.markerDao.deleteMarker(markerId);
}
#Transactional
public Marker getMarker(int markerId) {
return this.markerDao.getMarker(markerId);
}
#Transactional
public List<Marker> getAllMarkers() {
return this.markerDao.getAllMarkers();
}
}
And here is the file structure:
I understand that I should tell my program the database name and the columns using beans but I don't understand how. How can I link the java code to the beans? Sorry I pasted so much code, I just wanted to make sure you have everything needed. Thank you in advance!
This is the one you need: Spring Boot with MySQL
Refer this example : Spring MVC with JdbcTemplate Example
The annotations in your "Marker" class determine the MySQL table and column names (based on the class and class variable names). The tablename will be "marker", with the columns "id", "longitude", "latitude", "address".
You forgot the most important part in your code: your spring configuration. it determines how the SessionFactory instance will be initialized before being injected into your DAO class. Here you have to set an appropriate connection to the MySQL Server (e.g. via an JNDI Resource)

Categories