If roleRegion do not have a lot of entries, can you make it a replicated one?
On Mon, Jan 6, 2020 at 5:02 PM Eric Shu <e...@pivotal.io> wrote: > Sorry, did not realize that it's a many to many relations. The above > mentioned colocation suggestion would not help due to the roles are in a > map (can not achieve the colocation). > > Regards, > Eric > > On Mon, Jan 6, 2020 at 4:59 PM Eric Shu <e...@pivotal.io> wrote: > >> Please note distributed transaction is not a supported feature in Geode >> (not fully implemented). There was discussion before whether we should >> remove the code or throw exception when transaction is set to distributed. >> However, neither was being done. >> >> Currently in Geode, if you want to have a transaction involving two >> partitioned regions, they must be colocated -- (the entries touched in a >> transaction must reside in the primary buckets on a same member node.) >> >> To achieve the colocation, one option in your case is to add roleId in >> UserRegion key (composite key of userId and roleId) and partitioned on >> roleId and colocated with role region. It is not optimal (need to have an >> additional field in a key), but is a workaround. >> >> Regards, >> Eric >> >> >> On Mon, Jan 6, 2020 at 11:54 AM anurag.botre....@gmail.com < >> anurag.botre....@gmail.com> wrote: >> >>> Stackoverflow Question Link >>> < >>> https://stackoverflow.com/questions/59581006/org-apache-geode-cache-unsupportedoperationintransactionexception> >>> >>> >>> Getting below exception while updating entry in the cache while >>> establishing >>> Many to Many relation. >>> >>> org.apache.geode.cache.UnsupportedOperationInTransactionException: >>> Expected >>> size of 1 {[/__PR/_B__User_101]} for >>> target=192.168.1.2(cacheServer2:7756)<v1>:41001 during a distributed >>> transaction but got 2 {[[], [DistTxThinEntryState: ,regionVersion=2 >>> ,tailKey=440 ,memberID=null]]} >>> at >>> >>> org.apache.geode.internal.cache.DistTXStateProxyImplOnCoordinator.populateEntryEventMap(DistTXStateProxyImplOnCoordinator.java:576) >>> at >>> >>> org.apache.geode.internal.cache.DistTXStateProxyImplOnCoordinator.doPrecommit(DistTXStateProxyImplOnCoordinator.java:484) >>> at >>> >>> org.apache.geode.internal.cache.DistTXStateProxyImplOnCoordinator.commit(DistTXStateProxyImplOnCoordinator.java:88) >>> at >>> >>> org.apache.geode.internal.cache.TXManagerImpl.commit(TXManagerImpl.java:426) >>> at >>> >>> com.trendcore.cache.peertopeer.service.UserServiceImpl.attachRoleToUser(UserServiceImpl.java:108) >>> at >>> >>> com.trendcore.cache.peertopeer.CacheApplication.attachRoleToUser(CacheApplication.java:121) >>> Cache Configuration -> It's Peer to Peer configration with 2 regions. >>> >>> Properties properties = new Properties(); >>> properties.setProperty("locators", "localhost[13489]"); >>> properties.setProperty("mcast-address", "224.0.0.0"); >>> properties.setProperty("mcast-port", "0"); >>> properties.setProperty(NAME, "cacheServer1"); >>> >>> CacheFactory cacheFactory = new CacheFactory(this.cacheConfiguration); >>> cache = cacheFactory.create(); >>> User Region >>> >>> RegionFactory<Long, User> regionFactory = >>> this.cache.createRegionFactory(RegionShortcut.PARTITION); >>> userRegion = regionFactory.create(USER_REGION); >>> Role Region >>> >>> RegionFactory<Long, Role> regionFactory = >>> this.cache.createRegionFactory(RegionShortcut.PARTITION); >>> roleRegion = regionFactory.create(ROLE_REGION); >>> User model resides in User region >>> >>> public class User implements Serializable{ >>> private Long id; >>> private String username; >>> private Map<Long,Object> roles; >>> >>> //Getters , Setters >>> >>> public void addRole(Long roleId) { >>> roles.put(roleId,null); >>> } >>> } >>> Role model resides in Role region >>> >>> public class Role implements Serializable { >>> >>> private Long id; >>> private String roleName; >>> >>> //getters , setters >>> } >>> Users and roles are inserted in the respective regions using below code. >>> >>> public void insertUser(User user) { >>> CacheTransactionManager cacheTransactionManager = >>> cache.getCacheTransactionManager(); >>> try { >>> cacheTransactionManager.begin(); >>> userRegion.put(user.getId(), user); >>> cacheTransactionManager.commit(); >>> } catch (Exception e) { >>> cacheTransactionManager.rollback(); >>> } >>> } >>> >>> >>> >>> public void insertRole(Role role) { >>> CacheTransactionManager cacheTransactionManager = >>> cache.getCacheTransactionManager(); >>> try { >>> cacheTransactionManager.begin(); >>> roleRegion.put(role.getId(), role); >>> cacheTransactionManager.commit(); >>> } catch (Exception e) { >>> cacheTransactionManager.rollback(); >>> } >>> } >>> When any roleIds are put in existing cache user object then above >>> exception >>> is thrown. >>> >>> public void attachRoleToUser(Long userId, Long roleId) { >>> Region<Long, User> userRegion = cache.getRegion(USER_REGION); >>> Region<Long, Role> roleRegion = cache.getRegion("Role"); >>> CacheTransactionManager cacheTransactionManager = >>> cache.getCacheTransactionManager(); >>> try { >>> cacheTransactionManager.setDistributed(true); >>> cacheTransactionManager.begin(); >>> >>> Role role = roleRegion.get(roleId); >>> >>> if (role != null) { >>> User user = userRegion.get(userId); >>> user.addRole(role.getId()); >>> userRegion.put(userId,user); >>> } >>> cacheTransactionManager.commit(); >>> } catch (Exception e) { >>> try { >>> cacheTransactionManager.rollback(); >>> }catch (Exception rbe){ >>> >>> } >>> throw new RuntimeException(e); >>> } >>> } >>> Any guidance in this case will be appreciated. >>> >>> >>> >>> >>> Changed, attach user to role method to below and there is no exception. >>> >>> Region<Long, User> userRegion = cache.getRegion(USER_REGION); >>> Region<Long, Role> roleRegion = cache.getRegion("Role"); >>> CacheTransactionManager cacheTransactionManager = >>> cache.getCacheTransactionManager(); >>> try { >>> //This is change fetching role information outside transaction >>> boundry. >>> Role role = roleRegion.get(roleId); >>> >>> cacheTransactionManager.setDistributed(true); >>> cacheTransactionManager.begin(); >>> >>> //This line is causing below exception >>> >>> //org.apache.geode.cache.UnsupportedOperationInTransactionException: >>> Expected size of 1 {[/__PR/_B__User_101]} >>> //Role role = roleRegion.get(roleId); >>> >>> if (role != null) { >>> User user = userRegion.get(userId); >>> user.addRole(role.getId()); >>> userRegion.put(userId,user); >>> } >>> cacheTransactionManager.commit(); >>> } catch (Exception e) { >>> try { >>> if(cacheTransactionManager != null && >>> cacheTransactionManager.exists()) >>> cacheTransactionManager.rollback(); >>> }catch (Exception rbe){ >>> >>> } >>> throw new RuntimeException(e); >>> } >>> And there is no exception. >>> >>> However need more information on below points. >>> >>> 1.Transaction was set to distributed. >>> 2.User and Role both regions were involved in this case transaction >>> failed, >>> with exception UnsupportedOperationInTransactionException >>> 3.Distributed transactions are not supported for multiple regions. >>> >>> >>> >>> -- >>> Sent from: >>> http://apache-geode-incubating-developers-forum.70738.x6.nabble.com/ >>> >>