Package org.hibernate.test.cache.infinispan.functional.cluster

Source Code of org.hibernate.test.cache.infinispan.functional.cluster.EntityCollectionInvalidationTestCase$MyListener

/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2009-2011, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors.  All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA  02110-1301  USA
*/
package org.hibernate.test.cache.infinispan.functional.cluster;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import javax.transaction.TransactionManager;

import org.infinispan.Cache;
import org.infinispan.manager.CacheContainer;
import org.infinispan.notifications.Listener;
import org.infinispan.notifications.cachelistener.annotation.CacheEntryVisited;
import org.infinispan.notifications.cachelistener.event.CacheEntryVisitedEvent;
import org.infinispan.util.logging.Log;
import org.infinispan.util.logging.LogFactory;
import org.jboss.util.collection.ConcurrentSet;
import org.junit.Test;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cache.spi.CacheKey;
import org.hibernate.test.cache.infinispan.functional.Contact;
import org.hibernate.test.cache.infinispan.functional.Customer;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

/**
* EntityCollectionInvalidationTestCase.
*
* @author Galder Zamarreño
* @since 3.5
*/
public class EntityCollectionInvalidationTestCase extends DualNodeTestCase {
  private static final Log log = LogFactory.getLog( EntityCollectionInvalidationTestCase.class );

  private static final long SLEEP_TIME = 50l;
  private static final Integer CUSTOMER_ID = new Integer( 1 );

  static int test = 0;

  @Test
  public void testAll() throws Exception {
    log.info( "*** testAll()" );

    // Bind a listener to the "local" cache
    // Our region factory makes its CacheManager available to us
    CacheContainer localManager = ClusterAwareRegionFactory.getCacheManager( DualNodeTestCase.LOCAL );
    // Cache localCache = localManager.getCache("entity");
    Cache localCustomerCache = localManager.getCache( Customer.class.getName() );
    Cache localContactCache = localManager.getCache( Contact.class.getName() );
    Cache localCollectionCache = localManager.getCache( Customer.class.getName() + ".contacts" );
    MyListener localListener = new MyListener( "local" );
    localCustomerCache.addListener( localListener );
    localContactCache.addListener( localListener );
    localCollectionCache.addListener( localListener );
    TransactionManager localTM = DualNodeJtaTransactionManagerImpl.getInstance( DualNodeTestCase.LOCAL );

    // Bind a listener to the "remote" cache
    CacheContainer remoteManager = ClusterAwareRegionFactory.getCacheManager( DualNodeTestCase.REMOTE );
    Cache remoteCustomerCache = remoteManager.getCache( Customer.class.getName() );
    Cache remoteContactCache = remoteManager.getCache( Contact.class.getName() );
    Cache remoteCollectionCache = remoteManager.getCache( Customer.class.getName() + ".contacts" );
    MyListener remoteListener = new MyListener( "remote" );
    remoteCustomerCache.addListener( remoteListener );
    remoteContactCache.addListener( remoteListener );
    remoteCollectionCache.addListener( remoteListener );
    TransactionManager remoteTM = DualNodeJtaTransactionManagerImpl.getInstance( DualNodeTestCase.REMOTE );

    SessionFactory localFactory = sessionFactory();
    SessionFactory remoteFactory = secondNodeEnvironment().getSessionFactory();

    try {
      assertTrue( remoteListener.isEmpty() );
      assertTrue( localListener.isEmpty() );

      log.debug( "Create node 0" );
      IdContainer ids = createCustomer( localFactory, localTM );

      assertTrue( remoteListener.isEmpty() );
      assertTrue( localListener.isEmpty() );

      // Sleep a bit to let async commit propagate. Really just to
      // help keep the logs organized for debugging any issues
      sleep( SLEEP_TIME );

      log.debug( "Find node 0" );
      // This actually brings the collection into the cache
      getCustomer( ids.customerId, localFactory, localTM );

      sleep( SLEEP_TIME );

      // Now the collection is in the cache so, the 2nd "get"
      // should read everything from the cache
      log.debug( "Find(2) node 0" );
      localListener.clear();
      getCustomer( ids.customerId, localFactory, localTM );

      // Check the read came from the cache
      log.debug( "Check cache 0" );
      assertLoadedFromCache( localListener, ids.customerId, ids.contactIds );

      log.debug( "Find node 1" );
      // This actually brings the collection into the cache since invalidation is in use
      getCustomer( ids.customerId, remoteFactory, remoteTM );

      // Now the collection is in the cache so, the 2nd "get"
      // should read everything from the cache
      log.debug( "Find(2) node 1" );
      remoteListener.clear();
      getCustomer( ids.customerId, remoteFactory, remoteTM );

      // Check the read came from the cache
      log.debug( "Check cache 1" );
      assertLoadedFromCache( remoteListener, ids.customerId, ids.contactIds );

      // Modify customer in remote
      remoteListener.clear();
      ids = modifyCustomer( ids.customerId, remoteFactory, remoteTM );
      sleep( 250 );
      assertLoadedFromCache( remoteListener, ids.customerId, ids.contactIds );

      // After modification, local cache should have been invalidated and hence should be empty
      assertEquals( 0, getValidKeyCount( localCollectionCache.keySet() ) );
      assertEquals( 0, getValidKeyCount( localCustomerCache.keySet() ) );
    }
    catch (Exception e) {
      log.error( "Error", e );
      throw e;
    }
    finally {
      // cleanup the db
      log.debug( "Cleaning up" );
      cleanup( localFactory, localTM );
    }
  }

