Reading data from a sql database with spring data fails - java

I'm having a database with existing tables. One of these is called AKTIVE_AUFTRAEGE with the id "AKTIVE_AUFTRAGE_ID" and the second field "ROBOTER_AUFTRAG_ID". I want to read the data using Spring data. I followed some tutorials an my code looks like this:
spring.jpa.hibernate.ddl-auto=none
spring.datasource.url=jdbc:sqlserver://****;databaseName=****;schema=dbo
spring.datasource.username=****
spring.datasource.password=****
spring.datasource.driverClassName=com.microsoft.sqlserver.jdbc.SQLServerDriver
spring.jpa.show-sql=true
spring.jpa.hibernate.dialect=org.hibernate.dialect.SQLServer2012Dialect
spring.jpa.hibernate.naming.implicit-strategy=org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
and
package hello;
import javax.persistence.*;
#Entity
#Table(name = "AKTIVE_AUFTRAEGE")
public class AktiveAuftraege {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name="AKTIVE_AUFTRAEGE_ID")
private Integer auftragID;
private Integer ROBOTER_AUFTRAG_ID;
... getter and setter
}
and
package hello;
import org.springframework.data.repository.CrudRepository;
public interface AuftraegeRepsository extends CrudRepository<AktiveAuftraege, Integer> {
AktiveAuftraege findByauftragID(Integer aktive_auftraege_id);
}
and
package hello;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
#Controller
public class Test {
#Autowired
private AuftraegeRepsository auftraegeRepsository;
public void testAll(){
if (auftraegeRepsository != null) {
Iterable<AktiveAuftraege> results = auftraegeRepsository.findAll();
for (AktiveAuftraege e : results) {
System.out.println(e);
}
} else {
System.out.println("ISNULL!");
}
}
}
and the main
package hello;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
Test t = new Test();
t.testAll();
}
}
I'm very new to Spring data and have a couple of questions:
How can I check if the application has a connection to the database?
Why is the autowired repository always null?
I assume the problem mentioned problem is caused in the application class with the new operator. How can I avoid this? (Or is this fine?)
Do I need to implement all variables of a table in a class or can I just implement the ones I want to get back and igore the other columns?

How can I check if the application has a connection to the database?
If the application starts up correctly, it means you have a connection to the database
Why is the autowired repository always null?
Because you instantiate the Test class yourself, and Spring is thus out of the equation, and thus doesn't inject anything in the object you created behind its back, since it doesn't even know about it.
How can I avoid this?
By getting it from the ApplicationContext returned by SpringApplication.run(), or by creating a bean of type CommandLineRunner and injecting the Test inside it. Check the Spring Boot documentation.
Do I need to implement all variables of a table in a class or can I just implement the ones I want to get back and igore the other columns?
If you just want to read from that table, having only a subset of the columns is fine. But if you want to insert data in it, the other columns will be ignored, and will thus always have their default value (or null if there is no default value).

Related

Type mismatch: cannot convert from Object to AccountDAO

Hello im doing a simple spring application and for some reason this error came up:
Type mismatch: cannot convert from Object to AccountDAO
I have 3 classes, AccountDao:
package com.luv2code.aopdemo.dao;
import org.springframework.stereotype.Component;
#Component
public class AccountDAO {
public void addAccount() {
System.out.println(getClass() + ": DOING MY DB WORK: ADDING AN ACCOUNT");
}
}
DemoConfig:
package com.luv2code.aopdemo;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
#Configuration
#EnableAspectJAutoProxy
#ComponentScan("com.luv2code.aopdemo")
public class DemoConfig {
}
And MainDemoApp:
package com.luv2code.aopdemo;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.luv2code.aopdemo.dao.AccountDAO;
public class MainDemoApp {
public static void main(String[] args) {
//read spring config java class
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(DemoConfig.class);
//get the bean from spring container
AccountDAO theAccountDAO = context.getBean("accountDAO", AccountDAO.class); //THE PROBLE IS HERE
//call the business method
theAccountDAO.addAccount();
//close the context
context.close();
}
}
The error is in the MainDemoApp at AccountDAO theAccountDAO = context.getBean("accountDAO", AccountDAO.class);
(only the part after = is red)
Can you try this:
AccountDAO theAccountDAO = (AccountDAO) context.getBean("accountDAO", AccountDAO.class);
Try context.refresh() before context.getBean(...)call, if it does not help do following:
Annotate MainDemoApp.java with #SpringBootApplication.
Remove #ComponentScan from DemoConfig and create the #Bean explicitly.
Start in debug mode and see if hits bean creation for AccountDAO.
I kept trying to remove (and readd if nothing changed) one library from buildpath, one by one, just to try even if i dont know what effect would have. After removing org.springframework.context.jar the error disappeared.
just lol. anyone could explain please?

