Spring boot - Service class is null - java

I'm dwelling with an autoWired service class which is null in a Spring Boot application.. Every object is instantiated by Spring, so I don't know why it happens.
The situation is:
I have a Rele.java class which is the following:
#Component
public class Rele {
private Pin pin;
private GpioController gpio;
private GpioPinDigitalOutput relePin;
private static final Logger logger = Logger.getLogger(Rele.class);
private Interruttore interruttore;
#Autowired AccensioneService accensioneService;
public Rele(){
}
// Costruttore
public Rele(Pin pin, Interruttore interruttore) {
this.pin = pin;
this.gpio = GpioFactory.getInstance();
this.relePin = gpio.provisionDigitalOutputPin(pin, "MyRele", PinState.LOW);
this.interruttore = interruttore;
}
public void lightOn() {
try {
if (relePin.isLow()) {
relePin.high();
updateAccensione(interruttore, true);
logger.debug("Rele acceso");
}
} catch (NullPointerException e) {
logger.debug("relepin è:" +relePin);
logger.debug("gpio è:"+gpio);
}
}
public void lightOff() {
if (relePin.isHigh()) {
relePin.low();
updateAccensione(interruttore, false);
logger.debug("Rele spento");
}
}
public void updateAccensione(Interruttore interruttore, boolean acceso) {
Date lastDateAccensione = new Date();
try {
logger.debug("accensioneService is"+accensioneService);
lastDateAccensione = accensioneService.findLastDate(interruttore);
} catch(NullPointerException npe){
logger.debug("accensioneService is: "+accensioneService);
logger.error("Error is:", npe);
lastDateAccensione = new Timestamp(lastDateAccensione.getTime());
}
Accensione accensione = new Accensione();
Date date = new Date();
logger.debug("lastDate:" + lastDateAccensione);
accensione.setDateTime(new Timestamp(date.getTime()));
accensione.setInterruttore(interruttore);
accensione.setIsLit(acceso);
accensione.setLastDateTime(lastDateAccensione);
logger.debug("Accensione è:"+accensione.toString());
accensioneService.saveAccensione(accensione);
}
public Pin getPin() {
return pin;
}
public void setPin(Pin pin) {
this.pin = pin;
}
public Interruttore getInterruttore() {
return interruttore;
}
public void setInterruttore(Interruttore interruttore) {
this.interruttore = interruttore;
}
public GpioPinDigitalOutput getRelePin() {
return relePin;
}
public void setRelePin(GpioPinDigitalOutput relePin) {
this.relePin = relePin;
}
public GpioController getGpio() {
return gpio;
}
public void setGpio(GpioController gpio) {
this.gpio = gpio;
}
}
When trying to call for updateAccensione, this is null.
Rele is created from a Controller, by this method
#RequestMapping(value="/illuminazione")
public ResponseEntity<Illuminazione> findIlluminazione(#RequestParam(value="idLuce") int idLuce,
#RequestParam(value="lit") boolean lit,
#RequestParam(value="suServer") boolean suServer) {
Illuminazione illuminazione = new Illuminazione();
Date lastDate = illuminazioneService.findLastDate(idLuce);
illuminazione.setLastDateTime(lastDate);
illuminazione.setIdLuce(idLuce);
illuminazione.setIsLit(lit);
Date date = new Date();
illuminazione.setDateTime(new Timestamp(date.getTime()));
illuminazioneService.saveIlluminazione(illuminazione);
logger.debug("Aggiornata luce " + idLuce + " accesa: "+lit);
//managing rele
if(suServer){
//check if status has changed
Luce luce = luceService.findById(idLuce);
int idInterruttore = luce.getInterruttore().getIdInterruttore();
Interruttore interruttore = interruttoreService.findById(idInterruttore);
Rele rele = releService.findByInterruttore(interruttore);
logger.debug("rele="+rele.toString());
if(lit){
rele.lightOn();
} else {
rele.lightOff();
}
}
return new ResponseEntity<Illuminazione>(illuminazione,HttpStatus.OK);
}
Rele is created, i find it in my logs.
AccensioneService is an interface, it's concrete implementation is AccensioneServiceImpl:
#Service("accensioneService")
#Transactional
public class AccensioneServiceImpl implements AccensioneService{
#Autowired AccensioneDao dao;
#Override
public void saveAccensione(Accensione accensione) {
dao.saveAccensione(accensione);
}
#Override
public Accensione findById(int id) {
return dao.findById(id);
}
#Override
public Date findLastDate(Interruttore interruttore) {
return dao.findLastDate(interruttore);
}
#Override
public boolean findLastStatus(int id) {
return dao.findLastStatus(id);
}
#Override
public void updateAccensione(Interruttore interruttore) {
}
}
I don't know if anything else is needed. AccensioneService is also called in other methods and controller, and it works... only when called inside Rele gives me this error...