  private IdContainer createCustomer(SessionFactory sessionFactory, TransactionManager tm)
      throws Exception {
    log.debug( "CREATE CUSTOMER" );

    tm.begin();

    try {
      Session session = sessionFactory.getCurrentSession();
      Customer customer = new Customer();
      customer.setName( "JBoss" );
      Set<Contact> contacts = new HashSet<Contact>();

      Contact kabir = new Contact();
      kabir.setCustomer( customer );
      kabir.setName( "Kabir" );
      kabir.setTlf( "1111" );
      contacts.add( kabir );

      Contact bill = new Contact();
      bill.setCustomer( customer );
      bill.setName( "Bill" );
      bill.setTlf( "2222" );
      contacts.add( bill );

      customer.setContacts( contacts );

      session.save( customer );
      tm.commit();

      IdContainer ids = new IdContainer();
      ids.customerId = customer.getId();
      Set contactIds = new HashSet();
      contactIds.add( kabir.getId() );
      contactIds.add( bill.getId() );
      ids.contactIds = contactIds;

      return ids;
    }
    catch (Exception e) {
      log.error( "Caught exception creating customer", e );
      try {
        tm.rollback();
      }
      catch (Exception e1) {
        log.error( "Exception rolling back txn", e1 );
      }
      throw e;
    }
    finally {
      log.debug( "CREATE CUSTOMER -  END" );
    }
  }

  private Customer getCustomer(Integer id, SessionFactory sessionFactory, TransactionManager tm) throws Exception {
    log.debug( "Find customer with id=" + id );
    tm.begin();
    try {
      Session session = sessionFactory.getCurrentSession();
      Customer customer = doGetCustomer( id, session, tm );
      tm.commit();
      return customer;
    }
    catch (Exception e) {
      try {
        tm.rollback();
      }
      catch (Exception e1) {
        log.error( "Exception rolling back txn", e1 );
      }
      throw e;
    }
    finally {
      log.debug( "Find customer ended." );
    }
  }

  private Customer doGetCustomer(Integer id, Session session, TransactionManager tm) throws Exception {
    Customer customer = (Customer) session.get( Customer.class, id );
    // Access all the contacts
    for ( Iterator it = customer.getContacts().iterator(); it.hasNext(); ) {
      ((Contact) it.next()).getName();
    }
    return customer;
  }

