Create
cancel
Showing results for 
Search instead for 
Did you mean: 
Sign up Log in

CrowdService.updateUser(...) causes "Write operations are not allowed in read-only mode"?

Gary Weaver
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
December 12, 2011

Using the following in a custom authenticator in Confluence 3.5/4.0:

com.atlassian.crowd.embedded.api.User crowdUser = crowdService.getUser(user.getName());

    ImmutableUser.Builder userBuilder = new ImmutableUser.Builder();
    // clone the user before making mods
    userBuilder.active(crowdUser.isActive());
    userBuilder.directoryId(crowdUser.getDirectoryId());
    userBuilder.displayName(crowdUser.getDisplayName());
    userBuilder.emailAddress(crowdUser.getEmailAddress());
    userBuilder.name(crowdUser.getName());

    // ... only do the following if name/email is different
    crowdService.updateUser(userBuilder.toUser());

in one customer environment sometimes produces the following error. Any ideas as to what might be wrong that we could relay to this customer, or is this a problem with our implementation?:

org.springframework.dao.InvalidDataAccessApiUsageException: Write operations are not allowed in read-only mode (FlushMode.NEVER): Turn your Session into FlushMode.AUTO or remove 'readOnly' marker from transaction definition.
	at org.springframework.orm.hibernate.HibernateTemplate.checkWriteOperationAllowed(HibernateTemplate.java:1000)
	at org.springframework.orm.hibernate.HibernateTemplate$11.doInHibernate(HibernateTemplate.java:590)
	at org.springframework.orm.hibernate.HibernateTemplate.execute(HibernateTemplate.java:370)
	at org.springframework.orm.hibernate.HibernateTemplate.update(HibernateTemplate.java:588)
	at org.springframework.orm.hibernate.HibernateTemplate.update(HibernateTemplate.java:584)
	at com.atlassian.crowd.embedded.hibernate2.HibernateUserDao.update(HibernateUserDao.java:225)
	at com.atlassian.confluence.user.crowd.CachedCrowdUserDao.update(CachedCrowdUserDao.java:177)
	at com.atlassian.crowd.directory.AbstractInternalDirectory.updateUser(AbstractInternalDirectory.java:396)
	at com.atlassian.crowd.manager.directory.DirectoryManagerGeneric.updateUser(DirectoryManagerGeneric.java:352)
	at com.atlassian.crowd.manager.application.ApplicationServiceGeneric.updateUser(ApplicationServiceGeneric.java:434)
	at com.atlassian.crowd.embedded.core.CrowdServiceImpl.updateUser(CrowdServiceImpl.java:315)

Note: I created a ticket for this: CWD-2733

2 answers

1 accepted

Comments for this post are closed

Community moderators have prevented the ability to post new answers.

Post a new question

1 vote
Answer accepted
Joe Clark
Atlassian Team
Atlassian Team members are employees working across the company in a wide variety of roles.
December 29, 2011

Hey Gary... Just letting you know I've just encountered this problem, too, while writing a custom authenticator of my own. My initial thought is that the authenticator code that interacts with Embedded Crowd needs to be wrapped in a read/write transaction in order to update the crowd tables successfully.

I'm chasing this up now and will update my answer when I have some answers of my own :)

EDIT: Update

Yes, my initial suspicions were correct. You need to wrap any code that causes updates to the database in a new transaction template. An example of how to do this is here: https://developer.atlassian.com/display/CONFDEV/Hibernate+Sessions+and+Transaction+Management+Guidelines (see the section on 'Manual Transaction Management')

Gary Weaver
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
January 2, 2012

Joe,

Do I need to do that in plugins, too, or just authenticators? For example, we add groups, users, etc. in the Custom Space User Management (CSUM) plugin using embedded Crowd, etc. I totally appreciate the documentation and example code. However, I've put in a bug, because I really don't think this is a good idea. It just doesn't seem very "Atlassian" to require this much code just to do a user update, and it would be great to see a patch we could have users apply. But, there is probably a perfectly sound argument for why things are now so complicated, and I'd like to hear it if it can't be fixed:

https://jira.atlassian.com/browse/CWD-2745

Thanks!

Gary

Joe Clark
Atlassian Team
Atlassian Team members are employees working across the company in a wide variety of roles.
January 3, 2012

Authenticators are a special case, since they are custom code that lives outside the plugin framework. Lots of the bells and whistles that make plugin development easy (automatic dependency injection, transaction management, etc.) just aren't available for authenticators, which leads to a lot of hand-rolled plumbing code to accomplish the same thing.

As far as I know (and sadly I am no guru when it comes to Confluence's transaction management architecture), you may need to do the same transaction-wrapping code in your CSUM plugin (although as you can see in the doco, transaction management in plugins uses a SAL API that is is slightly less lines of code).

0 votes
JohnJ July 19, 2012

Is this true for Jira?

I'm trying to port the confluence authenticator to Jira 5.x and running into problems fetching the transactionManager. This works in the confluence authentator but not in the jira authenticator.

(PlatformTransactionManager) ContainerManager.getComponent("transactionManager");

Joe Clark
Atlassian Team
Atlassian Team members are employees working across the company in a wide variety of roles.
July 19, 2012

In JIRA, I think you need to use ComponentAccessor, instead of ContainerManager

JohnJ July 19, 2012

No "getTransactionManager" method in ComponentAccessor. Am I overlooking something?

Joe Clark
Atlassian Team
Atlassian Team members are employees working across the company in a wide variety of roles.
July 22, 2012

Try getComponent(PlatformTransactionManager.class) or getOSGiComponentInstanceOfType(PlatformTransactionManager.class)

TAGS
AUG Leaders

Atlassian Community Events