On 28/11/23 18:19, GCHQDeveloper29 wrote:
Hi,
The updateAttr function in my prior email exists within my 'logic' class.
I.e. org.apache.syncope.core.logic.AttributeLogic
The second code block within the same email is what would/could exist within
the Rest-CXF class of the extension.
If I remove the @Transactional annotation on the updateAttr function, I start
getting 'Could not find EntityManager for domain Master' exceptions, from my
userDAO.findByUsername() call, (userDAO being autowired within the logic class).
I have also tried passing through the UserDAO from the LogicContext class
however that does not work either.
If the only reason to call
userDAO.findByUsername()
is to find the actual user uuid because your "key" variable " can either be the
username or the UUID of the user", then I would suggest to implement something like
AbstractAnyService#findActualKey [1] which is using only the method
userDAO.findKey()
which is itself annotated as @Transactional and can be used outside of any
transaction.
Alternatively, you can also leverage
userDAO.findUsername()
This will allow to remove @Transactional from the updateAttr method.
Regards.
[1]
https://github.com/apache/syncope/blob/3_0_X/core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AbstractService.java#L64
On Tuesday, 28 November 2023 at 13:14, Francesco Chicchiriccò
<ilgro...@apache.org> wrote:
Hi,
I assume the code below lies inside a REST service implementation class.
Basically, it manipulates payload objects (UserCR, AttrPatch and so on) then
invokes UserLogic for actual processing.
If so, then you should remove @Transactional from such method as by doing so
you are essentially breaking the transaction mechanism as managed by UserLogic.
HTH
Regards.
On 28/11/23 11:53, GCHQDeveloper29 wrote:
Hi there,
I'm hoping to gain some advice (or report a bug in the case I've not just been
a fool!).
I'm currently on version 3.0.4, although plan to move to 3.0.5 soon, and am
using version 1.5.7 of the LDAP connector.
I have a slightly different version of the following function sat behind a rest
endpoint, but am observing peculiar behaviour when calling the rest endpoint
(hence triggering an update in userLogic).
```
@Transactional
public Response updateAttr(final UpdateAttrTO updateAttrTO, final String
attribute)
{
// key can either be the username or the UUID of the user
String key = updateAttrTO.getKey();
String attrVal = updateAttrTO.getAttrVal();
try {
// getUser gets the user object, first trying by username, then by UUID
User user = getUser(key);
String uuid = user.getKey();
String username = user.getUsername();
// Create the patch and user update request
Attr attr = new Attr.Builder(attribute)
.value(attrVal)
.build();
AttrPatch patch = new AttrPatch.Builder(attr)
.operation(attrVal == "" ? PatchOperation.DELETE : PatchOperation.ADD_REPLACE)
.build();
UserUR userUR = new UserUR.Builder(uuid)
.plainAttr(patch)
.build();
// Attempt to patch the user
ProvisioningResult<UserTO> provisioningResult = userLogic.update(userUR, false);
return Response.ok().build();
}
// Catch if a user cannot be found
catch (NotFoundException e)
{
return Response.status(400, e.getLocalizedMessage()).build();
}
// Catch any other unanticipated error
catch (Exception e)
{
return Response.status(500, e.getLocalizedMessage()).build();
}
}
```
The above function can be called as below (I use rest parameters in actuality):
```
UpdateAttrTO updateAttrTO = new UpdateAttrTO();
updateAttrTO.setKey("ExampleKey");
updateAttrTO.setAttrVal("ExampleAttrVal");
return updateAttr(updateAttrTO, "ExampleAttribute");
```
When I do this, the value gets updated within syncopes database, however the
propogation task (to an LDAP connector), updates the downstream resource with
the previous value.
For example, if I were to do the following for a user "user123", that does not initially
have "ExampleAttribute" set, the downstream resource is always one value behind:
```
// ----
// Syncope value - N/A
// Downstream LDAP resource - N/A
// ----
UpdateAttrTO updateAttrTO1 = new UpdateAttrTO();
updateAttrTO1.setKey("user123");
updateAttrTO1.setAttrVal("1111");
updateAttr(updateAttrTO1, "ExampleAttribute");
// -----
// Syncope value - "1111"
// Downstream LDAP resource - N/A
// -----
UpdateAttrTO updateAttrTO2 = new UpdateAttrTO();
updateAttrTO2.setKey("user123");
updateAttrTO2.setAttrVal("2222");
updateAttr(updateAttrTO2, "ExampleAttribute");
// ----
// Syncope value - "2222"
// Downstream LDAP resource - "1111"
// ----
```
Hopefully I explained the situation sufficiently, if not please let me know and
I can try to give some more detail.
Kind Regards,
GCHQDeveloper29.
--
Francesco Chicchiriccò
Tirasa - Open Source Excellence
http://www.tirasa.net/
Member at The Apache Software Foundation
Syncope, Cocoon, Olingo, CXF, OpenJPA, PonyMail
http://home.apache.org/~ilgrosso/