Spring Boot Data Jpa - entityManager is null - java

I switched from jakarta to javax and started getting this error; (i have to use javax);
I don't understand why it worked before and now it cant inject EntityManager
it my first question here, sorry for mistakes
application.yaml:
spring:
jpa:
hibernate:
ddl-auto: update
datasource:
driver-class-name: org.postgresql.Driver
url: jdbc:postgresql://localhost:5432/stage3_module3
username: postgres
password: root
#SpringBootApplication
public class NewsManagementApplication {
public static void main(String[] args) {
ApplicationContext context = SpringApplication.run(NewsManagementApplication.class, args);
NewsManagementMenu menu = context.getBean(NewsManagementMenu.class);
menu.setScanner(new Scanner(System.in));
menu.runMenu();
}
}
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import java.util.List;
import java.util.Optional;
#Repository
public class NewsRepository implements BaseRepository<NewsModel, Long> {
#PersistenceContext
private EntityManager entityManager;
#Override
#SuppressWarnings("unchecked")
public List<NewsModel> readAll() {
return entityManager.createQuery("select n from NewsModel n").getResultList();
}
#Override
public Optional<NewsModel> readById(Long id) {
return Optional.ofNullable(entityManager.find(NewsModel.class, id));
}
#Transactional
#Override
public NewsModel create(NewsModel entity) {
entityManager.persist(entity);
return entity;
}
#Transactional
#Override
public NewsModel update(NewsModel entity) {
Optional<NewsModel> maybeNull = readById(entity.getId());
if (maybeNull.isEmpty()) {
return null;
}
NewsModel toUpdate = maybeNull.get();
toUpdate.setTitle(entity.getTitle());
toUpdate.setContent(entity.getContent());
toUpdate.setLastUpdateDate(entity.getLastUpdateDate());
toUpdate.setAuthor(entity.getAuthor());
toUpdate.setTags(entity.getTags());
return toUpdate;
}
#Transactional
#Override
public boolean deleteById(Long id) {
return entityManager.createQuery("delete from NewsModel n where n.id=:id")
.setParameter("id", id)
.executeUpdate() != 0;
}
#Override
public boolean existById(Long id) {
return readById(id).isPresent();
}
}
dependencies {
implementation "org.springframework:spring-context:$springVersion"
testImplementation "org.springframework:spring-test:$springVersion"
testImplementation "org.junit.jupiter:junit-jupiter-api:$jupiterVersion"
testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:$jupiterVersion"
testImplementation "com.tngtech.archunit:archunit-junit5:$archUnitVersion"
implementation 'org.springframework.boot:spring-boot-starter-data-jpa:3.0.2'
implementation 'org.postgresql:postgresql:42.5.2'
testImplementation 'org.mockito:mockito-core:5.1.1'
testImplementation 'org.mockito:mockito-junit-jupiter:5.1.1'
implementation 'javax.persistence:persistence-api:1.0'
}
it gives me:
Cannot invoke "javax.persistence.EntityManager.createQuery(String)" because "this.entityManager" is null
update: problem solved
I changed version of spring-boot-starter-data-jpa to 2.7.7 and
add this dependency: 'javax.xml.bind:jaxb-api:2.3.1'

The only thing I can think of is that #PersistenceContextannotation is not properly configured -> means that the entityManager instance variable is not being properly initialized or injected.
Try to see if the answer from this post helps: java.lang.NullPointerException: Cannot invoke "javax.persistence.EntityManager error in Spring MVC while pulling data

problem was solved
I changed version of spring-boot-starter-data-jpa to 2.7.7 and add this dependency: 'javax.xml.bind:jaxb-api:2.3.1'

Related

Spring Boot Data Rest does not recognize RepositoryRestResource with disableDefaultExposure()

