Hello, I am trying update relation by REST v1, but failed.
I have a relation like this:
GET /cmdbuild/services/rest/v1/domains/UpdateTest/relations
{"data":[{"_destinationDescription":"C002","_sourceId":12557,"_type":"UpdateTest","_destinationId":12559,"_id":12615,"_destinationType":"LinkTest","_sourceType":"LinkTest","_sourceDescription":"C001"}],"meta":{"total":1}}
So I put one, API returns 500 Internal Server Error (Stack trace is attached below)
PUT /cmdbuild/services/rest/v1/domains/UpdateTest/relations/12615
{"_sourceId":12557,"_type":"UpdateTest","_destinationId":12559,"_id":12615,"_destinationType":"LinkTest","_sourceType":"LinkTest"}
I trace programs commit b890716 on 2.3 branch,
at org.cmdbuild.service.rest.v1.cxf.CxfRelations#update copying Relation instance to RelationDTO, it missed to copy relation Id but at DefaultDataAccessLogic#updateRelation, it uses dto's relationId, so it seems query is always failed.
----
Error logs in tomcat:
WARN 2015-04-13 02:56:39 [org.apache.cxf.jaxrs.impl.WebApplicationExceptionMapper] javax.ws.rs.WebApplicationException: java.util.NoSuchElementException
at org.cmdbuild.service.rest.v1.cxf.WebApplicationExceptionErrorHandler.propagate(WebApplicationExceptionErrorHandler.java:145)
at org.cmdbuild.service.rest.v1.cxf.CxfRelations.update(CxfRelations.java:280)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.cmdbuild.common.reflect.AnnouncingInvocationHandler.invoke(AnnouncingInvocationHandler.java:31)
at com.sun.proxy.$Proxy164.update(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:132)
at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:120)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
at com.sun.proxy.$Proxy22.update(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
(snip)
at java.lang.Thread.run(Thread.java:662)
Caused by: java.util.NoSuchElementException
at java.util.AbstractList$Itr.next(AbstractList.java:350)
at org.cmdbuild.dao.query.DBQueryResult.getOnlyRow(DBQueryResult.java:55)
at org.cmdbuild.dao.query.ForwardingQueryResult.getOnlyRow(ForwardingQueryResult.java:38)
at org.cmdbuild.services.localization.LocalizedQueryResult.getOnlyRow(LocalizedQueryResult.java:57)
at org.cmdbuild.dao.view.user.UserQueryResult.getOnlyRow(UserQueryResult.java:86)
at org.cmdbuild.logic.data.access.DefaultDataAccessLogic.updateRelation(DefaultDataAccessLogic.java:1057)
at org.cmdbuild.service.rest.v1.cxf.CxfRelations.update(CxfRelations.java:278)
... 78 more
-----
org.cmdbuild.service.rest.v1.cxf.CxfRelations
public void update(final String domainId, final Long relationId, final Relation relation) {
final CMDomain targetDomain = dataAccessLogic.findDomain(domainId);
if (targetDomain == null) {
errorHandler.domainNotFound(domainId);
}
try {
final RelationDTO relationDTO = relationDto(targetDomain, relation);
System.out.println("domainId = " + domainId); // DEBUG
System.out.println("relationId = " + relationId); // DEBUG -> 12615 OK
System.out.println("relationDTO =" + relationDTO.relationId); // DEBUG -> null NG?
dataAccessLogic.updateRelation(relationDTO);
} catch (final Exception e) {
errorHandler.propagate(e);
}
}
private RelationDTO relationDto(final CMDomain domain, final Relation relation) {
final RelationDTO relationDTO = new RelationDTO();
relationDTO.domainName = domain.getName();
relationDTO.master = "_1";
relationDTO.addSourceCard(relation.getSource().getId(), relation.getSource().getType());
relationDTO.addDestinationCard(relation.getDestination().getId(), relation.getDestination().getType());
relationDTO.relationAttributeToValue = relation.getValues();
return relationDTO;
}
-----
org.cmdbuild.logic.data.access.DefaultDataAccessLogic#updateRelation
(snip)
condition(attribute(domainAlias, ID_ATTRIBUTE), eq(relationDTO.relationId)), // <- relationDTO.relationId Always NULL
(snip)
I dumped DB query logs,
2015-04-13 02:56:39 JST [3105-50] postgres@cmdbuild LOG: execute <unnamed>: SELECT * FROM (
SELECT
"LinkTest"."Code" AS "LinkTest#Code", "LinkTest"."Description" AS "LinkTest#Description", "LinkTest"."Notes" AS "LinkTest#Notes", "LinkTest"."IdClass"::oid AS "_LinkTest_IdClass", "LinkTest"."Id" AS "_LinkTest_Id", "LinkTest"."User" AS "_LinkTest_User", "LinkTest"."BeginDate" AS "_LinkTest_BeginDate", "DST"."IdClass"::oid AS "_DST_IdClass", "DST"."Id" AS "_DST_Id", "DST"."User" AS "_DST_User", "DST"."BeginDate" AS "_DST_BeginDate", "DOM"."IdDomain"::oid AS "_DOM_IdDomain", "DOM"."_Src" AS "_DOM__Src", "DOM"."Id" AS "_DOM_Id", "DOM"."User" AS "_DOM_User", "DOM"."BeginDate" AS "_DOM_BeginDate", "DOM"."EndDate" AS "_DOM_EndDate", "DOM"."IdObj1" AS "_DOM_IdObj1", "DOM"."IdObj2" AS "_DOM_IdObj2"
FROM "LinkTest" AS "LinkTest"
JOIN (SELECT "Id", "IdDomain", $1 AS "_Src", "IdObj1", "IdObj2", "User", "BeginDate", NULL AS "EndDate" FROM ONLY "Map_UpdateTest" WHERE "Map_UpdateTest"."Status" = $2 UNION ALL SELECT "Id", "IdDomain", $3 AS "_Src", "IdObj2" AS "IdObj1", "IdObj1" AS "IdObj2", "User", "BeginDate", NULL AS "EndDate" FROM ONLY "Map_UpdateTest" WHERE "Map_UpdateTest"."Status" = $4) AS "DOM" ON "LinkTest"."Id"="DOM"."IdObj1" JOIN (SELECT "Id", "IdClass", "User", "BeginDate", NULL AS "EndDate", NULL AS "CurrentId" FROM ONLY "LinkTest" WHERE "LinkTest"."Status" = $5) AS "DST" ON "DOM"."IdObj2"="DST"."Id"
WHERE ( "LinkTest"."Id" = $6 AND ( "DOM"."Id" = $7 AND "DOM"."_Src" = $8 ) ) AND "LinkTest"."Status" = $9) AS main
ORDER BY "_LinkTest_Id"
LIMIT ALL
OFFSET 0
2015-04-13 02:56:39 JST [3105-51] postgres@cmdbuild DETAIL: parameters: $1 = '_1', $2 = 'A', $3 = '_2', $4 = 'A', $5 = 'A', $6 = '12557', $7 = NULL, $8 = '_1', $9 = 'A'