Spring Boot #Autowired object - Nullpointer Exception [duplicate]

This question already has answers here:
Why is my Spring #Autowired field null?
(21 answers)
Closed 3 years ago.
I am developing a spring boot application to send sms notification. This is my class for the purpose.
package org.otp.services;
import org.otp.Configurations;
import com.mashape.unirest.http.HttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.annotation.PropertySources;
#Component
public class SmsService
{
private static final Logger LOG = LoggerFactory.getLogger(SmsService.class);
public String send(String mobile, String msg)
{
//Code
}
}
And this is the class which uses the above class for sending notification.
package org.otp.controllers;
import org.otp.Constants;
import org.otp.services.EmailService;
import org.otp.services.SmsService;
import org.otp.dto.MessageRequest;
import org.otp.dto.MessageResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestBody;
#Component
public class MessageController {
private static final Logger LOG = LoggerFactory.getLogger(MessageController.class);
#Autowired
SmsService smsService;
public void sendMessageToAlert(#RequestBody MessageRequest messageRequest)
{
String smsStatus = "FAIL";
MessageResponse messageResponse = new MessageResponse();
//1. Nullpointer
smsStatus = smsService.send(messageRequest.getMobileNo(),messageRequest.getMessage());
}
}
Main Class
package org.otp;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;
#SpringBootApplication
#EnableAsync
public class OtpServiceApplication implements ApplicationRunner
{
public static void main(String[] args) {
SpringApplication.run(OtpServiceApplication.class, args);
}
}
Problem is, I get a nullpointer exception in the (1) stating that my SmsService object is null. And my main class is in package org.otp so the two classes here falls under sub package so no need of component scan.
Therefore I am confused what to do to solve this. I have tried many answers here like adding a #Component annotation and #ComponentScan in main class but nothing works. Could someone please point out my mistake here.
Thanks in advance.
If your #Autowired annotation is not working and throws NPE ,it means that spring fails to create an instance of the component class in the application context . Try to:
Verify that the classes are in class path for scanning and also check to ensure that all auto-wired classes have the annotation #Component to enable them to be picked up during class path scanning.
Check the spring boot start up logs to verify if there are any errors
during bean creation.
Check to ensure all related classes used in the service layer are auto-wired properly and that the injected classes are annotated with #Component .
For further help please share the main application class along with your project structure.
Since you are using springboot , it is preferable to use the sprinboot stereotype annotations instead of the #Component annotation, if you are building a standard springboot web application.
#Service : for the service layer.
#Controller : for the controller layer . Also,DispatcherServlet will look for #RequestMapping on classes which are annotated using #Controller but not with #Component.
In Springboot application's main class add following annotation
#SpringBootApplication
#ComponentScan(
basePackages = {"org.otp.*"}
)
public class YourSpringMainClass{
public static void main(String[] args) {
SpringApplication.run(YourSpringMainClass.class, args);
}
}
While using annotations we should configured with #ComponentScan annotation to tell Spring the packages to scan for annotated components. This should be used in mail class(Which class wants to load first) in your case you are working with spring boot so you should use this annotation in Springboot application's main class. Like below
#SpringBootApplication
#ComponentScan(
basePackages = {"org.otp.*"}
)
public class YourSpringMainClass{
public static void main(String[] args) {
SpringApplication.run(YourSpringMainClass.class, args);
}
}

What is the table name?