I know there are a lot of similar issues here on stackoverflow, but none of this fixes my issue.
I want to expose some methods from my Spring Boot Repositories as Webservice, but one Repository randomly ^(1) only returns 404 on all Methods.
We are talking about following classes
#Component
public class CustomRepositoryRestConfigurer implements RepositoryRestConfigurer {
#Override
public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config, CorsRegistry cors) {
config.disableDefaultExposure();
}
}
#RepositoryRestResource(exported = true)
public interface TransactionRepository extends JpaRepository<Transaction, Long> {
#Query("select t from Transaction where ....")
#RestResource(exported = true) // true is default
Page<Transaction> findAllByQuery(
// more stuff
#Param("text") String text,
Pageable pageable);
void delete(Transaction entity); // should not be exposed!
}
And following tests will fail:
#AutoConfigureMockMvc
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK, classes = Application.class)
public class SampleTest {
#Autowired
private MockMvc mvc;
#Test
public void check_profile_is_ok() throws Exception {
mvc.perform(get("/")
// fails...
.andExpect(jsonPath("$._links.transactions").value(notNullValue()))
}
#Test
public void check_access() throws Exception {
mvc.perform(get("/transactions/search/findAllByQuery")
// fails...
.andExpect(status().isOk());
}
}
When remove config.disableDefaultExposure(); the Testcase will pass, but then all Endpoints are exposed - and I don't want this.
Is there any configuration I'm missing?
I have a second repository CategoryRepository and everything is same but working.
Okay I solved it by myself. I had (falsely) a second Repository on the Transaction Entity.

How to write a test for a service in which beans self-register

Problem with correct class setting for tests.
I have the following service structure
My service:
Interface
public interface ColumnsFromTableService {
List<ColumnsDto> getTableColumnsFromSource(DataProvider dataProvider, String tableName);
DataProviderSourceType myDataProviderSourceType();
#Autowired
default void regMe(ColumnsFromTableFacade columnsFromTableFacade){
columnsFromTableFacade.register(myDataProviderSourceType(),this);
}
}
Impl
#Service
#RequiredArgsConstructor
public class OracleColumnsFromTableServiceImpl implements ColumnsFromTableService {
private final DataProviderInsideDao dataProviderInsideDao;
#Override
public List<ColumnsDto> getTableColumnsFromSource(DataProvider dataProvider, String tableName) {
return dataProviderInsideDao.getColumnsByTableNameFromOracle(dataProvider, tableName);
}
#Override
public DataProviderSourceType myDataProviderSourceType() {
return DataProviderSourceType.ORACLE;
}
}
My facade:
Interface
public interface ColumnsFromTableFacade {
List<ColumnsDto> getTableColumnsFromSource(DataProvider dataProvider, String tableName);
void register(DataProviderSourceType dataProviderSourceType, ColumnsFromTableService columnsDataProviderService);
}
Impl
#Service
public class ColumnsFromTableFacadeImpl implements ColumnsFromTableFacade {
private final Map<DataProviderSourceType, ColumnsFromTableService> implementationMap = new HashMap<>();
#Override
public List<ColumnsDto> getTableColumnsFromSource(DataProvider dataProvider, String tableName) {
ColumnsFromTableService columnsFromTableService = implementationMap.get(dataProvider.getSourceType());
return columnsFromTableService.getTableColumnsFromSource(dataProvider,tableName);
}
#Override
public void register(DataProviderSourceType dataProviderSourceType, ColumnsFromTableService columnsDataProviderService) {
implementationMap.put(dataProviderSourceType, columnsDataProviderService);
}
}
For use, I inject the facade in the place I need.
Everything works in the application. When creating ColumnsFromTableService beans, Spring Boot sees the #Autowired annotation in the interface and and registers the service in the facade. But when testing this facade, I can't set it up correctly.
My test:
#ExtendWith(MockitoExtension.class)
public class EasyServiceTest {
#InjectMocks
TablesFromSourceFacadeImpl tablesFromSourceFacade;
#Test
void test(){
tablesFromSourceFacade.getAllTablesFromSource(new DataProvider());
}
}
When running the test, the facade is successfully instantiated. But the collection with implementations is empty.
enter image description here
I am using
Junit jupiter - 5.7.1
Spring boot - 2.4.3
I decided to be rough
#ExtendWith(MockitoExtension.class)
public class EasyServiceTest {
TablesFromSourceFacadeImpl tablesFromSourceFacade;
#InjectMocks
OracleTablesFromSourceServiceImpl oracleTablesFromSourceService;
#InjectMocks
OracleColumnsFromTableServiceImpl oracleColumnsFromTableService;
#BeforeEach
void setUp() {
tablesFromSourceFacade = new TablesFromSourceFacadeImpl();
tablesFromSourceFacade.register(postgresTablesFromSourceService.myDataProviderSourceType(),
postgresTablesFromSourceService);
tablesFromSourceFacade.register(oracleTablesFromSourceService.myDataProviderSourceType(),
oracleTablesFromSourceService);
}
#Test
void test(){
tablesFromSourceFacade.getAllTablesFromSource(new DataProvider());
}
}
UPDATED
The second solution to the problem is to raise either the entire context of the spring, or part of it. But in my case, this did not work, since the services are scattered across different packages, and I would have to raise the entire context, which is heavy.

Spring Transaction Management #Transactional behavior

I wanted to know how the Spring #Transactional will work for the following Coding scenarios. I am using Spring 4 + Hiberante 5 with Oracle 19C database for this example.
Example 1:
#Service
public class UserService {
#Transactional(readOnly = true)
public void invoice() {
createPdf();
// send invoice as email, etc.
}
#Transactional(propagation = Propagation.REQUIRES_NEW)
public void createPdf() {
// ...
}
}
Example 2:
#Service
public class UserService {
#Autowired
private InvoiceService invoiceService;
#Transactional(readOnly = true)
public void invoice() {
invoiceService.createPdf();
// send invoice as email, etc.
}
}
#Service
public class InvoiceService {
#Transactional(propagation = Propagation.REQUIRES_NEW)
public void createPdf() {
// ...
}
}
Thanks
Example 1: As you are calling the createPDF method from inside your Service, the #Transactional(REQUIRES_NEW) annotation will effectively be ignored. There will be no new transaction opened.
Example 2: As your are calling another service, which is wrapped in a transactional proxy, you will get a new transaction, as the annotation is respected.
You also might want to read up on this article: Spring Transaction Management: #Transactional In-Depth

Injecting Objects into Filters

I've created a server filter that extends jersey's ContainerRequestFilter, within this custom filter I'd like to inject an (EntityManager) object. To accomplish this I created a factory that implements jersey's hk2.api.Factory and configuration. This setup successfully injects the object into resources, however, it fails to inject the object into the filter.
Does anyone know how to configure jersey to inject objects into filters?
Original Error:
A MultiException has 3 exceptions. They are:
java.lang.IllegalStateException: Not inside a request scope.
java.lang.IllegalArgumentException: While attempting to resolve the dependencies of co.example.filters.Filter errors were found
java.lang.IllegalStateException: Unable to perform operation: resolve on co.example.filters.Filter
Error Messages:
WARNING: The following warnings have been detected: WARNING: Unknown
HK2 failure detected: MultiException stack 1 of 2
javax.persistence.PersistenceException: [PersistenceUnit: egunit]
Unable to build Hibernate SessionFactory at
org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.persistenceException(EntityManagerFactoryBuilderImpl.
at
org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.access$600(EntityManagerFactoryBuilderImpl.java:120)
at
org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:860)
at
org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:850)
at
org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl.withTccl(ClassLoaderServiceImpl.java:425)
at
org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:849)
at
org.hibernate.jpa.HibernatePersistenceProvider.createEntityManagerFactory(HibernatePersistenceProvider.java:75)
at
org.hibernate.ejb.HibernatePersistence.createEntityManagerFactory(HibernatePersistence.java:54)
at
javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:55)
at
javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:39)
at
co.example.factories.ExampleEntityManagerFactory.(ExampleEntityManagerFactory.java:21)
...
...
...
MultiException stack 2 of 2
java.lang.IllegalStateException: Unable to perform operation: create
on co.example.factories.ExampleEntityManagerFactory at
org.jvnet.hk2.internal.ClazzCreator.create(ClazzCreator.java:395)
at
org.jvnet.hk2.internal.SystemDescriptor.create(SystemDescriptor.java:471)
at
org.jvnet.hk2.internal.PerLookupContext.findOrCreate(PerLookupContext.java:69)
at org.jvnet.hk2.internal.Utilities.createService(Utilities.java:2064)
at
org.jvnet.hk2.internal.ServiceHandleImpl.getService(ServiceHandleImpl.java:105)
at
org.jvnet.hk2.internal.ServiceHandleImpl.getService(ServiceHandleImpl.java:87)
at
org.jvnet.hk2.internal.FactoryCreator.create(FactoryCreator.java:117)
at
org.jvnet.hk2.internal.SystemDescriptor.create(SystemDescriptor.java:471)
at
org.glassfish.jersey.process.internal.Reque.findOrCreate(RequestScope.java:162)
at org.jvnet.hk2.internal.Utilities.createService(Utilities.java:2064)
at
org.jvnet.hk2.internal.ServiceLocatorImpl.internalGetService(ServiceLocatorImpl.java:711)
at
org.jvnet.hk2.internal.ServiceLocatorImpl.getService(ServiceLocatorImpl.java:661)
at
org.jvnet.hk2.internal.IterableProviderImpl.get(IterableProviderImpl.java:108)
at co.example.filters.Filter.filter(Filter.java:35)
Custom Filter:
#Provider
public class Filter implements ContainerRequestFilter {
#Inject private javax.inject.Provider<EntityManager> entityManagerProvider;
#Override
public void filter(ContainerRequestContext requestContext) throws IOException {
EntityManager entityManager = entityManagerProvider.get();
EntityDao ed = new EntityDao(entityManager);
...
}
Factory:
public class ExampleEntityManagerFactory implements Factory<EntityManager> {
private final CloseableService closeableService;
private final EntityManagerFactory entityManagerFactory;
#Inject
public ExampleEntityManagerFactory(CloseableService closeableService) {
this.closeableService = closeableService;
this.entityManagerFactory = Persistence.createEntityManagerFactory("egunit");
}
#Override
public EntityManager provide() {
final EntityManager instance = entityManagerFactory.createEntityManager();
//closeableService.add(new Closeable() {
// #Override
// public void close() throws IOException {
// if (instance.isOpen()) instance.close();
// }
//});
return instance;
}
#Override
public void dispose(EntityManager instance) {
if (instance.isOpen()) instance.close();
}
}
Binding:
public class Configuration extends ResourceConfig {
public Configuration() {
...
register(new AbstractBinder() {
#Override
protected void configure() {
bindFactory(ExampleEntityManagerFactory.class).to(EntityManager.class).in(RequestScoped.class);
}
});
}
}
Hard to tell for sure without seeing some code (and verifying), but I'm just going to make an educated guess and say that it's a scoping issue. The EntityManager should be inherently inside a request scope, so I'm guessing that's how you have it set up. So it works fine in your resource class, which I'm guessing is also request scoped (default behavior).
Your ContainerRequestFilter on the other hand, is in a singleton scope. So trying to inject a request scoped EntityManager into the singleton scoped filter is not possible, and you are probably getting the message "Not in a request scope" on startup.
One easy fix is to simply inject javax.inject.Provider<EntityManager>. One of the things it states about the Provider in the javadoc:
Compared to injecting T directly, injecting Provider<T>:
abstracting scope so you can look up an instance in a smaller scope from an instance in a containing scope.
So just do
#Provider
public static class Filter implements ContainerRequestFilter {
#Inject
private javax.inject.Provider<EntityManager> emProvider;
#Override
public void filter(ContainerRequestContext request) throws IOException {
EntityManager em = emProvider.get();
}
}
Given all else is functional, this should work (as tested). If this is not the problem/solution, please post some code and the complete stack trace.
For anyone interested, here is the complete test, using Jersey Test Framework.
Only Maven dependency required
<dependency>
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
<artifactId>jersey-test-framework-provider-grizzly2</artifactId>
<version>2.17</version>
<scope>test</scope>
</dependency>
Test (If you want to see it fail, remove the javax.inject.Provider in the filter, and simple inject EntityManager)
import java.io.IOException;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.Provider;
import junit.framework.Assert;
import org.glassfish.hk2.api.Factory;
import org.glassfish.hk2.utilities.binding.AbstractBinder;
import org.glassfish.jersey.process.internal.RequestScoped;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
import org.junit.Test;
public class FilterScopeTest extends JerseyTest {
public static class EntityManager {
public String getEntity() {
return "Some Entity";
}
public void close() {
}
}
public static class EntityManagerFactory implements Factory<EntityManager> {
EntityManager em = new EntityManager();
public EntityManagerFactory() {
System.out.println("+++++ EntityManagerFactory Created +++++");
}
#Override
public EntityManager provide() {
return em;
}
#Override
public void dispose(EntityManager t) {
em.close();
}
}
public static class Binder extends AbstractBinder {
#Override
protected void configure() {
bindFactory(EntityManagerFactory.class).to(EntityManager.class).in(RequestScoped.class);
}
}
#Provider
public static class Filter implements ContainerRequestFilter {
#Inject
private javax.inject.Provider<EntityManager> em;
public Filter() {
System.out.println("+++++ Filter Created +++++");
}
#Override
public void filter(ContainerRequestContext request) throws IOException {
System.out.println("+++++ In filter EM is null: " + (em.get() == null) + " +++++");
System.out.println("+++++ EM entity value: " + (em.get().getEntity()) + " +++++");
}
}
#Path("em")
public static class EmResource {
#Inject
EntityManager em;
#GET
public String getStuff() {
return em.getEntity();
}
}
#Override
public Application configure() {
return new ResourceConfig(EmResource.class, Filter.class).register(new Binder());
}
#Test
public void doIt() {
Response response = target("em").request().get();
Assert.assertEquals(200, response.getStatus());
System.out.println(response.readEntity(String.class));
response.close();
}
#Test
public void doIt2() {
Response response = target("em").request().get();
Assert.assertEquals(200, response.getStatus());
System.out.println(response.readEntity(String.class));
response.close();
}
}

not being able to persist entity in JPA in spring 3

I am not being able to persist entity in JPA, although findAll works
here.
Here is the JpaDAO
package aop.web.teacher.dao;
import java.lang.reflect.ParameterizedType;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceException;
import javax.persistence.Query;
import org.apache.log4j.Logger;
import org.springframework.orm.jpa.JpaCallback;
import org.springframework.orm.jpa.support.JpaDaoSupport;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
public abstract class JpaDAO extends JpaDaoSupport {
protected Class entityClass;
private static Logger log = Logger.getLogger(JpaDAO.class);
#SuppressWarnings("unchecked")
public JpaDAO() {
ParameterizedType genericSuperclass = (ParameterizedType) getClass()
.getGenericSuperclass();
this.entityClass = (Class) genericSuperclass
.getActualTypeArguments()[1];
}
#Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
public void persist(E entity) {
getJpaTemplate().persist(entity);
}
#Transactional
public void remove(E entity) {
getJpaTemplate().remove(entity);
}
#Transactional
public E merge(E entity) {
return getJpaTemplate().merge(entity);
}
#Transactional
public void refresh(E entity) {
getJpaTemplate().refresh(entity);
}
#Transactional
public E findById(K id) {
return getJpaTemplate().find(entityClass, id);
}
#Transactional
public E flush(E entity) {
getJpaTemplate().flush();
return entity;
}
#SuppressWarnings("unchecked")
#Transactional
public List findAll() {
Object res = getJpaTemplate().execute(new JpaCallback() {
public Object doInJpa(EntityManager em) throws PersistenceException {
Query q = em.createQuery("SELECT h FROM "
+ entityClass.getName() + " h");
return q.getResultList();
}
});
return (List) res;
}
#SuppressWarnings("unchecked")
#Transactional
public Integer removeAll() {
return (Integer) getJpaTemplate().execute(new JpaCallback() {
public Object doInJpa(EntityManager em) throws PersistenceException {
Query q = em.createQuery("DELETE FROM " + entityClass.getName()
+ " h");
return q.executeUpdate();
}
});
}
}
Here is the TestDao class
package aop.web.teacher.dao;
import java.util.Date;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.PersistenceContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;
import aop.web.teacher.rmodels.Teachermaster;
#Service
#Repository
public class TestDaoImpl extends JpaDAO implements TestDao {
#Autowired
EntityManagerFactory entityManagerFactory;
#PersistenceContext
private EntityManager em;
#PostConstruct
public void init() {
super.setEntityManagerFactory(entityManagerFactory);
}
public int saveTeacher() {
List teacherList = findAll();
Teachermaster m1 = teacherList.get(0);
logger.info("Found " + m1.getId() + " and " + m1.getRace());
m1.setRace(m1.getRace() + "::" + System.currentTimeMillis());
logger.info("New " + m1.getId() + " and " + m1.getRace());
persist(m1);
return 0;
}
}
Here is the spring context xml
http://pastebin.com/pKqzW9h1
Here the findAll works
but when we make a change to the attribute of the Teachermaster
then persist or merge does not seem to save the entity...
If we flush it we get exception
javax.persistence.TransactionRequiredException: no transaction is in progress
Please advise
Spring uses proxy-based AOP, therefore aspects (including transactional aspect) are not applied when methods are called from the same class.
Generally speaking
#Transactional annotations should be usually placed on service methods rather than on DAO methods
Your saveTeacher() looks like a service method, it would be better to place it in the separate service class and annotate as #Transactional
You don't need persist() in saveTeacher() - changes made to persistent objects should be saved automatically
Beware of dynamic proxy vs target class proxy distinction (regarding to TestDao) - see the links below
See also:
7.6.1 Understanding AOP proxies
10.5.1 Understanding the Spring Framework's declarative transaction implementation
You are calling a local method when invoking persist() from your test class. This way the proxy that would create transactions is not invoked so your call to persist() has no transaction.
The way to do this properly is to have the test class not extend the object under test but have it injected. This way the proxy will be triggered and the transaction will be created.
By the way, I must add that I find your class design a little bit beculiar. May I suggest creating a structure like the following?
DAO interface:
public interface FooDao {
void persist(Foo foo);
// ...
}
DAO implementation:
public class FooDaoImpl implements FooDao {
#PersistenceContext
private EntityManager entityManager;
#Transactional
public void persist(Foo foo) {
entityManager.persist(foo);
}
}
Test class:
#RunWith(SpringJunit4ClassRunner.class)
#ContextConfiguration(...)
public class FooDaoTest {
#Autowired
private FooDao fooDao;
#Test
public void testPersist() {
// do some testing
}
}
You can, if you wish, extract most of the logic in the DAO implementations into a generic superclass.

Categories