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

Reply via email to