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/ >> >