  private IdContainer modifyCustomer(Integer id, SessionFactory sessionFactory, TransactionManager tm)
      throws Exception {
    log.debug( "Modify customer with id=" + id );
    tm.begin();
    try {
      Session session = sessionFactory.getCurrentSession();
      IdContainer ids = new IdContainer();
      Set contactIds = new HashSet();
      Customer customer = doGetCustomer( id, session, tm );
      customer.setName( "NewJBoss" );
      ids.customerId = customer.getId();
      Set<Contact> contacts = customer.getContacts();
      for ( Contact c : contacts ) {
        contactIds.add( c.getId() );
      }
      Contact contact = contacts.iterator().next();
      contacts.remove( contact );
      contactIds.remove( contact.getId() );
      ids.contactIds = contactIds;
      contact.setCustomer( null );

      session.save( customer );
      tm.commit();
      return ids;
    }
    catch (Exception e) {
      try {
        tm.rollback();
      }
      catch (Exception e1) {
        log.error( "Exception rolling back txn", e1 );
      }
      throw e;
    }
    finally {
      log.debug( "Find customer ended." );
    }
  }

  private void cleanup(SessionFactory sessionFactory, TransactionManager tm) throws Exception {
    tm.begin();
    try {
      Session session = sessionFactory.getCurrentSession();
      Customer c = (Customer) session.get( Customer.class, CUSTOMER_ID );
      if ( c != null ) {
        Set contacts = c.getContacts();
        for ( Iterator it = contacts.iterator(); it.hasNext(); ) {
          session.delete( it.next() );
        }
        c.setContacts( null );
        session.delete( c );
      }

      tm.commit();
    }
    catch (Exception e) {
      try {
        tm.rollback();
      }
      catch (Exception e1) {
        log.error( "Exception rolling back txn", e1 );
      }
      log.error( "Caught exception in cleanup", e );
    }
  }

  private void assertLoadedFromCache(MyListener listener, Integer custId, Set contactIds) {
    assertTrue(
        "Customer#" + custId + " was in cache", listener.visited.contains(
        "Customer#"
            + custId
    )
    );
    for ( Iterator it = contactIds.iterator(); it.hasNext(); ) {
      Integer contactId = (Integer) it.next();
      assertTrue(
          "Contact#" + contactId + " was in cache", listener.visited.contains(
          "Contact#"
              + contactId
      )
      );
      assertTrue(
          "Contact#" + contactId + " was in cache", listener.visited.contains(
          "Contact#"
              + contactId
      )
      );
    }
    assertTrue(
        "Customer.contacts" + custId + " was in cache", listener.visited
        .contains( "Customer.contacts#" + custId )
    );
  }

  protected int getValidKeyCount(Set keys) {
      return keys.size();
  }

  @Listener
  public static class MyListener {
    private static final Log log = LogFactory.getLog( MyListener.class );
    private Set<String> visited = new ConcurrentSet<String>();
    private final String name;

    public MyListener(String name) {
      this.name = name;
    }

    public void clear() {
      visited.clear();
    }

    public boolean isEmpty() {
      return visited.isEmpty();
    }

    @CacheEntryVisited
    public void nodeVisited(CacheEntryVisitedEvent event) {
      log.debug( event.toString() );
      if ( !event.isPre() ) {
        CacheKey cacheKey = (CacheKey) event.getKey();
        Integer primKey = (Integer) cacheKey.getKey();
        String key = cacheKey.getEntityOrRoleName() + '#' + primKey;
        log.debug( "MyListener[" + name + "] - Visiting key " + key );
        // String name = fqn.toString();
        String token = ".functional.";
        int index = key.indexOf( token );
        if ( index > -1 ) {
          index += token.length();
          key = key.substring( index );
          log.debug( "MyListener[" + name + "] - recording visit to " + key );
          visited.add( key );
        }
      }
    }
  }

  private class IdContainer {
    Integer customerId;
    Set<Integer> contactIds;
  }

}
TOP

Related Classes of org.hibernate.test.cache.infinispan.functional.cluster.EntityCollectionInvalidationTestCase$MyListener

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.