Edited to add
You must be calling new Rele() or the other Rele(Pin, Interruttore ) constructor? If you are calling these in your code, the accensioneService will be null because Spring needs to create the bean, you cannot create it with its constructor if you want beans Autowired into it or for it to be Autowired. If you want it to behave like this, Spring has to know about it, so it has to be in (and come from) the Spring context.
Put a log statement in each constructor and find out who is calling them, and fix that so that instead of calling the constructor, you get the bean from Spring.
Old answer below
You need to post this method to be sure:
Rele rele = releService.findByInterruttore(interruttore);
I'll bet you are creating rele somewhere by calling new Rele(), which is not correct. You need to let Spring create it for you.
You did not post enough code to give further suggestions.
Also, you say this is null. What this are you talking about?

Related

Why do I get null values after injecting bean?

When I try to inject the packagePropertiesList Bean in Operation.class, I get values from a properties file. But when I use operation.removeStudentFromList(), I get only null values. Do you see any problem here?
values while injecting beans
#SpringBootApplication
public class LearningCenterApplication {
public static void main(String[] args) {
SpringApplication.run(LearningCenterApplication.class, args);
ApplicationContext context =
new AnnotationConfigApplicationContext(Config.class, Operations.class, PackageProperties.class);
Operations operations = context.getBean(Operations.class);
operations.removeStudentFromList();
}
#Bean
List<PackageProperties> packagePropertiesList(List<PackageProperties> packageProperties) {
System.out.println(packageProperties);
return packageProperties;
}
#Bean
#ConfigurationProperties(prefix = "remove")
public PackageProperties removeMethod() {
return new PackageProperties();
}
#Bean
#ConfigurationProperties(prefix = "add")
public PackageProperties addMethod() {
return new PackageProperties();
}
}
#Component
public class Operations {
private List<PackageProperties> packagePropertiesList;
#Autowired
public Operations(List<PackageProperties> packagePropertiesList) {
this.packagePropertiesList = packagePropertiesList;
}
public void removeStudentFromList() {
System.out.println(packagePropertiesList);
}
}
public class PackageProperties {
private String packageName;
private String className;
private String methodName;
public String getPackageName() {
return packageName;
}
public void setPackageName(String packageName) {
this.packageName = packageName;
}
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
public String getMethodName() {
return methodName;
}
public void setMethodName(String methodName) {
this.methodName = methodName;
}
#Override
public String toString() {
return packageName + "." + className + "." + methodName;
}
}
application.properties
remove.packageName = org.epam.operations
remove.className = Operations
remove.methodName = removeStudentFromList()
add.packageName = org.epam.operations
add.className = Operations
add.methodName = addStudent()
[null.null.null] — output when operations.removeStudentFromList() is invoked
You are creating an additional ApplicationContext next to the one that's already created by Spring Boot (with new AnnotationConfigApplicationContext(). Remove that and use the existing context to get a bean, or rather have a look at the ApplicationRunner interface, if you want to run code automatically after the application has started.
The whole property handling will only work for the application context, that's created and managed by Spring Boot, not for the one that you created yourself.

Spring Boot Abstract Singleton Service problem