I am creating a Spring Boot application using the H2 database. I am constantly getting the following error:
Table "THINGS_TO_DO" not found; SQL statement:
insert into things_to_do (id, name, verified) values (1, 'TestUser1', 1) [42102-197]
And, I feel this is logical since I don't know where to pass this table name in the application. Also, what should the table name be - is there some specific name that the table must have?
My ThingsToDo.java is like below:
package me.hiboy.springboot.microservice.example.todo;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
#Entity
#Table(name="things_to_do")
public class ThingsToDo {
#Id
private Long id;
#Column(name="name")
private String name;
#Column(name="verified")
private int verificationStatus;
private String task;
public ThingsToDo() {
}
public ThingsToDo(Long id, String name, int verificationStatus, String task) {
super();
this.id=id;
this.name=name;
this.verificationStatus=verificationStatus;
this.task=task;
}
public Long getId() {
return id;
}
public String getName() {
return name;
}
public int getVerificationStatus() {
return verificationStatus;
}
public String getTask() {
return task;
}
}
The controller ThingsToDoController.java is as follows:
package me.hiboy.springboot.microservice.example.todo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
#RestController
public class ThingsToDoController {
#Autowired
ThingsToDoRepository repository;
#GetMapping("/")
public String index() {
return "Hello from the ToDo Controller\n";
}
#GetMapping("/todo/{name}")
public ThingsToDo getThingsToDo(#PathVariable String name) {
ThingsToDo thingToDo=repository.findByName(name);
return thingToDo;
}
}
Repository ThingsToDoRepository is:
package me.hiboy.springboot.microservice.example.todo;
import org.springframework.data.jpa.repository.JpaRepository;
public interface ThingsToDoRepository extends JpaRepository<ThingsToDo, Long> {
ThingsToDo findByName(String name);
}
Application.properties is:
spring.application.name=todo-service
server.port=8080
spring.jpa.show-sql=true
spring.h2.console.enabled=true
spring.datasource.url=jdbc:h2:mem:mydb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
spring.datasource.username=sa
spring.datasource.password=
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.platform=h2
spring.datasource.initialize=true
data.sql is:
insert into things_to_do (id, name, verified) values (1, 'TestUser1', 1);
insert into things_to_do (id, name, verified) values (2, 'TestUser2', 0);
I don't think pom.xml is required - in case it is, kindly lemme know and I will post that as well. Thanks.
Edit:
The one with the main() method is here:
package me.hiboy.springboot.microservice.example.todo.springbootmicroservicetodoservice;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class SpringBootMicroserviceTodoServiceApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootMicroserviceTodoServiceApplication.class, args);
}
}
Edit: All the answers given so far do not help at all.
Follow the package name as
If your main class is in the com.example package
then all packages in your application will be following this package
as for new entity, the package will be
com.example.entity
You need to use proper package names as I can see you Application class and other classes do not follow the package naming convention.
Plus If I just want to insert simple test data I often implement a ApplicationRunner. Implementations of this interface are run at application startup and can use e.g. a autowired repository to insert some test data.
Your implementation would look like this:
#Component
public class DataLoader implements ApplicationRunner {
#Autowired
ThingsToDoRepository repository;
#Autowired
public DataLoader(ThingsToDoRepository repository) {
this.repository = repository;
}
public void run(ApplicationArguments args) {
repository.save(new ThingsToDo(1, 'TestUser1', 1));
repository.save(new ThingsToDo(2, 'TestUser2', 0));
}
}
You are getting this error because there is no table with such name.
You could try to add spring.jpa.hibernate.ddl-auto=create-drop to your .properties file. Then each time you run your app it should generate that table using your entity.
Or you need to create a table with name things_to_do manually and then when you run your app it should work. For this, you need to add
/src/main/resources/schema.sql
create table things_to_do
(
id integer not null,
/*all the rest columns */
);
Another thing is that for Spring to find your components (like repository or service etc.) it scans packages. And auto-configs scan the package where your main class is located and all the nested packages.
So if you don't want to set manually where your classes are located, you need to follow this structure!
Example:
my.main.package // here is your main class
my.main.package.entities // here are your entities
my.main.package.repositories // your repos
my.main.package.services // services
This is just an example, it does not mean you should provide the same names, just follow the convention. Hope it is clear what I mean by package structure :)
Usually, you would refer to your table by its entity name, not the actual table name. In this case it would be ThingsToDo.
But in this particular case, you're overriding this by giving your entity another name:
#Entity
#Table(name="things_to_do")
public class ThingsToDo {
That's why you should work with "things_to_do" in your query, or remove the name statement.

testing HQL query on hbm2dll with Junit

How can I test HQL query with JUnit tests?
I have mapped Entity Class:
#Entity
#Table(name = "DOE")
public DomainObjectEntity {
//some attributes
}
which represents domain objects:
public class DomainObject {
//some attributes
}
I also have repository interface for my domain objects:
public interface DomainObjectRepository {
/**
* Gets entity by some attribute
*
*/
DomainObject getDomainObjectByObjectId(String objectId);
}
this interface is implemented in
#Repository
public class DomainObjectRepositoryImpl implements DomainObjectRepository {
#Inject
private DomainObjectEntityJPARepository entityRepository;
#Override
public DomainObjectgetDomainObjectById(String parcelId) {
//this converts my entity to domain object
return entityRepository.findByDomainObjectId(DomainObjectId.getStr()).getDomainObject();
}
}
my JPA Entity repository looks like this:
public interface DomainObjectEntityJPARepository extends JpaRepository<DomainObjectEntity, String> {
/**
* get DomainObject with requested id
*
* #param objectId - objects id
* #return DomainObject
*/
#Query("some query to be tested")
DomainObjectEntity findByDomainObjectId(#Param("objectId") String objectId);
}
and finally i want to write a simple JUnit test to check if query to findByDomainObjectId returns the correct object. I think my test should look like this:
create test object to put into DB
retrieve object from DB
compare objects
i have setted up a hbm2dll with import.sql to create and populate my DB but how can i access it from Junit test by calling method findByDomainObjectId?
Unit vs integration
First of all there is one thing you need to ask:
Do you want an Unit test or an Integration test
An unit test is fast (ie, milliseconds) to run and is, well, unitary - meaning it doesn't touch the database.
An integration test is heavier and, in case of a database test, will touch the db.
While it is usually preferable to create unit tests, in your case it seems you want an integration test - you actually want to test the call to the database and check if the query does what you think it does.
When to load data
I would suggest that in your integration test you don't preload data with import.sql (or at least think very carefully if this is what you want). The reason for this is that, as your test suite grows, you'll need the database in one state for test A, another state for test B, and so on, and you'll quickly end up in a situation where you'll have incompatible states.
You'll also end up with slower tests if you load too much data via SQL.
My advise would be: try to create/manipulate the data in your test.
How to test
How to test it depends on how you load your hibernate in production. Judging by the code you've shown, I believe you might be using a Dependency injection mechanism to start up hibernate's EntityManager (or SessionFactory), like Spring.
If this is the case, you can use spring to configure you integration test.
The main suggestions here would be:
Use rollback so that data is not stored between tests (guarantees test independence)
As your test suite grows, create an abstract class that holds the configuration and, e.g, exposes the EntityManager/sessionFactory. All your integration tests just need to extend this class, have the repository injected (in your example, inject DomainObjectRepositoryImpl into the test) and run the method you need to test.
Below is a very simple abstract test I have (in my case I'm using a SessionFactory):
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.transaction.TransactionConfiguration;
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations={
"/spring-SF-tests.xml",
"/spring-transaction.xml"
})
#TransactionConfiguration(transactionManager="txManager", defaultRollback=true)
public abstract class HibernateAbstractTest extends AbstractTransactionalJUnit4SpringContextTests {
#Autowired
protected SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sessionFactory){
this.sessionFactory = sessionFactory;
}
public Session getSession(){
return sessionFactory.getCurrentSession();
}
public void save(Object object){
getSession().save(object);
}
public void update(Object object){
getSession().update(object);
}
}
Since I wanted to test only query, proper solution was to #autowire JPArepository and then in setup, populate it with data, this way tests were bound only with DB structure and not the data inside
public class EntityObjectJPARepositoryTest {
#Autowired
DomainObjectEntityJPARepository domainObjectRepo;
DomainObjectEntity entity;
#Before
public void Setup(){
entity = new DomainObjectEntity ()
//setup entity
domainObjectRepo.save(entity);
}
#Test
public void testfindByDomainObjectId(){
DomainObjectEntity res = domainObjectRepo.findByDomainObjectId(objectid);
Assert.assertEquals(entity.getId(), res.getId());
}
//everything else
}

Mocking CGLIB enhanced objects

Is it true that mockito can't mock objects that were already enhanced by CGLIB?
public class Article {
#Autowired
private dbRequestHandler
#Autowired
private filesystemRequestHandler
#Transactional
public ArticleDTO getArticleContents() {
//extractText() and then save the data in DTO
//extractImages() and then save the data in DTO
// some other calls to other databases to save data in dto
return articleDTO;
}
public void extractText() {
//call to DB
}
public void extractImages() {
// call to file system
}
}
public class IntegrationTest {
#Autowired
private Article article;
//setup method {
articleMock = Mockito.spy(article);
doNothing().when(articleMock).extractImages();
}
}
In the above example when it comes to doNothing().when(articleMock).extractImages(); it actually calls the real function. On a closer look articleMock gets enhanced two times. One cause of autowiring and second time cause of spying.
If I can't spy on enhaced objects, then how can I test the getArticle() method in my Integration test, so that I can verify a proper DTO is returned.
Note : I actually don't want to test the method which does filesystem calls. just the DB ones. thats why I need to test the getArticle method.
If I understand correctly your class is wired by Spring. Spring uses CGLIB to ensure transactional behaviour only if there is no interface, which is implemented by your object. If there is an interface, it uses simple JDK Dynamic Proxies. (see http://docs.spring.io/spring/docs/3.0.0.M3/reference/html/ch08s06.html)
Maybe you could try to extract an interface, and let Spring to use dynamic proxies. Maybe then Mockito could perform better.
If you run as a true unit test and not as an integration test, you need not run in a container having Spring autowire for you. In one of your comments, I think you alluded to trying this, and you noted that there was an endless set of chained object references which you would have to provide as well. But there is a way around that. Mockito provides some predefined Answer classes that you can initialize your mock with. You may want to look at RETURNS_DEEP_STUBS, which will possibly get you around this problem.
Will you please update your question with ready-to-go compilable code. Here's some code review suggestions:
Issues with this question code:
Article.java missing import: org.springframework.beans.factory.annotation.Autowired
Article.java missing import: org.springframework.transaction.annotation.Transactional
Article.java attribute syntax issue: dbRequestHandler
Article.java attribute syntax issue: filesystemRequestHandler
Article.java method has no initialized return statement: articleDTO
Here's what you maybe should use as you questionCode with the above issues fixed:
Article.java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
public class Article {
#Autowired
private Object dbRequestHandler;
#Autowired
private Object filesystemRequestHandler;
#Transactional
public ArticleDTO getArticleContents() {
// extractText() and then save the data in DTO
// extractImages() and then save the data in DTO
// some other calls to other databases to save data in dto
ArticleDTO articleDTO = null;
return articleDTO;
}
public void extractText() {
// call to DB
}
public void extractImages() {
// call to file system
}
}
IntegrationTest.java is a poor name for a testClass because it's to generic. I would suggest ArticleTest for a java unit test.
ArticleTest.java
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.springframework.beans.factory.annotation.Autowired;
#RunWith(PowerMockRunner.class)
#PrepareForTest(ClassWithPrivate.class)
public class ArticleTest {
#InjectMocks
private Article cut;
#Mock
private Object dbRequestHandler;
#Mock
private Object filesystemRequestHandler;
#Test
public void testeExtractImages() {
/* Initialization */
Article articleMock = Mockito.spy(cut);
/* Mock Setup */
Mockito.doNothing().when(articleMock).extractImages();
/* Test Method */
ArticleDTO result = cut.getArticleContents();
/* Asserts */
Assert.assertNull(result);
}
}
You can utilize AdditionalAnswers.delegatesTo method. In following example, the secondProxyDoingMocking declaration creates something like a spy (compare with implementation of spy() method) except it uses "lightweight" method delegation.
import org.mockito.AdditionalAnswers;
public class ArticleTest {
#Autowired
private Article firstProxyDoingAutowiring;
#Test
public void testExtractImages() {
Article secondProxyDoingMocking = Mockito.mock(Article.class,
Mockito.withSettings().defaultAnswer(
AdditionalAnswers.delegatesTo(firstProxyDoingAutowiring)
)
);
Mockito.doNothing().when(secondProxyDoingMocking).extractImages();
...
}
}
I didn't test this example, however I assembled it from my working code. My use case was similar: return constant value for given method, call real method for all remaining methods of Spring #Transactional-annotated bean.

Categories