I'm starting a project using Neo4j and Spring Data Neo4j. I want my program to use a local database that already contains my data (as opposed to loading the data each time on startup) since I have a lot of data that needs to be loaded into the database. I've tried setting up a test case that populates a database with my data in order to accomplish this goal. However, the data in the database does not appear to persist after my tests have finished running: I look at the database using the neo4j console/shell and find it is empty.
I've constructed a small example project that's also not working. Any insight into what I'm doing incorrectly would be appreciated.
Node entity class:
#NodeEntity
public class Entity {
#GraphId private Long graphId;
private String name;
public Entity() { }
public Entity(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
Repository class:
public interface EntityRepository extends GraphRepository<Entity> { }
My test class:
#ContextConfiguration(locations = "classpath:applicationContext.xml")
#RunWith(SpringJUnit4ClassRunner.class)
#Transactional
public class DatabaseTest {
#Autowired Neo4jTemplate template;
#Autowired EntityRepository entityRepository;
#Test
public void testCreatingEntities() {
Entity entity1 = new Entity("one");
Entity entity2 = new Entity("two");
template.save(entity1);
template.save(entity2);
Iterator<Entity> entityIterator = entityRepository.findAll().iterator();
List<Entity> entityList = IteratorUtils.toList(entityIterator);
System.out.println("Number of entities = " + entityList.size());
for(Entity entity : entityList) {
System.out.println("Entity " + entity.getName());
}
}
}
applicationContext.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:neo4j="http://www.springframework.org/schema/data/neo4j"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/data/neo4j
http://www.springframework.org/schema/data/neo4j/spring-neo4j.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<context:spring-configured/>
<context:annotation-config/>
<context:component-scan base-package="personal.neo4j">
<context:exclude-filter type="annotation"
expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<neo4j:config storeDirectory="data/test.db"
base-package="personal.neo4j"/>
<neo4j:repositories base-package="personal.neo4j"/>
<tx:annotation-driven/>
</beans>
Test output:
Running personal.neo4j.DatabaseTest
Number of entities = 2
Entity one
Entity two
Using libraries:
Java 1.7
Spring 3.2.8.RELEASE
Neo4j 2.0.2
Spring Data Neo4j 3.0.2.RELEASE
JUnit 4.11
Thanks for your help,
Thomas
See if this thread helps:
http://forum.spring.io/forum/spring-projects/data/53804-commit-transactions-running-springjunit4classrunner
Looks like SpringJUnit4ClassRunner will rollback all transactions, unless explicitly told otherwise.
Related
My Spring Boot Application is secured by Spring Security OAuth2. The userdata is stored in a SQL-database. I followed here royclarkson's Oauth protected REST service. This project works with Spring Data JPA. This works fine.
https://github.com/royclarkson/spring-rest-service-oauth
But now I want to implement my Neo4J Configuration to get data from my Neo4J-Database via Neo4J-JDBC (JDBC-template). Here I followed this GitHub project:
https://github.com/neo4j-examples/movies-java-spring-boot-jdbc
As a standalone application it works, but if I put this two projects togehter, I get this Exception:
HibernateJpaAutoConfiguration.class]: Invocation of init method failed;
nested exception is org.hibernate.HibernateException:
Unable to determine Dialect to use [name=Neo4j, majorVersion=3];
user must register resolver or explicitly set 'hibernate.dialect'
My Neo4jConfig.java looks like this:
#Configuration
public class Neo4jConfig {
//NEO4J Server Implementation via JDBC
private static final String NEO4J_URL = System.getProperty("NEO4J_URL","jdbc:neo4j://localhost:7474");
private static final String NEO4J_USER = System.getProperty("NEO4J_USER","neo4j");
private static final String NEO4J_PASSWORD = System.getProperty("NEO4J_PASSWORD","neo4j");
#Bean
public DataSource dataSource() {
return new DriverManagerDataSource(NEO4J_URL, NEO4J_USER, NEO4J_PASSWORD);
}
public Neo4jConfig(){
}
public String getNeo4JURL(){
return NEO4J_URL;
}
}
TripController.java
import hello.data.Trip;
#RestController
public class TripController {
#Autowired
JdbcTemplate template;
public static final RowMapper<Trip> TRIP_ROW_MAPPER = new RowMapper<Trip>() {
public Trip mapRow(ResultSet rs, int rowNum) throws SQLException {
return new Trip(rs.getString("tripname"),rs.getInt("slots"), rs.getInt("to_date"), rs.getInt("from_date"));
}
};
String SEARCH_TRIPS_QUERY =
" MATCH (t:Trip)\n" +
" RETURN t.tripname as tripname, t.slots as slots, t.to_date as to_date, t.from_date as from_date";
#RequestMapping(path = "/alltrips", method = RequestMethod.GET)
public List<Trip> alltrips() {
return template.query(SEARCH_TRIPS_QUERY, TRIP_ROW_MAPPER);
}
}
I hope you guys understand my question. I know, I am a really newone at Spring, but I hope anyone can help me :)
This is happening because hibernate does not find any dialect for Neo4J as Neo4j is not RDBMS database and dialect is not provided by default. You can use Hibernate OGM (search and include it in pom.xml), and then use following configuration to configure Entitymanager and Transaction manager
#Configuration
#EnableJpaRepositories(basePackages = {
"your repository packages" }, entityManagerFactoryRef = "n4jEntityManager", transactionManagerRef = "n4jTxnManager")
public class DatabaseConfiguration {
#Bean(name = "n4jEntityManager")
public LocalContainerEntityManagerFactoryBean entityManager() {
Map<String, Object> properties = new HashMap<String, Object>();
properties.put("javax.persistence.transactionType", "resource_local");
properties.put("hibernate.ogm.datastore.provider","neo4j");
properties.put("hibernate.ogm.datastore.host","localhost");
properties.put("hibernate.ogm.datastore.port","7474");
properties.put("hibernate.ogm.datastore.database", "your database");
properties.put("hibernate.ogm.datastore.create_database", "true or false");
LocalContainerEntityManagerFactoryBean entityManager = new LocalContainerEntityManagerFactoryBean();
entityManager.setPackagesToScan("your domain packages");
entityManager.setPersistenceUnitName("n4jPU");
entityManager.setJpaPropertyMap(properties);
entityManager.setPersistenceProviderClass(HibernateOgmPersistence.class);
return entityManager;
}
#Bean(name = "n4jTxnManager")
public PlatformTransactionManager txnManager() {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(mongoEntityManager().getObject());
return transactionManager;
}
}
But I suggest, to remove Hibernate altogether if you are not going to use RDBMS and will only be using Neo4j. Spring data has good support for NoSQL databases and Entities can be defined using annotations like #NodeEntity and #GraphId
I have looked everywhere and not a single response is valid or the question is just slightly off to the point of not getting me the answer I need. Given all the searches I have looked for there seems to be one MASSIVE flaw in .Net's implementation of xml serialization.
Default:
[XmlRoot("root", Namespace="http://myclass.org/")]
public class MyClass
{
}
void Main() {
XmlSerializer ser = new XmlSerializer(typeof(MyClass));
XmlSerializerNamespaces xsn = new XmlSerializerNamespaces();
xsn.Add("mc", "http://myclass.org/");
ser.Serialize(new StreamWriter(Console.Out), new MyClass(), xsn);
}
OUTPUT:
<?xml version="1.0"?>
<mc:root xmlns:mc="http://myclass.org/">
</mc:root>
IXmlSerializable:
[XmlRoot("root", Namespace="http://myclass.org/")]
public class MyClass : IXmlSerializable
{
public XmlSchema GetSchema() {return null;}
public void ReadXml(XmlReader reader) {}
public void WriteXml(XmlWriter writer) {}
}
void Main() {
XmlSerializer ser = new XmlSerializer(typeof(MyClass));
XmlSerializerNamespaces xsn = new XmlSerializerNamespaces();
xsn.Add("mc", "http://myclass.org/");
ser.Serialize(new StreamWriter(Console.Out), new MyClass(), xsn);
}
OUTPUT:
<?xml version="1.0"?>
<root xmlns="http://myclass.org/">
</root>
WHY!
How do we fix this?
This is essential to figure out because without custom processing I will be forced to double step it, and process the serialized xml into an XmlDocument to fix this glitch. and yes, this HAS to be a glitch. I can work around everything else EXCEPT the root element.
I am not the only one who needs to know how to do this.
Thanks
Jaeden "Sifo Dyas" al'Raec Ruiner
I'm working on a large Grails 1.3.7 project and I want to access the flow state name from a filter for logging purposes. I've been googling a lot and the closest answer I could find was: Grails WebFlow State Name, but it only works from within the flow itself.
Is there any way to obtain the state name of the flow that is being executed in current session from outside the flow (the filter)?
Thanks in advance,
Guillermo
After a lot of googling and debugging I managed to produce the following code. It works in a simple application. I'll integrate it with the main application when I come back from holidays and then I'll update this question.
package org.glalejos
import org.springframework.context.ApplicationContext
import org.springframework.webflow.context.ExternalContext
import org.springframework.webflow.context.ExternalContextHolder
import org.springframework.webflow.context.servlet.ServletExternalContext
import org.springframework.webflow.execution.FlowExecution
import org.springframework.webflow.execution.FlowExecutionKey
import org.springframework.webflow.execution.repository.FlowExecutionRepository
class LoggingFilters {
def grailsApplication
String getFlowStateName(def grailsApplication, def servletContext, def request, def response) {
String stateName
if (grailsApplication && servletContext && request && request.queryString && response) {
try {
String strKey = null
String[] keys = request.queryString.split("&")
keys.each{ if (it.startsWith("execution=")) strKey = it.substring(10)}
if (strKey != null) {
ApplicationContext ctx = grailsApplication.mainContext
FlowExecutionRepository fer = ctx.getBean("flowExecutionRepository")
FlowExecutionKey fek = fer.parseFlowExecutionKey(strKey)
ExternalContext previousContext = ExternalContextHolder.getExternalContext()
try {
// You have to set an external context before invoking "fer.getFlowExecution()" or it'll throw a NPE
ExternalContextHolder.setExternalContext(new ServletExternalContext(servletContext, request, response));
FlowExecution fe = fer.getFlowExecution(fek)
stateName = fe.getActiveSession().getState().getId()
} finally {
ExternalContextHolder.setExternalContext(previousContext);
}
} else {
stateName = null
}
} catch(Exception e) {
stateName = null
}
} else {
stateName = null
}
return stateName
}
def filters = {
logData(controller:"*", action:"*") {
before = {
println("Incoming request. Current flow state name is: ${getFlowStateName(grailsApplication, servletContext, request, response)}")
}
after = {
println("Dispatched request. Current flow state name is: ${getFlowStateName(grailsApplication, servletContext, request, response)}")
}
}
}
}
EDIT: The code above is OK to determine the name of the current flow state at a given point in time, but it won't update the Mapped Diagnostic Context of the logging framework as the flow execution evolves. For this purpose it is necessary to implement a org.springframework.webflow.execution.FlowExecutionListener and register it in conf/spring/resources.groovy:
beans = {
myLoggingFlowExecutionListener(org.example.MyLoggingFlowExecutionListener)
}
You have to register this listener bean and the hibernateConversationListener bean in a executionListenerLoader bean, but, for some reason, Spring DSL doesn't work in this case (see EDIT2 below). So here is the resources.xml you can place in the same folder as resources.groovy in order to properly declare your resources:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
<bean id="executionListenerLoader" class="org.springframework.webflow.execution.factory.StaticFlowExecutionListenerLoader">
<constructor-arg>
<list>
<ref bean="hibernateConversationListener" />
<ref bean="myLoggingFlowExecutionListener" />
</list>
</constructor-arg>
</bean>
</beans>
Each FlowExecutionListener method receives a lot of context information that can be used for logging purposes (I'm ommiting the implementation of this class for clarity).
EDIT2: Failing to add the hibernateConversationListener bean to the executionListenerLoader results in Hibernate exceptions when manipulating domain objects during the lifecycle of the flow. However, Spring DSL doesn't work in this specific case, so I had to declare the required beans using XML format. See http://grails.1312388.n4.nabble.com/Registering-custom-flow-execution-listener-td2279764.html. I've updated the code above to the final, working, version.
Currently I am using a Transaction View pattern to make lazy-loading of collections possible in views.
I have the following in web.xml
<filter>
<filter-name>view</filter-name>
<filter-class>com.jasoni.ViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>view</filter-name>
<url-pattern>*.xhtml</url-pattern>
</filter-mapping>
And the Filter class has the following...
public class ViewFilter implements Filter {
#Resource UserTransaction tx;
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
try {
tx.begin();
chain.doFilter(request, response);
}
//catch here
finally {
//another try-catch
tx.commit();
}
}
}
Then assuming I have the following (rather contrived) backing bean
#ManagedBean
#RequestScoped
public class DepartmentEmployees {
#EJB
private DepartmentServiceBean deptService;
#ManagedProperty(value="#{param.deptId}")
private Integer deptId;
private Department dept;
#PostConstruct
public String init() {
dept = deptService.findById(deptId);
}
}
I can do something like this in my view (.xhtml file)
<ul>
<c:forEach var="emp" items="#{departmentEmployees.dept.employees}">
<li>#{emp.firstName} #{emp.lastName}</li>
</c:forEach>
</ul>
Just wondering if anybody knows of a different way to accomplish the same thing without using filters (or servlets).
This approach ("open session in view") has a couple of major disadvantages. Besides being kind of hacky (it's certainly not the design idea of a servlet filter to control a business session) you don't have many options to appropriately process any "real" exception that occurs while rendering the JSF page.
You don't write much about your infrastructure / technology stack, but I assume that you are on a Java EE 6 server.
I usually use the EntityManger in Extended Mode and flush it with transactions which I control explicitly by annotating only certain methods of my business facade. Have a look at this example (taken from Adam Bien - Real World Java EE Patterns, Rethinking Best Practices):
#Stateful
#TransactionAttribute(TransactionAttributeType.NEVER)
public class BookFacadeBean implements BookFacade {
#PersistenceContext(type=PersistenceContextType.EXTENDED)
private EntityManager em;
private Book currentBook;
public Book find(long id){
this.currentBook = this.em.find(Book.class, id);
return this.currentBook;
}
public void create(Book book){
this.em.persist(book);
this.currentBook = book;
}
public Book getCurrentBook() {
return currentBook;
}
#TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void save(){
//nothing to do here
}
}
A next level in this approach would be to bind the EntityManager to a CDI conversation scope. Have a look at (a) Weld (b) Seam 3 Persistence for further discussions on that topic.
This is rather a rough sketch of an alternative than a detailed how-to. I hope this level of information is what you were asking about - feel free to ask further questions. :-)
I cannot seem to inject a simple bean into my #WebService. With Spring on the classpath and javax.inject dependencies defined, I created a simple JAX-WS webservice with some underlying interface-driven DAOs etc:
#Named
#WebService(name = "NoteStorage", serviceName = "NoteStorageWS")
public class NoteStorageWS implements NoteStore {
private static final Log l = LogFactory.getLog(NoteStorageWS.class);
#Named("NoteDAO")
#Inject
private NoteDAO noteDAO;
public NoteStorageWS() {
super();
}
#Override
#WebMethod
public StorageState takeNote(String note) {
try {
l.info(format("Service received message: '%s'", note));
Note n = new Note();
n.setContent(note);
noteDAO.store(n);
} catch (Exception e) {
l.error(e);
return StorageState.FAILURE;
}
return StorageState.SUCCESS;
}
#WebMethod(exclude = true)
public void setNoteDAO(NoteDAO noteDAO) {
this.noteDAO = noteDAO;
}
}
NoteDAOhas just implementation: FlatFileNoteDAO which is defined as follows:
#Named("NoteDAO")
public class FlatFileNoteDAO implements NoteDAO {
private static final Log l = LogFactory.getLog(FlatFileNoteDAO.class);
#Override
public void store(Note n) {
if (n == null) {
throw new IllegalArgumentException("Note was null");
}
try {
l.info(format("Storing note '%s'", n));
FileWriter fileWriter = new FileWriter(new File("Note"));
fileWriter.write(format("%s\n", n.getContent()));
fileWriter.close();
} catch (IOException e) {
throw new DataAccessException(e);
}
}
}
My web.xml says:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=" http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/context.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<resource-env-ref>
<description>Object factory for the CDI Bean Manager</description>
<resource-env-ref-name>BeanManager</resource-env-ref-name>
<resource-env-ref-type>javax.enterprise.inject.spi.BeanManager</resource-env-ref-type>
</resource-env-ref>
</web-app>
I deploy the application to Glassfish by pointing it to the target/note-ws/ directory and execute the simple takeNote method via the ?Tester page.
Upon submission of the tester form I get a NullPointerException at the line noteDAO.store(n);, presumably because noteDAO wasn't injected.
I can confirm that Spring has been invoked by the logs from glassfish on context initialisation (the Java EE context):
[#|2011-12-04T16:57:24.970+0000|INFO|glassfish3.1.1|org.springframework.context.annotation.ClassPathBeanDefinitionScanner|_ThreadID=256;_ThreadName=Thread-2;|JSR-330 'javax.inject.Named' annotation found and supported for component scanning|#]
[#|2011-12-04T16:57:25.653+0000|INFO|glassfish3.1.1|org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor|_ThreadID=256;_ThreadName=Thread-2;|JSR-330 'javax.inject.Inject' annotation found and supported for autowiring|#]
[#|2011-12-04T16:57:25.757+0000|INFO|glassfish3.1.1|org.springframework.beans.factory.support.DefaultListableBeanFactory|_ThreadID=256;_ThreadName=Thread-2;|Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory#9e39146: defining beans [noteStorageWS,NoteDAO,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor]; root of factory hierarchy|#]
which says my beans are defined: noteStorageWS, NoteDAO and so-on.
Any ideas?
Edit
to clarify, I'm using Spring to provide JSR 330 -- dependency injection -- functionality.
I never got this solved, so I ended up removing the DI-features as the codebase was small and relied on manual dependency resolution - plain old new IFaceImpl(); for now.
JAX-WS and Guice require a specific integration via #GuiceManaged annotation. More info here.
Move the business logic to a separate bean and annotate it with #Configurable so that Spring can handle the lifecycle of the bean. Now use that bean in NoteStorageWS
#Configurable
public class NoteStorageUtil{
#Named("NoteDAO")
#Inject
private NoteDAO noteDAO;
public StorageState takeNote(String note) {
try {
l.info(format("Service received message: '%s'", note));
Note n = new Note();
n.setContent(note);
noteDAO.store(n);
} catch (Exception e) {
l.error(e);
return StorageState.FAILURE;
}
return StorageState.SUCCESS;
}
}
#WebService(name = "NoteStorage", serviceName = "NoteStorageWS")
public class NoteStorageWS implements NoteStore {
public StorageState takeNote(String note) {
return new NoteStorageUtil().takeNote(note)
}
}
Or please check if your end point configuration is proper, so that the web service end point is a spring-managed bean also.
Eg:-
<bean id="hello" class="demo.spring.service.HelloWorldImpl" />
<jaxws:endpoint id="helloWorld" implementor="#hello" address="/HelloWorld" />
check the link