Hi everyone this is my simple project code block
This service is renewing by sending a request once a day.
public class SingletonService {
private static final SingletonService INSTANCE = new SingletonService();
public static final int TIMEOUT_SEC = 86400 ;//SECONDS every day ONE REQUEST remote service
private static final Object lock = new Object();
private LocalDateTime queryDate;//Time
private EmployeeRepository employeeRepository;//My Remote Employee Repository
private List<Employee> list = new CopyOnWriteArrayList<>();
SingletonService() {//Singleton Design Pattern
}
public static SingletonService getInstance() {
return INSTANCE;
}
private boolean isTimeout() {//this methods check date
LocalDateTime execDate = LocalDateTime.now();
if (queryDate == null) {
return true;
}
LocalDateTime expireDate = queryDate.plusSeconds(TIMEOUT_SEC);
return expireDate.isBefore(execDate);
}
public synchronized void reload() {//this methods call repository employee list
queryDate = LocalDateTime.now();
list = employeeRepository.findAll();
}
public void initQuery() {//this methods check expire date and list size
synchronized(lock) {
if (isTimeout() || list.size() <= 0) {
reload();
}
}
}
public Integer countLatestRanking() {
return list.size();
}
public void setEmployeeRepository(EmployeeRepository employeeRepository) {
this.employeeRepository = employeeRepository;
}
public List<Employee> getList() {
return this.list;
}
public void setList(List<Employee> list) {
this.list = list;
}
}
My SingletonInitService
#Component
public class SingletonInitService {
#Autowired
private EmployeeRepository employeeRepository;
#PostConstruct
public void init() {
SingletonService.INSTANCE.setEmployeeRepository(employeeRepository);
}
public void onContextRefreshedEvent() {
SingletonService.INSTANCE.initQuery();
}
public List<Employee> getEmployees(){
return SingletonService.INSTANCE.getList();
}
}
My EmployeeService
#Service
public class EmployeeService {
#Autowired
private SingletonInitService singletonInitService;
public List<Employee> getEmployees(){
singletonInitService.onContextRefreshedEvent();
return singletonInitService.getEmployees();
}
}
My question is how can I write SingletonService abtract because I have too many repositories and I don't want to write this code over and over again (Please don't say why you didn't use the scheduler because it's not good to use job all the time)

Cannot persist in stateful session bean

