Results 1 to 10 of 17

Thread: Spring Social Neo4j

Hybrid View

  1. #1
    Join Date
    Jul 2012
    Posts
    10

    Default Spring Social Neo4j

    Hi people,
    I recently started to write a neo4j connector for spring social. This is the repo:

    https://github.com/maciossek/spring-social-neo4j

    Feel free to help me out here, since I do not have a lot of experience in this domain (java/spring/neo4j). I am working on a project, where we actually use a Neo4j database and we would like to have the spring social project working for us, too.

    Cheers,
    Mathias

  2. #2
    Join Date
    Aug 2004
    Posts
    1,075

    Default

    The main thing you'll want to focus on for Neo4j is writing the implementations of ConnectionRepository and UsersConnectionRepository. The difference between these two interfaces can be a bit confusing at first, so let me clear it up by saying that UsersConnectionRepository has responsibilities that span all users in an application while ConnectionRepository's responsibilities are for managing connections for a single user (indeed, one request-scoped instance of a ConnectionRepository will be created for each user). UsersConnectionRepository's main job is to create a ConnectionRepository for a given user as well as lookup user IDs given a connection. ConnectionRepository's job is to add, remove, and otherwise maintain connections for a given user.

    As an example, consider the JDBC implementations at https://github.com/SpringSource/spri...l/connect/jdbc.

    I think that the trick in implementing this will be in not forcing a specific graph or node structure for how users are kept in Neo4j. I'd think that the best approach here is probably to have the "userId" parameter passed into UsersConnectionRepository.createConnectionReposito ry()...and ultimately to the ConnectionRepository implementation's constructor...contain the node ID of the user to create the connection for. The only flaw in that thinking is that (as I understand it) any once-used-but-no-longer-used node IDs may be reused and therefore be non-unique over time.

    Even so, that may not be a problem. (Thinking out loud) Your connection repository could create connections as nodes related to whatever node is identified by the given node ID. That node won't be removed until the relationship to the connection is removed, so the node ID will be unique over any period of time for which the connection exists.

    The other trick would be what the Connection node would look like. If you're planning on using Spring Data Neo4j's annotations, you should avoid annotating the existing Connection interface or its implementations, as they will also be used in non-Neo4j apps. Instead, you might subclass/wrap/copy the existing Connection data into a Neo4j-specific type for purposes of persistence. You could also go native Neo4j instead of using Spring Data Neo4j and create the nodes manually--this also has the benefit of not requiring the additional dependency on Spring Data (not that I don't like Spring Data--I really do like it--but I just would avoid the dependency on it if I could).

    Hopefully this message proves more useful than confusing. If you have any questions, don't hesitate to ask.
    Craig Walls
    Spring Social Project Lead

  3. #3
    Join Date
    Jul 2012
    Posts
    10

    Default

    That is great feedback, thank you Craig.

    I think the issue is, that I do not want to create Neo4j nodes without any connection to my existing user nodes within my system. So there must be a reference node, when creating a ConnectionRepository.

    Regarding spring-data: I see your point there, especially when it comes to a general module. Maybe this can be done in an iteration. I will try with spring data first and see how far I come.

    The JDBC uses the JdbcTemplate and a set datasource attribute. For Neo4j i do have the Neo4jTemplate, but I think I need to define the graphDatabase bean somewhere in my application, to access it. Right?

    HTML Code:
    <bean id="graphDbService" class="org.neo4j.kernel.EmbeddedGraphDatabase"
         init-method="enableRemoteShell" destroy-method="shutdown">
    
         <constructor-arg index="0" value="data/neo4j-db"/>
             <constructor-arg index="1" ref="configuration"  />
    </bean>

    The Domain Model Should then be sth. like this: Bildschirmfoto 2012-07-06 um 11.20.15.jpg

    Therefore I would have the following classes:
    Neo4jConnectionRepository extends GraphRepository<Neo4jSocialUser>
    Neo4jUsersConnectionRepository
    Neo4jSocialUser

    while the SocialUser would be the domain class for the Neo4j node like it is displayed on the screenshot.

  4. #4
    Join Date
    Aug 2004
    Posts
    1,075

    Default

    Quote Originally Posted by maciossek View Post
    I think the issue is, that I do not want to create Neo4j nodes without any connection to my existing user nodes within my system. So there must be a reference node, when creating a ConnectionRepository.
    We're in agreement here and yes, when creating the Neo4jConnectionRepository, it must be given *something* to reference the user node for whom the connections are being created. Per the UsersConnectionRepository interface, the createConnectionRepository() method takes a String which is the userId. For Neo4j, that can be a String containing the node ID fo the user node for which the connections will managed. It's a bit odd, as the node ID would really be a numeric value. But the signature of that method is String, so I guess a conversion to/from String will be required to satisfy the method signature.

    The JDBC uses the JdbcTemplate and a set datasource attribute. For Neo4j i do have the Neo4jTemplate, but I think I need to define the graphDatabase bean somewhere in my application, to access it. Right?
    In the case of JDBC, JdbcUsersConnectionRepository is given a DataSource, from which is creates a JdbcTemplate. Likewise, Neo4jUsersConnectionRepository should be given the most basic thing it can be given to access the database. If you're going to use Neo4jTemplate internally, that's fine (except for the dependency issue I mentioned before), but Neo4jUsersConnectionRepository should be created with something lower-level, such as the graph database bean...pretty much what you said.

    Therefore I would have the following classes:
    Neo4jConnectionRepository extends GraphRepository<Neo4jSocialUser>
    Neo4jUsersConnectionRepository
    Neo4jSocialUser
    I'm not so sure I'd have Neo4jConnectionRepository extend GraphRepository. I'd just have it implement ConnectionRepository and internally use either Neo4jTemplate to do its work or (better, for dependency reasons) work with the database natively.

    In short, even if you're using Spring Data Neo4j internally, I'd keep it out of the external contract of those clasess so that you can rip it out later without changing the contract. Ideally, SDN wouldn't even be a dependency...but I understand your desire for an iterative approach using SDN to start. Just try to avoid getting too tied to SDN in the external contract so that it won't be hard to remove it in a later iteration.
    Craig Walls
    Spring Social Project Lead

  5. #5
    Join Date
    Jul 2012
    Posts
    10

    Default

    Is there a possibility to load the spring social configuration class after the XML definitions? My problem is, that this causes an error:


    Code:
    @Bean
    public UsersConnectionRepository usersConnectionRepository() {
        return new Neo4jUsersConnectionRepository(neo4jTemplate, connectionFactoryLocator(), textEncryptor);
    }
    No matching bean of type [org.springframework.data.neo4j.support.Neo4jTempla te] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Aut owired(required=true)}

  6. #6
    Join Date
    Jul 2012
    Posts
    10

    Default

    For Neo4j, that can be a String containing the node ID fo the user node for which the connections will managed.
    Peter Neubauer told me that I should never rely on the Node's ID. He said, that the ID might change after a DB crash, or when nodes are getting deleted. Neo4j does not need the connection between nodes, while they are getting created, but it makes the most sense. So using the module most likely expects nodes which map to a given userID. I think UUIDs could work fine.

    I still have troubles getting the application up and running. It might still be the issue with the bean configurations. I am going to drop neo4jTemplate and try using graphDBService instead, maybe that works better.

  7. #7
    Join Date
    Aug 2004
    Posts
    1,075

    Default

    You're right about node IDs...I had thought of that and that's why in my original post I said that it might not be best, but it might work, because you're not going to delete the user node without also eliminating all relationships tied to it (including the relationship to a FB/Twitter/etc connection node. In other words, the node ID will be constant as long as the connection exists. That said, I didn't consider that the node IDs might change when the DB crashes...in fact, I wasn't even aware of this scenario--I was only aware of node IDs changing and then being reused when a node is deleted.

    In that case, you should consider expecting the user node to have a certain property that can be used to uniquely identify the user. The Spring Social Neo4j code could default to a reasonable property name (e.g., "userId"), but also allow for that to be overridden with a different property name.
    Craig Walls
    Spring Social Project Lead

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •