Announcement Announcement Module
Collapse
No announcement yet.
Strange behavior using CrudRepository (also GemfireRepository) Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Strange behavior using CrudRepository (also GemfireRepository)

    I've been playing around with the new Spring-Gemfire project and have gotten most to work pretty smoothly. However, I have run into one problem using the CrudRepository and GemfireRepository interfaces. Let me set up the problem.

    Here is my main object being fetched.
    Code:
    @Region("Accounts")
    public class Account extends AbstractPersistentEntity {
    	private static final long serialVersionUID = 1L;
    	private String name;
    	private String acctNumber;
    	private List<Beneficiary> beneficiaries = new ArrayList<Beneficiary>();
    	
    	@PersistenceConstructor
    	public Account(Long id, String name, String acctNumber) {
    		super(id);
    		this.name = name;
    		this.acctNumber = acctNumber;
    	}
    Here is my Repository interface with one simple query
    Code:
    public interface AccountRepository extends CrudRepository<Account, Long> {
    
    	List<Account> findByName(String name); 
    }
    And... my gemfire configuration
    Code:
        <gfe:client-region id="accountRegion" name="Accounts" data-policy="empty"/>
        
        <gfe:pool id="gemfirePool">
        	<gfe:locator host="localhost" port="41111"/>
        </gfe:pool>
        
         <bean id="gfTemplate" class="org.springframework.data.gemfire.GemfireTemplate">
        	<property name="region" ref="accountRegion" />
        </bean>
        
        <gfe-data:repositories base-package="com.vmware.gfdemo.dao" />
    Finally, here are my tests. I was able to do some basic fetches and queries using the GemfireTemplate with no problem. But in the last test, I get an exception that seems to boil down to this: Region not found: /Accountss

    Code:
    	@Autowired @Qualifier("gfTemplate")
    	private GemfireTemplate accountTemplate;
    	
    	@Autowired
    	private AccountRepository accountRepository;
    
            // This works
    	@Test
    	public void testSimpleGet() {
    		Account a = accountTemplate.get(1);
    		assertEquals("Mark", a.getName());
    	}
    
    	// This works
    	@Test
    	public void testSearchByName() {
    		SelectResults<Account> results =  accountTemplate.find("SELECT * from /Accounts WHERE name=$1","Mark");
    		assertNotNull("Failed to perform find", results);
    		assertEquals("Fetched incorrect number of results", 1,results.size());
    		assertEquals("Failed to fetch Mark", "Mark", results.asList().get(0).getName());
    	}
    	
            // Fails with exception: 
            // Caused by: com.gemstone.gemfire.cache.query.RegionNotFoundException: Region not found:  /Accountss
    	@Test
    	public void testAccountRepository () {
    		List<Account> accounts = accountRepository.findByName("Mark");
    		assertNotNull("Failed to perform query",accounts);
    		assertEquals("Fetched incorrect number of results",1,accounts.size());
    		assertEquals("Failed to fetch Mark", "Mark", accounts.get(0).getName());
    	}
    I'm honestly baffled as to where it gets the the 'Accountss' region when I've clearly designated it as 'Accounts' in the @Region annotation on the Account class.

    Any ideas? Is this a bug or did I miss something incredibly stupid?

    Thanks

  • #2
    Thanks for reporting this. It is fixed and will be in the 1.3.0 release (very soon) https://jira.springsource.org/browse/SGF-156
    Last edited by dturanski; Feb 23rd, 2013, 10:49 AM.

    Comment


    • #3
      Originally posted by dturanski View Post
      Thanks for reporting this. It is fixed and will be in the 1.3.0 release (very soon) https://jira.springsource.org/browse/SGF-156
      Perfect! I tried out the latest snapshot build and it does work now.

      Now, another strange behavior. I tried using the findAll() method (both the one on the CrudRepository and defining my own to return a Set<Account> per some of the examples. While I can invoke accountRepository.count() and get the right number of items back, I can't seem to get anything returned with findAll().

      I don't see anything from the documentation that would indicate that anything more than the above is required but maybe I'm still missing something.

      Comment


      • #4
        Yes. This is a bit tricky because of the way gemfire works.In a client/server configuration count() does a true count of everything in the distributed grid. findAll() and all similar query methods query the local cache. The local cache does not stay in synch by default, and for many applications that's a good thing because you want to cache locally only data your application specifically uses. So if you call repo.findOne(key) you'll get the object. If your client region is configured to store entries locally (the default) then if you call findAll() again, any retrieved objects will be included. However, this leads to some apparent inconsistencies. If you want the local cache to hold the entire region, then subscribe to all cache keys. Enable subscriptions on the pool and register interest in all keys. configured in Spring as:
        Code:
        <gfe:client-region id="Person" pool-name="gemfirePool">
            <gfe:regex-interest pattern=".*" />
        </gfe:client-region>
        
        	 
        <gfe:pool id="gemfirePool" subscription-enabled="true">
               <gfe:server host="localhost" port="40404" />
        </gfe:pool>

        Comment


        • #5
          Originally posted by dturanski View Post
          Yes. This is a bit tricky because of the way gemfire works.In a client/server configuration count() does a true count of everything in the distributed grid. findAll() and all similar query methods query the local cache. The local cache does not stay in synch by default, and for many applications that's a good thing because you want to cache locally only data your application specifically uses.
          Thanks. You confirmed what I was just coming to the conclusion of based on stepping through the code into the bowels of SimpleGemfireRepository, etc. At the end of the day, it invokes region.values(), which in the case of client regions would only return values in the local cache. I should have known I guess but didn't think about how the query was performed.

          This kind of detail might be helpful in the JavaDocs for these classes.

          Thanks again.

          Comment


          • #6
            Actually, I changed findAll() to be consistent with count. I think for the repository abstraction, it makes more sense. You can use other APIs to find out what's in local cache. This won't require any special configuration. see https://jira.springsource.org/browse/SGF-163. Thanks for the feedback

            Comment


            • #7
              Ok - just got a chance to try migrating to the latest 1.3.0.RELEASE version. However, I tried simply changing the version and I'm getting ArtifactDescriptorExceptions. This is always difficult to trace down to the source but I can use 1.3.0.BUILD-SNAPSHOT and things work. Changing to 1.3.0.RELEASE gives me errors regarding 'failure to read artifact descriptor for gemfire 7.0.1'. This isn't in some other repository is it?

              Comment


              • #8
                Gemfire 7.0.1 is in http://repo.springsource.org/plugins-release. It may also be in the gemstone maven repo http://dist.gemstone.com/maven/release. This is a dependency for SDG 1.3.0 but if you are using some other version of GF you can exclude it.

                Comment

                Working...
                X