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