I'm new to Java, Neo4j and Spring Data and I'm experiencing some difficulties with the latter.
I'm currently using Spring Data Neo4j 4.1.6. and I have a basic class Person, which is marked with #NodeEntity. It has no-argument constructor and one constructor with String name just for tests.
After a lot of errors I managed to get to the point, where I have a Neo4jTemplate. THE PROBLEM is that when I try to save the Objects of the class Person in the database I get a warning that these are not instances of a persistable class.
e.g. WARN org.neo4j.ogm.session.Neo4jSession - Thread 1:xtractor.Person is not an instance of a persistable class
Here is my Configuration class and Thanks in advance.
package xtractor;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.ogm.session.Session;
import org.neo4j.ogm.session.SessionFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.neo4j.config.Neo4jConfiguration;
import org.springframework.data.neo4j.template.Neo4jOperations;
import org.springframework.data.neo4j.template.Neo4jTemplate;
#Configuration
public class Neo4jConfig extends Neo4jConfiguration{
#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.embedded.driver.EmbeddedDriver")
.setURI("file:///" + Console.dbLocation + ".db");
return config;
}
#Override
#Bean
public SessionFactory getSessionFactory() {
// with domain entity base package(s)
return new SessionFactory(getConfiguration(), "xtractor.*");//tried everything here
}
#Bean(destroyMethod = "shutdown")
public GraphDatabaseService graphDatabaseService() {
return Console.db; //thats the DatabaseService I use.
}
#Bean
//#Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
public Session getSession() throws Exception{
return super.getSession();
}
#Bean
public Neo4jOperations neo4jTemplate() throws Exception{
return new Neo4jTemplate(getSession());
}
}
Edit: Person.class
I think the problem is that I can't make Neo4j scan for these #NodeEntities
package xtractor;
import org.neo4j.ogm.annotation.*;
#NodeEntity
public class Person {
#GraphId
private Long graphId;
private String firstName;
private String lastName;
private int birthdate;
private String birthplace;
public Person(){
}
public Person(String firstName){
this.firstName = firstName;
System.out.println("Person created");
}
//getters and setters
}
Related
while creating a spring batch job that reads data from one table using a reader class and then writes into another table in the same db.
while running the application getting "datasource must be provided" error
The code looks like this
ApplicationConfiguration.java ( configuration class)
#Configuration
#Log4j2
public class ApplicationConfiguration {
#Bean(name="mysqlDS", destroyMethod = "close")
#Qualifier("mysqlDS")
public DataSource getDataSource(#Autowired DBConfiguration dbProperties) {
log.info("Inside getDataSource method");
HikariConfig jdbcConfig = new HikariConfig();
jdbcConfig.setJdbcUrl(dbProperties.getDbURL());
jdbcConfig.setDriverClassName(dbProperties.getDriverClass());
jdbcConfig.setPoolName(dbProperties.getJdbcPoolName());
jdbcConfig.setMaximumPoolSize(dbProperties.getMaxPoolSize());
jdbcConfig.setIdleTimeout(dbProperties.getIdleTimeout());
jdbcConfig.setMinimumIdle(dbProperties.getMinIdle());
jdbcConfig.setConnectionTimeout(dbProperties.getConnectionTimeout());
jdbcConfig.setUsername(dbProperties.getClientKey());
jdbcConfig.setPassword(dbProperties.getClientSecret());
return new HikariDataSource(jdbcConfig);
}
#Bean(name = "jdbcDS")
public JdbcTemplate getJdbcTemplate(#Autowired DBConfiguration dbProperties) {
return new JdbcTemplate(getDataSource(dbProperties));
}
}
DBConfiguration.java ( getting config properties from service)
#Component
#Getter
#Setter
#Configuration
#ConfigurationProperties("some service")
public class DBConfiguration {
private String dbURL;
private String driverClass;
private String jdbcPoolName;
private int maxPoolSize;
private long idleTimeout;
private int minIdle;
private long connectionTimeout;
private String clientKey;
private String clientSecret;
}
BatchConfig.java ( for creating job)
#Configuration
#EnableBatchProcessing
#Log4j2
public class BatchConfig {
#Autowired
DBConfiguration dbProperties;
#Autowired
public JobBuilderFactory jobBuilderFactory;
#Autowired
public StepBuilderFactory stepBuilderFactory;
#Autowired
SWItemReader itemReader ;
#Autowired
SWItemWriter itemWriter;
#Autowired
SWItemProcessor batchProcessor;
#Bean
public Job Job() {
return jobBuilderFactory.get("batch-job")
.incrementer(new RunIdIncrementer())
.flow(Step())
.end()
.build();
}
#Bean
public Step Step() {
return stepBuilderFactory.get("step")
.<Users,Managers>chunk(1)
.reader(itemReader)
.processor(batchProcessor)
.writer(itemWriter)
.build();
}
SWItemReader.java ( reader to read from db)
#Log4j2
public class SWItemReader extends JdbcCursorItemReader<Users> implements ItemReader<Manager> {
#Autowired
DBConfiguration dbProperties;
public ApplicationConfiguration applicationConfiguration;
private static final String QUERY_SELECT_PARTNERS ="select query"
public SWItemReader getItemReader() {
SWItemReader swItemReader = new SWItemReader();
swItemReader.setDataSource(applicationConfiguration.getDataSource(dbProperties));
swItemReader.setSql(QUERY_SELECT_USERS);
swItemReader.setFetchSize(100);
swItemReader.setRowMapper(new UsersRowMapper());
return swItemReader;
}
}
ERROR
Error creating bean with name 'BatchConfig': Unsatisfied dependency expressed through field 'swItemReader'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'SWItemReader' defined in file [D:\\git\SWItemReader.class]: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: DataSource must be provided"}
seems like the datasource is not being set properly .
What am i doing wrong here .
I have a simple listener that is receiving messages from Rabbitmq. I would like to modify the message and publish it to a new exchange/queue. I have been unable to get a rabbit template to work within a listener. Any help would be appreciated. My code is below, when I tried to autowire the template I get
Caused by: java.lang.NullPointerException: null
at com.example.Consumer.onMessage(Consumer.java:27) ~[classes!/:0.0.1-SNAPSHOT]
Classes:
package com.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class RabbittestApplication {
public static void main(String[] args) {
SpringApplication.run(RabbittestApplication.class, args);
}
}
package com.example;
import org.springframework.amqp.core.AcknowledgeMode;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
#Configuration
#EnableAutoConfiguration
public class RabbitConfig {
private static final String SIMPLE_MESSAGE_QUEUE = "qDLX1.dlx";
#Bean
public ConnectionFactory connectionFactory() {
CachingConnectionFactory connectionFactory = new CachingConnectionFactory("RabbitErl19");
connectionFactory.setUsername("gregg");
connectionFactory.setPassword("gregg");
connectionFactory.setPort(5672);
connectionFactory.setVirtualHost("dlxtest");
return connectionFactory;
}
#Bean
public RabbitTemplate rabbitTemplate() {
RabbitTemplate template = new RabbitTemplate(connectionFactory());
return template;
}
#Bean
public SimpleMessageListenerContainer listenerContainer() {
SimpleMessageListenerContainer listenerContainer = new SimpleMessageListenerContainer();
listenerContainer.setConnectionFactory(connectionFactory());
listenerContainer.setQueueNames(SIMPLE_MESSAGE_QUEUE);
listenerContainer.setMessageListener(new Consumer());
listenerContainer.setAcknowledgeMode(AcknowledgeMode.AUTO);
return listenerContainer;
}
}
package com.example;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
#Component
public class Consumer implements MessageListener {
#Autowired
private RabbitTemplate rabbitTemplate;
#Override
public void onMessage(Message message) {
System.out.println("Body: "+new String(message.getBody()));
System.out.println();
message.getMessageProperties().setExpiration("5000");
rabbitTemplate.send("xDLX1.delay", "xq1.retry", message);
}
}
Here is your code:
listenerContainer.setMessageListener(new Consumer());
As you see it is absolutely normal that #Autowired doesn't work. Just because you have bypassed dependency injection.
Since your Consumer is marked with #Component you can simply inject it into that SimpleMessageListenerContainer bean definition:
#Bean
public SimpleMessageListenerContainer listenerContainer(Consumer consumer)
Thanks that did it, I changed my code to what is below and it worked. Your help is much appreciated!
#Autowired
private Consumer consumer;
#Bean
public SimpleMessageListenerContainer listenerContainer() {
SimpleMessageListenerContainer listenerContainer = new SimpleMessageListenerContainer();
listenerContainer.setConnectionFactory(connectionFactory());
listenerContainer.setQueueNames(SIMPLE_MESSAGE_QUEUE);
listenerContainer.setMessageListener(consumer);
listenerContainer.setAcknowledgeMode(AcknowledgeMode.AUTO);
return listenerContainer;
}
Hello i use spring boot 1.3.2 version. I have a custom argument resolver which's name is ActiveCustomerArgumentResolver. Everything is great, resolveArgument method works fine but i can't initialize my service component which is of my custom arg. resolver. Is there a problem with lifecycle process? Here is my code:
import org.springframework.beans.factory.annotation.Autowired;
//other import statements
public class ActiveCustomerArgumentResolver implements HandlerMethodArgumentResolver {
#Autowired
private CustomerService customerService;
#Override
public boolean supportsParameter(MethodParameter parameter) {
if (parameter.hasParameterAnnotation(ActiveCustomer.class) && parameter.getParameterType().equals(Customer.class))
return true;
else
return false;
}
#Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
Principal userPrincipal = webRequest.getUserPrincipal();
if (userPrincipal != null) {
Long customerId = Long.parseLong(userPrincipal.getName());
return customerService.getCustomerById(customerId).orNull(); //customerService is still NULL here, it keeps me getting NullPointerEx.
} else {
throw new IllegalArgumentException("No user principal is associated with the current request, yet parameter is annotated with #ActiveUser");
}
}
}
Let the Spring create the resolver for you by making it a Component:
#Component
public class ActiveCustomerArgumentResolver implements HandlerMethodArgumentResolver {...}
Then inject the resolver into your WebConfig instead of simply using the new, like following:
#EnableWebMvc
#Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
#Autowired private ActiveCustomerArgumentResolver activeCustomerArgumentResolver;
#Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
argumentResolvers.add(activeCustomerArgumentResolver);
}
}
This is how i've solved the problem, not a generic one but helps me a lot:
#Configuration
#EnableAutoConfiguration
#ComponentScan
public class Application extends WebMvcConfigurerAdapter {
private static final Logger logger = LoggerFactory.getLogger(Application.class);
#Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
argumentResolvers.add(activeCustomerArgumentResolver());
}
#Bean
public ActiveCustomerArgumentResolver activeCustomerArgumentResolver() {
return new ActiveCustomerArgumentResolver();
}
}
I'm trying to write a "Hello, World" with Spring Data Neo4j in a standalone app. It runs and actually creates the Neo4j database, but my #Autowired repo is not being initialized. I suspect the problem is in my main class, but I don't know what to try. Unsurprisingly, almost all the Spring tutorials I've found are about web apps.
What am I doing wrong?
config bean:
#Configuration
#EnableNeo4jRepositories(basePackages = "test2")
public class ConfigBean extends Neo4jConfiguration {
private static final String DB_PATH = "/home/kevin/tmp/hello-spring-data-neo4j/";
public ConfigBean() {
setBasePackage("test2");
}
#Bean
public GraphDatabaseService graphDatabaseService() {
return new GraphDatabaseFactory().newEmbeddedDatabase(DB_PATH);
}
}
node entity:
#NodeEntity
public class Foo {
#GraphId
private Long id;
}
repository:
public interface FooRepository extends GraphRepository<Foo> { }
main class:
#Component
public class Test2 {
#Autowired
FooRepository repo;
public void doStuff() {
System.out.println("repo: " + repo); // null!
}
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext("test2");
new Test2().doStuff();
}
}
It logs about 350 lines of output. These are the last few lines. I searched for this error message, but the impression I got is that it's unrelated to my problem.
20:44:30.630 [main] DEBUG o.s.c.e.PropertySourcesPropertyResolver - Searching for key 'spring.liveBeansView.mbeanDomain' in [systemProperties]
20:44:30.631 [main] DEBUG o.s.c.e.PropertySourcesPropertyResolver - Searching for key 'spring.liveBeansView.mbeanDomain' in [systemEnvironment]
20:44:30.635 [main] DEBUG o.s.c.e.PropertySourcesPropertyResolver - Could not find key 'spring.liveBeansView.mbeanDomain' in any property source. Returning [null]
repo: null
Via the magical "ask a question, find the answer" effect, my main class now looks like this, and the repo is being assigned:
#Component
public class Test2 {
#Autowired
FooRepository repo;
public void doStuff() {
System.out.println("repo: " + repo);
}
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext("test2");
Test2 test2 = context.getBean(Test2.class);
test2.doStuff();
}
}
I encountered some difficulties during playing with neo4j. Firstly, when I try to delete defined #EntityModel, I get an exception (Please, forgive me the quality of pics, the exception messages are also in question title):
My Controller (this is just for testing purpouse):
#Controller
public class HomeController {
#Autowired
PersonRepository personRepository;
#RequestMapping(value="/", method = RequestMethod.GET)
public String loadPage(final Model model, final HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) {
Person person = new Person("My person");
personRepository.save(person);
personRepository.findOne(person.getId());
return "home";
}
}
And model:
#NodeEntity
public class Person {
#GraphId
private Long id;
private String name;
public Person() {}
public Person(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(final String name) {
this.name = name;
}
public Long getId() {
return id;
}
}
Configuration file:
#Configuration
#EnableTransactionManagement
#EnableNeo4jRepositories(basePackages = "com.springapp.mvc.repository")
#ComponentScan({"com.springapp.mvc"})
public class PersistenceConfig extends Neo4jConfiguration {
#Bean
public GraphDatabaseService graphDatabaseService() {
return new SpringRestGraphDatabase("http://localhost:7474/db/data");
}
}
My Repository:
public interface PersonRepository extends GraphRepository<Person> {
#Query("MATCH (n:Person{name: \"{namveValue}\"}) RETURN n;")
Person findByName(#Param("nameValue") final String name);
}
What am I doing wrong? I figured out that perhaps Person should implement org.neo4j.graphdb.Node and this is the source of these exceptions. However, having searched github repos I see that people do not implement this interface in their models. I have not found solution on stackoverflow so far.
Node exists in database but I cannot either delete it or save it. Please, help.
You are trying to see if a node with ID '0' exists as a person. Since the root node hasn't got a '__type__' property, the call will fail. SDN uses this property to determine the entity type of a node.
That being said, the exception seems to be caused by the following line:
if(! personRepository.exists(0L)) {