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();
}
}
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'm trying to make CDI work on JBeret SE.
This is my code:
SampleBatchlet class
#Named
public class SampleBatchlet extends AbstractBatchlet
{
#Inject
#BatchProperty(name = "foo")
String foo;
#Inject
StepContext stepContext;
#Inject
Logger logger;
#Override
public String process() throws Exception {
final String say = stepContext.getProperties().getProperty("say");
System.out.println("hello foolish");
return null;
}
}
SampleBatchletTest class
#EnableWeld
class SampleBatchletTest {
#Inject
Logger logger;
#WeldSetup
public WeldInitiator weld = WeldInitiator
.from(
LoggerProducer.class
)
.activate(
RequestScoped.class,
ApplicationScoped.class
)
.build();
#Test
void app() throws InterruptedException {
final JobOperator jobOperator = BatchRuntime.getJobOperator();
long id = jobOperator.start("simplebatchlet", null);
final JobExecutionImpl jobExecution = (JobExecutionImpl) jobOperator.getJobExecution(id);
jobExecution.awaitTermination(5, TimeUnit.SECONDS);
Assertions.assertEquals(BatchStatus.COMPLETED, jobExecution.getBatchStatus());
}
}
Server class
#ApplicationScoped
public class Server {
#Inject
private Logger logger;
public void init(#Observes #Initialized(ApplicationScoped.class) Object init) throws InterruptedException {
logger.info("init");
}
LoggerProducer class
public class LoggerProducer {
#Produces
public Logger produceLogger(InjectionPoint injectionPoint) {
return LoggerFactory.getLogger(injectionPoint.getMember().getDeclaringClass().getName());
}
}
The issue is Logger instance is not injected on SampleBatchlet, whereas is correctly injected either on test and server class above.
Any hints?
LITTLE UPDATE
By reading this reference
https://jberet.gitbooks.io/jberet-user-guide/content/batch_properties/
I discovered java.util.logging.Logger can be injected.
Therefore I added
<batchlet ref="it.infocert.shop.main.SampleBatchlet" >
<properties>
<property name="logger" value="java.util.logging.Logger" />
</properties>
</batchlet>
where value can be actually anything..
On SampleBatchlet I added
#Inject
#BatchProperty
Logger logger;
and now it is injected. I'm a bit perplexed by the way, because I wish to use another logger implementation..
When injecting via #BatchProperty, JBeret tries to check the type of injection field and match it up with the injection value, and instantiate an instance for injection. That's why the logger created by JBeret, instead of your own logger, is injected. For details, see JBeret BatchBeanProducer.java
To inject your own logger via a producer method, you may need to add a qualifier to disambuiguise it. For example,
public class LoggerProducer {
#Produces
#Named("myLogger")
public Logger produceLogger(InjectionPoint injectionPoint) {
return LoggerFactory.getLogger(injectionPoint.getMember().getDeclaringClass().getName());
}
}
#Inject
#Named("myLogger")
Logger logger;
I changed batchet ref on my xml from:
<batchlet ref="it.infocert.shop.main.SampleBatchlet">
to:
<batchlet ref="sampleBatchlet">
now it works
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
}
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 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)) {