I am making a shopping cart using a stateful session bean approach of Java EE Application. My plan is that after a user clicks on 'Checkout' button the order will be added to the database. However, the order is not updated in the database.
ShoppingCartFacade.java
#Stateful
public class ShoppingCartFacade implements ShoppingCartFacadeLocal {
#PersistenceContext(unitName = "DProject-ejbPU", type = PersistenceContextType.EXTENDED)
private EntityManager em;
private void create(Tickettable tickettable) {
em.persist(tickettable);
}
private ArrayList<Tickettable> ticketCart;
#PostConstruct
private void initializeBean(){
ticketCart = new ArrayList<>();
}
#Override
public boolean add(Tickettable tickettable) {
boolean result = false;
//Set the correct user and showtime table
tickettable.setUserid(this.getUsertableFrom(tickettable.getUserid().getUserid()));
tickettable.setShowtimeid(this.getShowtimetableFrom(tickettable.getShowtimeid().getShowtimeid()));
try {
//Already have ticket for this showtime
for (Tickettable ticket : ticketCart) {
if (ticket.getShowtimeid().getShowtimeid().equals(tickettable.getShowtimeid().getShowtimeid())) {
ticket.setQuantity(ticket.getQuantity() + tickettable.getQuantity());
result = true;
}
}
//New ticket
if (!result) {
ticketCart.add(tickettable);
result = true;
}
} catch (Exception ex) {
}
return result;
}
#Override
public ArrayList<Tickettable> getCart() {
return ticketCart;
}
#Override
public boolean checkOut() {
try {
for (Tickettable ticket : ticketCart) {
create(ticket);
}
ticketCart.clear();
return true;
} catch (Exception e) {
}
return false;
}
private Usertable getUsertableFrom(String userId) {
Usertable u = em.getReference(Usertable.class, userId);
return u;
}
private Showtimetable getShowtimetableFrom(String showtimeId) {
Showtimetable s = em.getReference(Showtimetable.class, showtimeId);
return s;
}
#Remove
public void remove() {
ticketCart = null;
}
}
ShoppingCartManagement.java
#Stateful
public class ShoppingCartManagement implements ShoppingCartManagementRemote {
#EJB
private ShoppingCartFacadeLocal shoppingCartFacade;
#Override
#PermitAll
public boolean add(TicketDTO ticketDTO) {
if (ticketDTO == null) {
// just in case
return false;
}
// convert to entity
Tickettable ticket = Utility.ticketDTO2Entity(ticketDTO);
// add one
return shoppingCartFacade.add(ticket);
}
#Override
#PermitAll
public ArrayList<TicketDTO> getCart() {
try {
ArrayList<Tickettable> alst = shoppingCartFacade.getCart();
if (alst.isEmpty()) {
//not found
return null;
} else {
ArrayList<TicketDTO> alsDTO = new ArrayList<>(alst.size());
for (Tickettable stt : alst) {
TicketDTO stDTO = Utility.ticketEntity2DTO(stt);
alsDTO.add(stDTO);
}
return alsDTO;
}
} catch (NullPointerException e) {
throw e;
}
}
#Override
#PermitAll
public boolean checkOut() {
return shoppingCartFacade.checkOut();
}
}
ShoppingCartManagedBean.java in War
#Named(value = "shoppingCartManagedBean")
#RequestScoped
public class ShoppingCartManagedBean implements Serializable{
.....
#EJB
private ShoppingCartManagementRemote shoppingCartManagement;
public String addTicket(){
this.quantity += 1;
UserDTO u = new UserDTO(userId,"","","","","");
ShowtimeDTO s = new ShowtimeDTO(showtimeId,"","","","","");
TicketDTO t = new TicketDTO("111111",u,s,Integer.toString(this.quantity));
//carts = shoppingCartManagement.getCart();
boolean result = shoppingCartManagement.add(t);
if(result){
return "success";
}
return "failure";
}
public String checkout(){
/*return shoppingCartManagement.checkOut();*/
boolean result = shoppingCartManagement.checkOut();
if(result) return "success";
return "failure";
}
}
*********************** UPDATE **********************
I just made the test. The cartList in ShoppingCartFacade.java is empty.
You need to be aware of the lifecycle management of the various beans that you're using.
#Stateful beans are not implicitly associated with the servlet/JSF session.
A new instance of ShoppingCartManagedBean will be created for each incoming request as it is #RequestScoped. This instance will automatically get a reference to a new instance of ShoppingCartManagement which will in turn get a reference to a new instance of ShoppingCartFacade.
You need to either:
Change ShoppingCartManagedBean to be #SessionScoped, or
Create an #SessionScoped facade which delegates to the ShoppingCartManagement reference and inject that in place of the EJB.
Either of these methods will associate your stateful session bean with the servlet/JSF session.

How to update code from Jmockit 1.1 to 1.9 to Access Real Instance?

I am trying to update code from Jmockit 1.1 to 1.9 to Access Real Instance, But it seems to be unsuccessful as below:
java.lang.IllegalArgumentException: Matching real methods not found for the following mocks:
CopyOfAccessRealInstanceTest$1#getRealInstanceName(String m, mockit.Invocation inv)
at CopyOfAccessRealInstanceTest$1.<init>(CopyOfAccessRealInstanceTest.java:28)
at CopyOfAccessRealInstanceTest.mockConstructor(CopyOfAccessRealInstanceTest.java:28)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
I think it is due to mock method:
#Mock(invocations = 1)
public String getRealInstanceName(String m,Invocation inv)
-------------------------Codes 1.9---------------------------------
public class CopyOfAccessRealInstanceTest {
private Constructor constructor = new Constructor("");
#Test
public void mockConstructor() {
// Mockit.setUpMock(Constructor.class, new MockedConstructor());
MockUp<Constructor> mockup = new MockUp<Constructor>() {
//public Constructor it;
#Mock(invocations = 1)
public String getRealInstanceName(String m,Invocation inv)
{
if ("real".equals(m)) {
return inv.proceed(inv.getInvokedArguments());
// return it.getRealInstanceName(m);
} else {
return "mock";
}
}
};
Assert.assertEquals("mock",
constructor.getRealInstanceName(""));
Assert.assertEquals("real_m_real",
constructor.getRealInstanceName("real"));
}
}
-----------------------Code of Jmock 1.1--------------------------------
public class AccessRealInstanceTest {
private Constructor constructor = new Constructor("");
#Test
public void mockConstructor() {
Mockit.setUpMock(Constructor.class, new MockedConstructor());
Assert.assertEquals("real_m_real",
constructor.getRealInstanceName("real"));
}
public static class MockedConstructor {
public Constructor it;
#Mock(reentrant = true)//reentrant allow to access real instance
public String getRealInstanceName(String m) {
if ("real".equals(m)) {
return it.getRealInstanceName(m);
} else {
return "mock";
}
}
}
}
Class to be Mocked:
public class Constructor {
private String memberId;
public Constructor(String memberId) {
this.memberId = memberId;
}
public String getRealName() {
return "real_" + this.memberId;
}
public String getRealInstanceName(String m) {
return "real_m_" + m;
}
}
It is resolved. Thank you for Rogério and Sean!
Note the API documentation says that an Invocation parameter must be the first parameter in the mock method. – Rogério

