I use a LocalContainerEntityManagerFactoryBean
to setting up a JPA EntityManagerFactory
. Among the scanned entities I scan with setPackagesToScan
I have a User entity that implement spring security interface UserDetails
.
When I lunch my application I have this error:
Caused by: org.hibernate.boot.registry.classloading.spi.ClassLoadingException: Unable to load class [com.medkhelifi.model.entities.User]
at org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl.classForName(ClassLoaderServiceImpl.java:354)
at org.hibernate.boot.model.source.internal.annotations.AnnotationMetadataSourceProcessorImpl.<init>(AnnotationMetadataSourceProcessorImpl.java:105)
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess$1.<init>(MetadataBuildingProcess.java:156)
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:150)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:904)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:935)
at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:57)
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:365)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:390)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:377)
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:341)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1821)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1758)
... 11 more
Caused by: java.lang.ClassNotFoundException: Could not load requested class : com.medkhelifi.model.entities.User
at org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl$AggregatedClassLoader.findClass(ClassLoaderServiceImpl.java:342)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:348)
at org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl.classForName(ClassLoaderServiceImpl.java:351)
... 23 more
This is how I configured my application: **Beans config: **
@Configuration
@PropertySource("classpath:application.properties")
@ComponentScan("com.medkhrlifi.tutorials.designpatterns.dao")
@EnableTransactionManagement
public class AppConfig {
// properties variable goes here ...
@Bean
public DataSource dataSource(){
// datasource config goes here ...
}
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean(){
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setGenerateDdl(true);
LocalContainerEntityManagerFactoryBean lem = new LocalContainerEntityManagerFactoryBean();
lem.setDataSource(dataSource());
lem.setJpaVendorAdapter(vendorAdapter);
lem.setPackagesToScan("com.medkhelifi.model.entities");
lem.setJpaProperties(jpaProperties());
//lem.afterPropertiesSet();
return lem;
}
@Bean
public PlatformTransactionManager platformTransactionManager(){
JpaTransactionManager txManager = new JpaTransactionManager();
txManager.setEntityManagerFactory(entityManagerFactoryBean().getObject());
return txManager;
}
@Bean
public Properties jpaProperties(){
Properties jpa = new Properties();
jpa.put("hibernate.dialect", dialect);
return jpa;
}
}
User entity
@Data
@Entity
@Table(name = "user")
public class User implements UserDetails {
private static final Logger logger = LoggerFactory.getLogger(User.class);
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private String id;
@NotEmpty
private String firstname;
@NotEmpty
private String lastname;
@NotEmpty
private String email;
@NotEmpty
private String password;
//@ElementCollection(fetch = FetchType.EAGER)
//@Builder.Default
@DBRef
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(
name = "user_role",
joinColumns = @JoinColumn(name = "id_user"),
inverseJoinColumns = @JoinColumn(name = "id_role"))
private List<Role> roles = new ArrayList<>();
// Override methods goes here
}
** UPDATE ** I know that the error came from the UserDetails interface implementation, because if I remove it my app start normally, but this is not what I want.
This is how I run my app (for test purpose only):
public class DaoApp {
private static AnnotationConfigApplicationContext applicationContext= new AnnotationConfigApplicationContext (AppConfig.class);
public static void main(String[] args) throws ParseException {
System.out.println("main app for test purpose only started successfully");
}
}
I hope I have provided enough information to be helped.
I bypassed the problem by removing the implementation of the UserDetails
interface from my User
entity, and set up a new mechanism to recover the GrantedAuthority
necessary for Spring Security. But I still do not understand why this interface implementation poses a problem with setPackagesToScan
used by the JPA EntityManagerFactory
.
If somone can give us an explanation?