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