Hibernate is saving a completely new entity automatically(full stack of calls)

I have already asked this question two times, but I'm new to stackoverflow and it seems that I don't know the rules for formatting my example code in here. Now I've decided to give the full stack of the calls and I hope I can explain the situation because everything is so strange and I can't find the words to describe it. First I will give you the source of the classes that have something to do with the problem. My actual question is in the end of the page. The large piece of code is just in case, because I don't know what could be the explanation of my problem.
Here is a service facade that gets calls from my flex application.
public class ServiceFacade implements IAuthenticationService, IProfileService, ICampaignService {
#Autowired
private IAuthenticationService authenticationService;
#Autowired
private IProfileService profileService;
#Autowired
private ICampaignService campaignService;
public void login(User user) throws AuthenticationException{
authenticationService.login(user);
}
#Override
public void logout() throws AuthenticationException {
authenticationService.logout();
}
#Override
public void sendForgottenPassword(String email) {
authenticationService.sendForgottenPassword(email);
}
#Override
public Profile getProfile(Long userId) {
return profileService.getProfile(userId);
}
#Override
public Profile updateProfile(Profile profile) {
return profileService.updateProfile(profile);
}
#Override
public Collection<String> getSocialConnectionsTypes(Long userId) {
return profileService.getSocialConnectionsTypes(userId);
}
#Override
public List<Email> findDuplicateEmails(Long profileId, List<Email> emails) {
return profileService.findDuplicateEmails(profileId, emails);
}
#Override
public Campaign getCampaign(Long campaignId) {
return campaignService.getCampaign(campaignId);
}
#Override
public Campaign updateCampaign(Campaign campaign) {
return campaignService.updateCampaign(campaign);
}
#Override
public void removeCampaign(Long campaignId) {
campaignService.removeCampaign(campaignId);
}
#Override
public void setPools(Long campaignId, Collection<Pool> pools) {
campaignService.setPools(campaignId, pools);
}
#Override
public void addPool(Long campaignId, Pool pool) {
campaignService.addPool(campaignId, pool);
}
#Override
public void removePool(Long campaignId, Pool pool) {
campaignService.removePool(campaignId, pool);
}
#Override
public List<Campaign> getCampaigns() {
return campaignService.getCampaigns();
}
#Override
public void updatePool(Long campaignId, Pool pool) {
campaignService.updatePool(campaignId, pool);
}
}
The method which is important for my question is the findDuplicateEmails method.
The profileService is implemented in the following class:
public class ProfileService implements IProfileService {
#Autowired
private IProfileManager profileManager;
#Override
public Profile getProfile(Long userId) {
return profileManager.getProfile(userId);
}
#Override
public Profile updateProfile(Profile profile){
profileManager.updateProfile(profile);
return profile;
}
#Override
public Collection<String> getSocialConnectionsTypes(Long userId) {
return profileManager.getSocialConnectionsTypes(userId);
}
#Override
public List<Email> findDuplicateEmails(Long profileId, List<Email> emails) {
return profileManager.findDuplicateEmails(profileId, emails);
}
}
Again the important method is findDuplicateEmails
The implementation of the profileManager is the following class:
public class ProfileManager implements IProfileManager {
#Autowired
private IProfileDao profileDao;
#Autowired
private ISectionManager autoCompleteManager;
#Autowired
private IUserSecurityService userSecurityService;
#Transactional
public Profile getProfile(Long userId) {
return profileDao.getProfileByUser(userId);
}
#Transactional
public void updateProfile(final Profile profile) {
List<Major> notApprovedMajors = extractNotApprovedMajors(profile);
List<Degree> notApprovedDegrees = extractNotApprovedDegrees(profile);
List<School> notApprovedSchools = extractNotApprovedSchools(profile);
List<Language> notApprovedLanguages = extractNotApprovedLanguages(profile);
List<Position> notApprovedPositions = extractNotApprovedPositions(profile);
List<Company> notApprovedCompanies = extractNotApprovedCompanies(profile);
List<Country> notApprovedCountries = extractNotApprovedCountries(profile);
List<City> notApprovedCities = extractNotApprovedCities(profile);
List<Certificate> notApprovedCertificates = extractNotApprovedCertificates(profile);
autoCompleteManager.updateAll(notApprovedMajors);
autoCompleteManager.updateAll(notApprovedDegrees);
autoCompleteManager.updateAll(notApprovedSchools);
autoCompleteManager.updateAll(notApprovedLanguages);
autoCompleteManager.updateAll(notApprovedPositions);
autoCompleteManager.updateAll(notApprovedCompanies);
autoCompleteManager.updateAll(notApprovedCountries);
autoCompleteManager.updateAll(notApprovedCities);
autoCompleteManager.updateAll(notApprovedCertificates);
profileDao.updateProfile(profile);
}
#Override
public List<Email> findDuplicateEmails(Long profileId, List<Email> emails) {
Profile persistedProfile = profileDao.findById(profileId);
if (persistedProfile.getContact() == null)
{
persistedProfile.setContact(new Contact());
}
List<Email> resultEmails = new ArrayList<Email>();
for (int i = 0; i < emails.size(); i++) {
if ((!userSecurityService.guaranteeUniquePrincipal(emails.get(i)) &&
!isPersistedInThePersistentCollection(emails.get(i), persistedProfile.getContact().getEmails())) ||
isDuplicateInTheCurrentCollection(emails.get(i), emails, i + 1)) {
resultEmails.add(emails.get(i));
}
}
return resultEmails;
}
private boolean isDuplicateInTheCurrentCollection(Email emailToCheck, List<Email> emails, int index)
{
for (int i = index ; i < emails.size(); i ++) {
if (emails.get(i).getEmailAddress().equals(emailToCheck.getEmailAddress())) {
return true;
}
}
return false;
}
private boolean isPersistedInThePersistentCollection(Email emailToCheck, Collection<Email> emails)
{
if (emails == null) {
return false;
}
for (Email persistedEmail : emails) {
if (persistedEmail.getEmailAddress().equalsIgnoreCase(emailToCheck.getEmailAddress())) {
return true;
}
}
return false;
}
}
Again the important method is the method findDuplicateEmails
Now, after this short background, here is my problem:
I am using Hibernate with spring's HibernateTemplate. I found out that in the method findDuplicateEmails, some completely new entities which come form the flex application gets saved automatically. This was very strange and during the debbugging I found out that even if I change the method findDuplicateEmails in the ProfileManager so it looks like:
#Override
public List<Email> findDuplicateEmails(Long profileId, List<Email> emails) {
Email email = new Email();
return null;
}
the entity email gets saved automatically. I also found out that if the identifier of the entity is not "email", but something else, like "newEmail", or "email1", or something, there is no problem and the entity gets persisted if and only if I make it persistent. This problem exists only in this class and finally, this problem shows up only for the Email. I mean that if I have Phone phone = new Phone(); the entity phone gets persisted only when I wish.
The flex application first checks that the entered from the user emails are unique, and then after some user interaction calls the method updateProfile() if the entered data is valid.
I would download Hibernate sources and start debugging, you will either find a bug in Hibernate (happens) or in your code, as this is one weird behavior.
This is an advice I got once, and was the fastest, most educating way to get to the root.

Categories

Resources