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/

Reply via email to