This question already has answers here:
Why is my Spring #Autowired field null?
(21 answers)
Closed 5 years ago.
I am not able to #autowire a class in spring boot application. below is the project explorer snapshot:
From my main class CrmDisconnectionApplication, I am calling DisconnectionConTrigger class. In that class I am doing #autowire for YamlConfig. But I am getting null pointer exception.
below is the code:
CrmDisconnectionApplication
package com.wpits.crm.disconnection;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import com.wpits.crm.disconnection.quartzJob.DisconnectionCronTrigger;
#SpringBootApplication(scanBasePackages = { "com.wpits.crm" })
public class CrmDisconnectionApplication {
public static void main(String[] args) {
SpringApplication.run(CrmDisconnectionApplication.class, args);
DisconnectionCronTrigger disconnectionCronTrigger = DisconnectionCronTrigger.getInstance();
disconnectionCronTrigger.initialize();
}
}
DisconnectionCronTrigger
package com.wpits.crm.disconnection.quartzJob;
import org.quartz.CronScheduleBuilder;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.wpits.crm.disconnection.config.YamlConfig;
#Component
public class DisconnectionCronTrigger {
#Autowired
private YamlConfig myConfig;
private static DisconnectionCronTrigger obj = null;
private DisconnectionCronTrigger() {}
public static DisconnectionCronTrigger getInstance() {
if(obj == null) {
obj = new DisconnectionCronTrigger();
}
return obj;
}
public void initialize() {
System.out.println("using environment: " + myConfig.getEnvironment());
System.out.println("name: " + myConfig.getName());
System.out.println("servers: " + myConfig.getServers());
System.out.println("hobies: "+myConfig.getHobies());
JobDetail job = JobBuilder.newJob(DisconnectionJob.class).withIdentity("DisconnectionJob", "group1").build();
Trigger trigger = TriggerBuilder.newTrigger().withIdentity("cronTrigger", "group1").withSchedule(CronScheduleBuilder.cronSchedule("0/10 * * * * ?")).build();
try {
Scheduler scheduler = new StdSchedulerFactory().getScheduler();
scheduler.start();
scheduler.scheduleJob(job, trigger);
}catch(Exception ex) {
ex.printStackTrace();
}
}
}
YamlConfig
package com.wpits.crm.disconnection.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import java.util.*;
#Configuration
#EnableConfigurationProperties
#ConfigurationProperties
public class YamlConfig {
private String name;
private String environment;
private List<String> servers = new ArrayList<>();
private List<String> hobies = new ArrayList<>();
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEnvironment() {
return environment;
}
public void setEnvironment(String environment) {
this.environment = environment;
}
public List<String> getServers() {
return servers;
}
public void setServers(List<String> servers) {
this.servers = servers;
}
public List<String> getHobies() {
return hobies;
}
public void setHobies(List<String> hobies) {
this.hobies = hobies;
}
}
I am getting null pointer exception for line System.out.println("using environment: " + myConfig.getEnvironment()); in class DisconnectionCronTrigger. Where am I getting it wrong. Please correct me..
The problem is this line
DisconnectionCronTrigger disconnectionCronTrigger = DisconnectionCronTrigger.getInstance();
In getInstance you are creating a new object using new. You should not do new, instead Autowire the bean or get it from Spring application context.
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(CrmDisconnectionApplication.class, args);
DisconnectionCronTrigger disconnectionCronTrigger = (DisconnectionCronTrigger)context.getBean("disconnectionCronTrigger");
disconnectionCronTrigger.initialize();
}
If you do it like this, then you will get an object will all the fields in the bean autowired. If you create a object using new, then you wont.
When defining an EntityManager in a Spring Java Config class, I can add the base packages to scan for Entity classes by calling a method on the corresponding builder:
public LocalContainerEntityManagerFactoryBean entityManagerFactory(EntityManagerFactoryBuilder builder) {
// Some other configuration here
builder.packages("org.foo.bar", "org.foo.baz");
return builder.build();
}
I need something similar for the places where Spring looks for Repository Interfaces. The usual way is using the #EnableJpaRepositories annotation:
#EnableJpaRepositories(basePackages = {"org.foo.barbaz"})
But I would like to have a dynamical way for defining these packages similar to the way above for the Entity locations. Something like this:
public SomeJpaRepositoryFactoryBean entityManagerFactory(JpaRepositoryFactoryBuilder builder) {
// Some other configuration here
builder.packages("org.foo.barbaz");
return builder.build();
}
Is there a way to do this with the current Spring Data JPA release is it simply not meant to be done this way?
You can use #AutoConfigurationPackage annotation to add your child module's package to scan-packages.
Remove all #EnableJpaRepositories from your child module
Add #AutoConfigurationPackage class to the top directory of your child module (similar to #SpringBootApplication, you must put this class to the top-most directory to scan all subpackages):
#AutoConfigurationPackage
public class ChildConfiguration {
}
Create spring.factories file under /resources/META-INF/spring.factories of your child module and add the configuration class:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.child.package.ChildConfiguration
Now you can #Autowired your repository from your core project. (Tested and worked)
Without Spring Boot (plain Spring MVC setup)
#EnableJpaRepositories can be used on more than one #Configuration class. That said, every module can declare its own repositories by having an own configuration class:
#Configuration
#EnableJpaRepositories(basePackages = "package1")
public class ConfigClass1 { /* ... */ }
#Configuration
#EnableJpaRepositories(basePackages = "package2")
public class ConfigClass2 { /* ... */ }
Spring Data JPA then counts in all of them (package1 and package2).
Although this is still not a programmatical way, it solves my problem.
This problem also puzzled me for almost a week.I debug the "spring application context refresh" code and org.springframework.data.jpa.repository.config.JpaRepositoriesRegistrar line by line and then I solve the problem.
I customize my EnableJpaRepository annotation and JpaRepositoriesRegistrar,then I can do anything in AbdJpaRepositoriesRegistrar("abd" is my customized classes's prefix).
AbdEnableJpaRepositories.java
import org.springframework.beans.factory.FactoryBean;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Import;
import org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean;
import org.springframework.data.repository.config.DefaultRepositoryBaseClass;
import org.springframework.data.repository.query.QueryLookupStrategy;
import org.springframework.data.repository.query.QueryLookupStrategy.Key;
import org.springframework.transaction.PlatformTransactionManager;
import javax.persistence.EntityManagerFactory;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* basePackages
* 复制EnableJpaRepositories,Import自定义的AbdJpaRepositoriesRegistrar.
* Copy from EnableJpaRepositories,Import customized AbdJpaRepositoriesRegistrar.
*
* #author Oliver Gierke
* #author Thomas Darimont
* #author ghj
*/
#Target(ElementType.TYPE)
#Retention(RetentionPolicy.RUNTIME)
#Documented
#Inherited
#Import(AbdJpaRepositoriesRegistrar.class)
public #interface AbdEnableJpaRepositories {
/**
* Alias for the {#link #basePackages()} attribute. Allows for more concise annotation declarations e.g.:
* {#code #EnableJpaRepositories("org.my.pkg")} instead of {#code #EnableJpaRepositories(basePackages="org.my.pkg")}.
*/
String value() default "";
/**
* Base packages to scan for annotated components. {#link #value()} is an alias for (and mutually exclusive with) this
* attribute. Use {#link #basePackageClasses()} for a type-safe alternative to String-based package names.
*/
String basePackages() default "";
/**
* Type-safe alternative to {#link #basePackages()} for specifying the packages to scan for annotated components. The
* package of each class specified will be scanned. Consider creating a special no-op marker class or interface in
* each package that serves no purpose other than being referenced by this attribute.
*/
Class<?>[] basePackageClasses() default {};
/**
* Specifies which types are eligible for component scanning. Further narrows the set of candidate components from
* everything in {#link #basePackages()} to everything in the base packages that matches the given filter or filters.
*/
Filter[] includeFilters() default {};
/**
* Specifies which types are not eligible for component scanning.
*/
Filter[] excludeFilters() default {};
/**
* Returns the postfix to be used when looking up custom repository implementations. Defaults to {#literal Impl}. So
* for a repository named {#code PersonRepository} the corresponding implementation class will be looked up scanning
* for {#code PersonRepositoryImpl}.
*
* #return
*/
String repositoryImplementationPostfix() default "Impl";
/**
* Configures the location of where to find the Spring Data named queries properties file. Will default to
* {#code META-INF/jpa-named-queries.properties}.
*
* #return
*/
String namedQueriesLocation() default "";
/**
* Returns the key of the {#link QueryLookupStrategy} to be used for lookup queries for query methods. Defaults to
* {#link Key#CREATE_IF_NOT_FOUND}.
*
* #return
*/
Key queryLookupStrategy() default Key.CREATE_IF_NOT_FOUND;
/**
* Returns the {#link FactoryBean} class to be used for each repository instance. Defaults to
* {#link JpaRepositoryFactoryBean}.
*
* #return
*/
Class<?> repositoryFactoryBeanClass() default JpaRepositoryFactoryBean.class;
/**
* Configure the repository base class to be used to create repository proxies for this particular configuration.
*
* #return
* #since 1.9
*/
Class<?> repositoryBaseClass() default DefaultRepositoryBaseClass.class;
// JPA specific configuration
/**
* Configures the name of the {#link EntityManagerFactory} bean definition to be used to create repositories
* discovered through this annotation. Defaults to {#code entityManagerFactory}.
*
* #return
*/
String entityManagerFactoryRef() default "entityManagerFactory";
/**
* Configures the name of the {#link PlatformTransactionManager} bean definition to be used to create repositories
* discovered through this annotation. Defaults to {#code transactionManager}.
*
* #return
*/
String transactionManagerRef() default "transactionManager";
/**
* Configures whether nested repository-interfaces (e.g. defined as inner classes) should be discovered by the
* repositories infrastructure.
*/
boolean considerNestedRepositories() default false;
/**
* Configures whether to enable default transactions for Spring Data JPA repositories. Defaults to {#literal true}. If
* disabled, repositories must be used behind a facade that's configuring transactions (e.g. using Spring's annotation
* driven transaction facilities) or repository methods have to be used to demarcate transactions.
*
* #return whether to enable default transactions, defaults to {#literal true}.
*/
boolean enableDefaultTransactions() default true;
}
AbdJpaRepositoriesRegistrar.java
import org.springframework.data.jpa.repository.config.JpaRepositoryConfigExtension;
import org.springframework.data.repository.config.RepositoryConfigurationExtension;
import java.lang.annotation.Annotation;
class AbdJpaRepositoriesRegistrar extends AbdRepositoryBeanDefinitionRegistrarSupport {
/*
* (non-Javadoc)
* #see org.springframework.data.repository.config.RepositoryBeanDefinitionRegistrarSupport#getAnnotation()
*/
#Override
protected Class<? extends Annotation> getAnnotation() {
return AbdEnableJpaRepositories.class;
}
/*
* (non-Javadoc)
* #see org.springframework.data.repository.config.RepositoryBeanDefinitionRegistrarSupport#getExtension()
*/
#Override
protected RepositoryConfigurationExtension getExtension() {
return new JpaRepositoryConfigExtension();
}
}
AbdRepositoryBeanDefinitionRegistrarSupport.java
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.env.Environment;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.data.repository.config.RepositoryBeanDefinitionRegistrarSupport;
import org.springframework.data.repository.config.RepositoryConfigurationDelegate;
import org.springframework.data.repository.config.RepositoryConfigurationExtension;
import org.springframework.data.repository.config.RepositoryConfigurationUtils;
import org.springframework.util.Assert;
/**
*
* #author ghj
*/
abstract class AbdRepositoryBeanDefinitionRegistrarSupport extends RepositoryBeanDefinitionRegistrarSupport implements ImportBeanDefinitionRegistrar,
ResourceLoaderAware, EnvironmentAware {
private ResourceLoader resourceLoader;
private Environment environment;
#Override
public void setResourceLoader(ResourceLoader resourceLoader) {
this.resourceLoader = resourceLoader;
}
#Override
public void setEnvironment(Environment environment) {
this.environment = environment;
}
#Override
public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry registry) {
Assert.notNull(resourceLoader, "ResourceLoader must not be null!");
Assert.notNull(annotationMetadata, "AnnotationMetadata must not be null!");
Assert.notNull(registry, "BeanDefinitionRegistry must not be null!");
// Guard against calls for sub-classes
if (annotationMetadata.getAnnotationAttributes(getAnnotation().getName()) == null) {
return;
}
// 使用自定义的AbdAnnotationRepositoryConfigurationSource
AbdAnnotationRepositoryConfigurationSource configurationSource = new AbdAnnotationRepositoryConfigurationSource(
annotationMetadata, getAnnotation(), resourceLoader, environment);
RepositoryConfigurationExtension extension = getExtension();
RepositoryConfigurationUtils.exposeRegistration(extension, registry, configurationSource);
RepositoryConfigurationDelegate delegate = new RepositoryConfigurationDelegate(configurationSource, resourceLoader,
environment);
delegate.registerRepositoriesIn(registry, extension);
}
}
AbdAnnotationRepositoryConfigurationSource.java. You can override getBasePackages then you can return any packages you want.
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.env.Environment;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.data.repository.config.AnnotationRepositoryConfigurationSource;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
import java.lang.annotation.Annotation;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
/**
*
* #author ghj
*/
class AbdAnnotationRepositoryConfigurationSource extends AnnotationRepositoryConfigurationSource {
private static final String BASE_PACKAGES = "basePackages";
private static final String BASE_PACKAGE_CLASSES = "basePackageClasses";
private final AnnotationMetadata configMetadata;
private final AnnotationAttributes attributes;
private final Environment environment;
AbdAnnotationRepositoryConfigurationSource(AnnotationMetadata metadata, Class<? extends Annotation> annotation, ResourceLoader resourceLoader, Environment environment) {
super(metadata, annotation, resourceLoader, environment);
this.attributes = new AnnotationAttributes(metadata.getAnnotationAttributes(annotation.getName()));
this.configMetadata = metadata;
this.environment = environment;
}
#Override
public Iterable<String> getBasePackages() {
String value = attributes.getStringArray("value")[0];
String basePackages = attributes.getStringArray(BASE_PACKAGES)[0];
Class<?>[] basePackageClasses = attributes.getClassArray(BASE_PACKAGE_CLASSES);
// Default configuration - return package of annotated class
if (StringUtils.isEmpty(value) && StringUtils.isEmpty(basePackages) && basePackageClasses.length == 0) {
String className = configMetadata.getClassName();
return Collections.singleton(ClassUtils.getPackageName(className));
}
String[] packagesFromValue = parsePackagesSpel(value);
String[] packagesFromBasePackages = parsePackagesSpel(basePackages);
Set<String> packages = new HashSet<>();
packages.addAll(Arrays.asList(packagesFromValue));
packages.addAll(Arrays.asList(packagesFromBasePackages));
for (Class<?> typeName : basePackageClasses) {
packages.add(ClassUtils.getPackageName(typeName));
}
return packages;
}
private String[] parsePackagesSpel(String raw) {
if (!raw.trim().startsWith("$")) {
if (StringUtils.isEmpty(raw)) {
return new String[]{};
}
return raw.split(",");
} else {
raw = raw.trim();
String packages = this.environment.getProperty(raw.substring("${".length(), raw.length() - "}".length()));
return packages.split(",");
}
}
}
How to use?Here is configuration file.
PrimaryJpaConfiguration.java
import com.shinow.abd.springjpa2.annotation.AbdEnableJpaRepositories;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.env.Environment;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import javax.persistence.EntityManager;
import javax.sql.DataSource;
import java.util.Map;
#Configuration
#AbdEnableJpaRepositories(
basePackages = "${spring.jpa.base-packages}",
entityManagerFactoryRef = "entityManagerFactory",
transactionManagerRef = "transactionManager"
)
#EnableAutoConfiguration(exclude = HibernateJpaAutoConfiguration.class)
public class PrimaryJpaConfiguration implements EnvironmentAware {
private Environment env;
#Bean
#ConditionalOnMissingBean(name = "entityManager")
#Primary
public EntityManager entityManager(#Qualifier("entityManagerFactory") LocalContainerEntityManagerFactoryBean entityManagerFactory) {
return entityManagerFactory.getObject().createEntityManager();
}
#Bean
#ConditionalOnMissingBean(name = "entityManagerFactory")
#Primary
public LocalContainerEntityManagerFactoryBean entityManagerFactory(#Qualifier("dataSource") DataSource dataSource) {
Map<String, Object> properties = JpaProperties.get("", env);
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
entityManagerFactoryBean.setDataSource(dataSource);
entityManagerFactoryBean.setJpaPropertyMap(properties);
entityManagerFactoryBean.setPackagesToScan(env.getProperty("spring.jpa.base-packages").split(","));
entityManagerFactoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
return entityManagerFactoryBean;
}
#Bean
#ConditionalOnMissingBean(name = "dataSource")
#Primary
#ConfigurationProperties(prefix = "spring.datasource")
public DataSource dataSource() {
return DataSourceBuilder.create().build();
}
#Bean
#ConditionalOnMissingBean(name = "transactionManager")
#Primary
public PlatformTransactionManager transactionManager(#Qualifier("entityManagerFactory") LocalContainerEntityManagerFactoryBean entityManagerFactory) {
JpaTransactionManager transactionManager
= new JpaTransactionManager();
transactionManager.setEntityManagerFactory(
entityManagerFactory.getObject());
return transactionManager;
}
#Override
public void setEnvironment(Environment environment) {
this.env = environment;
}
}
You can add spring.jpa.base-packages config to your application.properties.
For example:spring.jpa.base-packages=com.foo.a,com.bar.b,and the repositories and entities under those packages "com.foo.a" and "com.bar.b" will be added to the spring Ioc container.
Answer by 高慧觉 Spring Data JPA - How to programmatically set JpaRepository base packages worked for me, but I've come up with a simpler and more reliable AnnotationRepositoryConfigurationSource implementation: just allow Spring Data to collect the packages in its way, and then post-process them and expand property placeholders to package names.
class AbdAnnotationRepositoryConfigurationSource extends AnnotationRepositoryConfigurationSource {
private final Environment environment;
ExpressionsSupportingAnnotationRepositoryConfigurationSource(AnnotationMetadata metadata, Class<? extends Annotation> annotation,
ResourceLoader resourceLoader, Environment environment, BeanDefinitionRegistry registry) {
super(metadata, annotation, resourceLoader, environment, registry);
this.environment = environment;
}
#Override
public Streamable<String> getBasePackages() {
Streamable<String> rawPackages = super.getBasePackages();
return Streamable.of(() -> rawPackages.stream()
.flatMap(raw -> parsePackagesSpel(raw).stream())
);
}
private List<String> parsePackagesSpel(#Nullable String rawPackage) {
Objects.requireNonNull(rawPackage, "Package specification cannot be null");
if (!rawPackage.trim().startsWith("$")) {
return Collections.singletonList(rawPackage);
}
rawPackage = rawPackage.trim();
String propertyName = rawPackage.substring("${".length(), rawPackage.length() - "}".length());
String packages = this.environment.getProperty(propertyName);
if (!StringUtils.hasText(packages)) {
throw new IllegalStateException(
String.format("Could not resolve the following packages definition: %s", rawPackage));
}
return Arrays.stream(packages.split(","))
.map(String::trim)
.filter(StringUtils::hasText)
.collect(Collectors.toList());
}
}
I've implemented a way to invoke #EnableJpaRepositories purely programmatically. For the purpose I've created a class which simulates the Annotation data passed to a config class annotated with the #EnableJpaRepositories annotation. I called my class EnableJpaRepositoriesData. It is confirmed working with Spring 5.1.5, SpringBoot 2.1.3. I guess it must be compatible with earlier and later versions alike, with none or very little changes at most.
Below follows the class code, and a sample usage code for it.
EnableJpaRepositoriesData.java:
package org.patladj.jpa.config.multijpa;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.classreading.AnnotationMetadataReadingVisitor;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Indexed;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.annotation.TransactionManagementConfigurationSelector;
import java.lang.reflect.Method;
import java.util.*;
public class EnableJpaRepositoriesData extends AnnotationMetadataReadingVisitor implements AnnotationMetadata {
private Map<String, ?> data;
private void initIt() throws NoSuchMethodException, ClassNotFoundException {
//################## protected final Set<String> annotationSet = new LinkedHashSet<>(4);
annotationSet.add(Configuration.class.getCanonicalName());
annotationSet.add(EnableTransactionManagement.class.getCanonicalName());
annotationSet.add(EnableJpaRepositories.class.getCanonicalName());
//################## protected final Map<String, Set<String>> metaAnnotationMap = new LinkedHashMap<>(4);
metaAnnotationMap.put(Configuration.class.getCanonicalName(),
new LinkedHashSet<>(Arrays.asList(
Component.class.getCanonicalName(),
Indexed.class.getCanonicalName()
)));
metaAnnotationMap.put(EnableTransactionManagement.class.getCanonicalName(),
new LinkedHashSet<>(Arrays.asList(
Import.class.getCanonicalName()
)));
metaAnnotationMap.put(EnableJpaRepositories.class.getCanonicalName(),
new LinkedHashSet<>(Arrays.asList(
Import.class.getCanonicalName()
)));
//################## protected final LinkedMultiValueMap<String, AnnotationAttributes> attributesMap = new LinkedMultiValueMap<>(4);
attributesMap.put(Configuration.class.getCanonicalName(),
new LinkedList<AnnotationAttributes>() {{
add(new AnnotationAttributes(new LinkedHashMap<String, Object>() {{
put("value", defaultFor(Configuration.class, "value"));
}}));
}});
attributesMap.put(Component.class.getCanonicalName(),
new LinkedList<AnnotationAttributes>() {{
add(new AnnotationAttributes(new LinkedHashMap<String, Object>() {{
put("value", defaultFor(Component.class, "value"));
}}));
}});
attributesMap.put(Indexed.class.getCanonicalName(),
new LinkedList<AnnotationAttributes>() {{
add(new AnnotationAttributes(new LinkedHashMap<String, Object>() {{
}}));
}});
attributesMap.put(EnableTransactionManagement.class.getCanonicalName(),
new LinkedList<AnnotationAttributes>() {{
add(new AnnotationAttributes(new LinkedHashMap<String, Object>() {{
put("order", defaultFor(EnableTransactionManagement.class, "order"));
put("mode", defaultFor(EnableTransactionManagement.class, "mode"));
put("proxyTargetClass", defaultFor(EnableTransactionManagement.class, "proxyTargetClass"));
}}));
}});
attributesMap.put(Import.class.getCanonicalName(),
new LinkedList<AnnotationAttributes>() {{
add(new AnnotationAttributes(new LinkedHashMap<String, Object>() {{
put("value", new Class<?>[]{TransactionManagementConfigurationSelector.class});
}}));
add(new AnnotationAttributes(new LinkedHashMap<String, Object>() {{
put("value", new Class<?>[]{Class.forName("org.springframework.data.jpa.repository.config.JpaRepositoriesRegistrar")});
}}));
}});
attributesMap.put(EnableJpaRepositories.class.getCanonicalName(),
new LinkedList<AnnotationAttributes>() {{
add(new AnnotationAttributes(new LinkedHashMap<String, Object>() {{
put("repositoryBaseClass", data.get("repositoryBaseClass"));
put("basePackages", data.get("basePackages"));
put("value", defaultFor(EnableJpaRepositories.class, "value"));
put("excludeFilters", new AnnotationAttributes[]{});
put("includeFilters", new AnnotationAttributes[]{});
put("basePackageClasses", defaultFor(EnableJpaRepositories.class, "basePackageClasses"));
put("bootstrapMode", defaultFor(EnableJpaRepositories.class, "bootstrapMode"));
put("transactionManagerRef", data.get("transactionManagerRef"));
put("considerNestedRepositories", defaultFor(EnableJpaRepositories.class, "considerNestedRepositories"));
put("namedQueriesLocation", defaultFor(EnableJpaRepositories.class, "namedQueriesLocation"));
put("queryLookupStrategy", defaultFor(EnableJpaRepositories.class, "queryLookupStrategy"));
put("entityManagerFactoryRef", data.get("entityManagerFactoryRef"));
put("enableDefaultTransactions", defaultFor(EnableJpaRepositories.class, "enableDefaultTransactions"));
put("repositoryImplementationPostfix", defaultFor(EnableJpaRepositories.class, "repositoryImplementationPostfix"));
put("repositoryFactoryBeanClass", defaultFor(EnableJpaRepositories.class, "repositoryFactoryBeanClass"));
}}));
}});
//##################
}
public EnableJpaRepositoriesData(#Nullable ClassLoader classLoader, Map<String, ?> data) throws NoSuchMethodException, ClassNotFoundException {
super(classLoader);
this.data = data;
this.initIt();
}
private Object defaultFor(Class<?> clazz, String methodName) throws NoSuchMethodException {
Method method = clazz.getDeclaredMethod(methodName);
return method.getDefaultValue();
}
}
Sample usage of the Class to actually invoke enableJpaRepositories
programmatically:
AnnotationMetadata enableJpaRepositoriesData = null;
try {
enableJpaRepositoriesData = new EnableJpaRepositoriesData(this.getClass().getClassLoader(), new HashMap<String, Object>() {{
put("repositoryBaseClass", MyJPAConnectorImpl.class);
put("basePackages", new String[] {
//This is where you set the repositories base packages to scan.
//... Having your best programmatic convenience
"org.patladj.connector.multijpa.common",
"org.patladj.connector.multijpa.anotherrepositoriespackage",
"org.patladj.connector.multijpa.morepackagestoscanforrepositories..."
});
//Ofcourse you need to create by yourself the custom transactionManagerFactory,
// ... entityManagerFactory, JPAVendorAdapter and Datasource beans for your
// ... custom persistence contexts using unique bean names (different than
// ... the default Spring data names: 'entityManagerFactory', etc...)
// ... Then "send" these bean names as references to each and every ...
// and as many as you want persistence contexts programmatically here
put("transactionManagerRef", myCustomPersistanceContextName + "_transactionManager");
put("entityManagerFactoryRef", myCustomPersistanceContextName + "_entityManagerFactory");
}});
} catch (NoSuchMethodException e) {
throw new ExceptionInInitializerError(e);
} catch (ClassNotFoundException e) {
throw new ExceptionInInitializerError(e);
}
AnnotationRepositoryConfigurationSource configurationSource = new AnnotationRepositoryConfigurationSource(
enableJpaRepositoriesData, EnableJpaRepositories.class, applicationContext, environment, registry
);
RepositoryConfigurationExtension extension = new JpaRepositoryConfigExtension();
RepositoryConfigurationUtils.exposeRegistration(extension, registry, configurationSource);
RepositoryConfigurationDelegate delegate = new RepositoryConfigurationDelegate(configurationSource, applicationContext, environment);
delegate.registerRepositoriesIn(registry, extension);
And finally, in case if you don't know, you can use the following #Configuration class
public class MultiJPABeanDefinitionRegistrar implements BeanDefinitionRegistryPostProcessor, ApplicationContextAware
... to override 2 of its methods to have the post process bean registry and applicationContext at your disposal to register bean definitions dynamically.
Methods to override:
- public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
- public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException
I referred this post only and created a module aware multi database aware spring data library for mysql(compatible with spring boot) in github.Some application properties need to be added and you are done .
Documentation and other details could be found at :-
https://github.com/yatharthamishra0419/spring-boot-data-multimodule-mysql
What your looking for is #EntityScan but it's only available in Spring Boot. The configuration you can annotate in Spring Data JPA is documented here https://docs.spring.io/spring-data/jpa/docs/2.0.8.RELEASE/reference/html/#jpa.java-config
#Configuration
#EnableJpaRepositories
#EnableTransactionManagement
class ApplicationConfig {
#Bean
public DataSource dataSource() {
EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
return builder.setType(EmbeddedDatabaseType.HSQL).build();
}
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setGenerateDdl(true);
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setJpaVendorAdapter(vendorAdapter);
factory.setPackagesToScan("com.acme.domain");
factory.setDataSource(dataSource());
return factory;
}
#Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
JpaTransactionManager txManager = new JpaTransactionManager();
txManager.setEntityManagerFactory(entityManagerFactory);
return txManager;
}
}
I recently started working on springBoot projects.
I wrote a sample program where I am fetching data from the DB, modifying it and storing it back in the DB.
The problem I am facing is, I am able to get the data from the DB but when saving it back, I am getting the below exception.
org.springframework.dao.InvalidDataAccessApiUsageException: no transaction is in progress; nested exception is
javax.persistence.TransactionRequiredException: no transaction is in progress at
org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:413) at
org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:246)
Below is my Code.
DataConfiguraiton.java
import java.util.Properties;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.annotation.EnableTransactionManagement;
/**
*
* This class contains code to configure database.
* #author satish
*
*/
#Configuration
#EntityScan(basePackages= {"com.tushar.common.model"})
#ComponentScan(basePackages= {"com.tushar.common.model"})
#EnableJpaRepositories(basePackages={"com"})
#EnableTransactionManagement
public class DataConfiguration {
#Value("${spring.datasource.driver-class-name}")
private String driverClassName;
#Value("${spring.datasource.url}")
private String url;
#Value("${spring.datasource.username}")
private String username;
#Value("${spring.datasource.password}")
private String password;
#Value("${spring.datasource.dialect}")
private String dialect;
/**
*
* It will scan the package where our entities appears.
* #param dataSource
* #return
*/
#Bean
#Autowired
public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource) {
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setGenerateDdl(true);
Properties jpaProperties = new Properties();
jpaProperties.setProperty("hibernate.show_sql", "true");
jpaProperties.setProperty("hibernate.dialect", dialect);
jpaProperties.setProperty("hibernate.hbm2ddl.auto", "update");
LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBean =
new LocalContainerEntityManagerFactoryBean();
localContainerEntityManagerFactoryBean.setJpaVendorAdapter(vendorAdapter);
localContainerEntityManagerFactoryBean.setPackagesToScan(new String[] {"com.att.pricerd.discountmanagement.model"});
localContainerEntityManagerFactoryBean.setDataSource(dataSource);
localContainerEntityManagerFactoryBean.setJpaProperties(jpaProperties);
return localContainerEntityManagerFactoryBean;
}
/**
*
* It will set the database properties to the data Source.
* #return
*/
#Bean
public DataSource dataSource(){
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(driverClassName);
dataSource.setUrl(url);
dataSource.setUsername(username);
dataSource.setPassword(password);
return dataSource;
}
#Bean
#Autowired
public JpaTransactionManager transactionManager(LocalContainerEntityManagerFactoryBean emf) throws Exception {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(emf.getObject());
transactionManager.setEntityManagerFactory(emf.getNativeEntityManagerFactory());
return transactionManager;
}
}
Repository
#Repository
public interface EmployeeRepository extends JpaRepository<Employee,Long> {
}
DAO Class
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
#Component
public class EmployeeDataManagementDaoImpl implements EmployeeDataManagementDao {
private static final Logger LOG = LoggerFactory.getLogger(EmployeeDataManagementDaoImpl.class);
#Autowired
private EmployeeDataManagmentUtil EmployeeDataManagmentUtil;
#Autowired
private SalesEmployeesRepository salesEmployeesRepository;
#Autowired
private EmployeeRepository employeeRepository;
#PersistenceContext
private EntityManager em;
#Override
public void addEmployee(EmployeeDetailsRequestVo EmployeeRequest) {
convertAndSaveSalesEmployee(EmployeeRequest);
}
/**
* Fetch data from DB, update the inital and maximum Employee and
* save it back to DB.
* #throws DataNotFoundException
*
*/
#Override
public void changeEmployee(List<Employee> Employees) throws EmployeeManagementException {
for (Employee employee : Employees) {
List<Employee> EmployeesDB;
try {
EmployeesDB = getEmployeeFromDB(employee);
} catch (DataNotFoundException e) {
List<String> errorMessage = new ArrayList<>();
errorMessage.add(e.getMessage());
LOG.error(e.getMessage(),e);
throw new EmployeeManagementException(errorMessage);
}
for (Employee employee : EmployeesDB) {
if (employee.getMaxEmployee() != null) {
Employee.setMaxEmployee(employee.getMaxEmployee());
}
if (employee.getInitialEmployee() != null) {
Employee.setInitialEmployee(employee.getInitialEmployee());
}
employeeRepository.saveAndFlush(Employee);
}
}
}
/**
* This method is used to get the Employee details from DB.
*
* #param employee
* #return List<Employee>
* #throws DataNotFoundException
*/
private List<Employee> getEmployeeFromDB(Employee employee)
throws DataNotFoundException {
List<Employee> EmployeesDB = findByAllEmployeesFilters(employee.getempId(),
employee.getyearsExp(), employee.getdeptLevInd(), employee.getsalary(),
employee.getaddress(), employee.getCountryCd(), employee.getpinCode());
if (EmployeesDB.isEmpty()) {
String errCode = ""; // error code for data not found, yet to be
// decided.
LOG.error("ERROR CODE :: {}", errCode);
throw new DataNotFoundException(errCode);
}
return EmployeesDB;
}
/**
* This method will update the end date Employee
* #param List<Employee>
*/
#Override
public void inactivateEmployee(List<Employee> Employees)
throws EmployeeManagementException {
for (Employee employee : Employees) {
List<Employee> employeesDB;
try {
employeesDB = getEmployeeFromDB(employee);
} catch (DataNotFoundException e) {
List<String> errorMessage = new ArrayList<>();
errorMessage.add(e.getMessage());
LOG.error(e.getMessage(),e);
throw new EmployeeManagementException(errorMessage);
}
for (Employee employee : EmployeesDB) {
if (employee.getEmployeeEndDate() != null) {
employee.setEmployeeEndDate(employee.getEmployeeEndDate());
}
//
employeeRepository.saveAndFlush(Employee);
}
}
}
/**
*
* #param empId
* #param yearsExp
* #param bigDecimal
* #param salary
* #param regionId
* #param countryCd
* #param pinCode
* #return
*/
private List<Employee> findByAllEmployeeFilters(BigDecimal empId, BigDecimal yearsExp,
BigDecimal bigDecimal, BigDecimal salary, String regionId, String countryCd, String pinCode) {
CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
CriteriaQuery<Employee> criteriaQuery = criteriaBuilder
.createQuery(Employee.class);
Root<Employee> root = criteriaQuery.from(Employee.class);
criteriaQuery.where(criteriaBuilder.equal(root.get("empId"), empId),
criteriaBuilder.equal(root.get("deptLevInd"), bigDecimal),
criteriaBuilder.equal(root.get("yearsExp"), yearsExp), criteriaBuilder.equal(root.get("salary"), salary),
criteriaBuilder.equal(root.get("address"), regionId),
criteriaBuilder.equal(root.get("countryCd"), countryCd),
criteriaBuilder.equal(root.get("pinCode"), pinCode));
return em.createQuery(criteriaQuery).getResultList();
}
}
The getEmployeeFromDB gets me the values from DB but saveAndFlush is giving me the exception.
Actualy Bedla is rigth, you should use #Transactional. What i want to add that method changeEmployee should be declared in Service class. Correct desing is create EmployeeService class and move method changeEmployee to it, and annotate service with #Transactional. Generaly dao should contain only find methods to load from db and update/save methods to save.
I have a redis cluster with master, slave and 3 sentinel servers. The master and slave is map to dns names as node1-redis-dev.com, node2-redis-dev.com. The redis server version is 2.8
I include below in my application.properties file.
spring.redis.cluster.nodes=node1-redis-dev.com:6379,node2-redis-dev.com:6379
spring.redis.pool.max-idle=8
spring.redis.pool.min-idle=0
spring.redis.pool.max-active=-1
spring.redis.pool.max-wait=-1
But when I inspect the StringRedisTemplate, I see localhost instead of cluster information under hostName property of JedisConnectionFactory.
Also I see the exception in creationStackTrace property of JedisPool.
java.lang.Exception
at org.apache.commons.pool2.impl.BaseGenericObjectPool.<init>(BaseGenericObjectPool.java:139)
at org.apache.commons.pool2.impl.GenericObjectPool.<init>(GenericObjectPool.java:107)
at redis.clients.util.Pool.initPool(Pool.java:43)
at redis.clients.util.Pool.<init>(Pool.java:31)
at redis.clients.jedis.JedisPool.<init>(JedisPool.java:80)
at redis.clients.jedis.JedisPool.<init>(JedisPool.java:74)
at redis.clients.jedis.JedisPool.<init>(JedisPool.java:55)
at org.springframework.data.redis.connection.jedis.JedisConnectionFactory.createRedisPool(JedisConnectionFactory.java:228)
at org.springframework.data.redis.connection.jedis.JedisConnectionFactory.createPool(JedisConnectionFactory.java:204)
The CasheRepository class looks like below,
#Component
#CacheConfig(cacheNames = "enroll", cacheManager = "enrollCM")
public class EnrollCashRepository {
#Autowired
private StringRedisTemplate stringRedisTemplate;
//Other methods
}
I am using spring boot 1.3.4 with spring-boot-starter-redis 1.2.7 which import jedis 2.7.3 dependency.
What am I missing with integrate redis cluster with Spring boot applicatiom?
All that is needed is setting the initial collection of cluster nodes in RedisClusterConfiguration and provide that one to JedisConnectionFactory.
#Configuration
class Config {
List<String> clusterNodes = Arrays.asList("node1-redis-dev.com:6379", "node2-redis-dev.com:6379");
#Bean
RedisConnectionFactory connectionFactory() {
return new JedisConnectionFactory(new RedisClusterConfiguration(clusterNodes));
}
#Bean
RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {
// just used StringRedisTemplate for simplicity here.
return new StringRedisTemplate(factory);
}
}
The following should work
application.properties
spring.redis.cluster.nodes=127.0.0.1:6379
spring.redis.cluster.max-redirects=3
ClusterConfigurationProperties.java
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
#Component
#ConfigurationProperties(prefix = "spring.redis.cluster")
public class ClusterConfigurationProperties {
/*
* spring.redis.cluster.nodes[0] = 127.0.0.1:7379 spring.redis.cluster.nodes[1]
* = 127.0.0.1:7380 ...
*/
private List<String> nodes;
/**
* spring.redis.cluster.max-redirects=3
*/
private int maxRedirects;
/**
* Get initial collection of known cluster nodes in format {#code host:port}.
*
* #return
*/
public List<String> getNodes() {
return nodes;
}
public void setNodes(List<String> nodes) {
this.nodes = nodes;
}
public int getMaxRedirects() {
return maxRedirects;
}
public void setMaxRedirects(int maxRedirects) {
this.maxRedirects = maxRedirects;
}
}
RedisConfig.java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.connection.RedisClusterConfiguration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import io.lettuce.core.ReadFrom;
#Configuration
public class RedisConfig {
#Autowired
private ClusterConfigurationProperties clusterProperties;
#Bean
LettuceConnectionFactory redisConnectionFactory(RedisClusterConfiguration redisConfiguration) {
LettuceClientConfiguration clientConfig = LettuceClientConfiguration.builder()
.readFrom(ReadFrom.REPLICA_PREFERRED).build();
return new LettuceConnectionFactory(redisConfiguration, clientConfig);
}
#Bean
RedisClusterConfiguration redisConfiguration() {
RedisClusterConfiguration redisClusterConfiguration = new RedisClusterConfiguration(clusterProperties.getNodes());
redisClusterConfiguration.setMaxRedirects(clusterProperties.getMaxRedirects());
return redisClusterConfiguration;
}
#Bean
#ConditionalOnMissingBean(name = "redisTemplate")
#Primary
RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(connectionFactory);
template.setKeySerializer(new StringRedisSerializer());
// other settings...
return template;
}
}
I'm fairly new to Spring (the Neo4j side), and I am having trouble #AutoWire-ing my repository.
this is my repo:
package org.jarivm.relationGraph.objects.repositories;
public interface EmployeeRepository extends GraphRepository<Employee> {
#Query("MATCH a=(:Employee)-[:WORKED_ON]->(p:Project) WHERE id(p)={0} RETURN a")
Iterable<Employee> getTeamMates(Project client);
}
my test class:
package org.jarivm.relationGraph;
import org.apache.commons.collections4.set.ListOrderedSet;
import org.jarivm.relationGraph.objects.domains.Employee;
import org.jarivm.relationGraph.objects.domains.Project;
import org.jarivm.relationGraph.objects.repositories.EmployeeRepository;
import org.jarivm.relationGraph.utilities.NodeProperties;
import org.junit.After;
import org.junit.Before;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runners.MethodSorters;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.Iterator;
/**
* #author Jari Van Melckebeke
* #since 02.09.16
*/
#FixMethodOrder(MethodSorters.JVM)
public class Tests extends Application {
#Autowired
private Facade facade;
#Autowired
private EmployeeRepository employeeRepository;
#Before
public void setUp() throws Exception {
facade = new Facade();
}
#After
public void tearDown() throws Exception {
facade.tearDown();
}
/*
#Test
public void persistedEmployeeShouldBeRetrievableFromGraphDB() {
Employee employee = new Employee("john", "adams");
//System.out.println(session.getTransaction().status());
if (!facade.findEmployeeByProperty("name", employee.getName()).iterator().hasNext()) {
facade.commit(employee);
Employee foundHim = facade.findEmployeeByProperty("name", employee.getName()).iterator().next();
assert foundHim.getId().equals(employee.getId());
assert foundHim.getName().equals(employee.getName());
}
}
#Test
public void persistedChainShouldBeRetrievableFromGraphDB() {
Employee employee = new Employee("john", "myles");
Client client = new Client();
Sector sector = new Sector();
Project project = new Project();
client.setName("Real Dolmen");
project.setClient(client);
project.setCost(100.0);
project.setName("project highrise");
Set<Employee> set = new ListOrderedSet<Employee>();
set.add(employee);
project.setTeam(set);
sector.setName("game");
client.setSector(sector);
facade.commit(sector);
facade.commit(employee);
facade.commit(client);
facade.commit(project);
Client foundHim = facade.findClientByProperty("name", client.getName()).iterator().next();
assert foundHim.getId().equals(client.getId());
assert foundHim.getName().equals(client.getName());
}
#Test
public void projectShouldBeInsertableAlone() {
Project project = new Project();
project.setName("random");
project.setLanguage("Java");
facade.commit(project);
Project foundHim = facade.findProjectByProperty("name", project.getName()).iterator().next();
assert foundHim.getId().equals(project.getId());
}
#Test
public void clientShouldBeInsertableAlone() {
Client client = new Client();
client.setName("Colruyt");
facade.commit(client);
Client foundHim = facade.findClientByProperty("name", client.getName()).iterator().next();
assert foundHim.getId().equals(client.getId());
}*/
#Test
public void createdNodesShoudBeEditable() {
Iterator<Employee> employees = facade.findEmployeeByProperty("name", "john").iterator();
Project project = facade.findProjectByProperty("name", "random").iterator().next();
while (employees.hasNext()) {
Employee e = employees.next();
if (project.getTeam() == null)
project.setTeam(new ListOrderedSet<Employee>());
project.getTeam().add(e);
}
facade.commit(project);
}
package org.jarivm.relationGraph;
#Autowired
private EmployeeRepository employeeRepository;
#Test
public void teamMatesShouldBeViewable() {
Project p = facade.findProjectByProperty("name", "Matsoft").iterator().next();
System.out.println(p);
System.out.println(employeeRepository);
Iterable<Employee> e = employeeRepository.getTeamMates(p);
System.out.println(e.iterator());
}
}
and my Application.java class:
package org.jarivm.relationGraph;
import org.neo4j.ogm.session.SessionFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.neo4j.config.Neo4jConfiguration;
import org.springframework.data.neo4j.repository.config.EnableNeo4jRepositories;
import org.springframework.transaction.annotation.EnableTransactionManagement;
/**
* #author Jari Van Melckebeke
* #since 23.09.16
*/
#EnableTransactionManagement
#ComponentScan(basePackages = {"org.jarivm.relationGraph"})
#Configuration
#EnableNeo4jRepositories(basePackages = "org.jarivm.relationGraph.objects.repositories.EmployeeRepository")
public class Application extends Neo4jConfiguration {
public static final String URL = System.getenv("NEO4J_URL") != null ? System.getenv("NEO4J_URL") : "http://localhost:7474";
#Bean
public org.neo4j.ogm.config.Configuration getConfiguration() {
org.neo4j.ogm.config.Configuration config = new org.neo4j.ogm.config.Configuration();
config
.driverConfiguration()
.setDriverClassName("org.neo4j.ogm.drivers.http.driver.HttpDriver")
.setURI(URL)
.setCredentials("neo4j", "mypassword");
return config;
}
#Override
public SessionFactory getSessionFactory() {
return new SessionFactory(getConfiguration(), "org.jarivm.relationGraph.objects.domains");
}
}
The #autowire did never work with this program so I do not know what the problem is...
thank's in advance,
Jari Van Melckebeke
I think your Tests class should not extend Application, but instead be annotated with RunsWith - something like (untested):
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes=org.jarivm.relationGraph.Application.class, loader=AnnotationConfigContextLoader.class
public class Tests {
for more information, see the section titled Integration Testing with #Configuration Classes:
https://spring.io/blog/2011/06/21/spring-3-1-m2-testing-with-configuration-classes-and-profiles