@PreAcquireNamespaceLock
  @PutMapping("/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/items/{itemId}")
  public ItemDTO update(@PathVariable("appId") String appId,
                        @PathVariable("clusterName") String clusterName,
                        @PathVariable("namespaceName") String namespaceName,
                        @PathVariable("itemId") long itemId,
                        @RequestBody ItemDTO itemDTO) {
    Item managedEntity = itemService.findOne(itemId);
    if (managedEntity == null) {
      throw NotFoundException.itemNotFound(appId, clusterName, namespaceName, itemId);
    }

    Namespace namespace = namespaceService.findOne(appId, clusterName, namespaceName);
    // In case someone constructs an attack scenario
    if (namespace == null || namespace.getId() != managedEntity.getNamespaceId()) {
      throw BadRequestException.namespaceNotMatch();
    }

    Item entity = BeanUtils.transform(Item.class, itemDTO);

    ConfigChangeContentBuilder builder = new ConfigChangeContentBuilder();

    Item beforeUpdateItem = BeanUtils.transform(Item.class, managedEntity);

    //protect. only value,type,comment,lastModifiedBy can be modified
    managedEntity.setType(entity.getType());
    managedEntity.setValue(entity.getValue());
    managedEntity.setComment(entity.getComment());
    managedEntity.setDataChangeLastModifiedBy(entity.getDataChangeLastModifiedBy());

    entity = itemService.update(managedEntity);
    builder.updateItem(beforeUpdateItem, entity);
    itemDTO = BeanUtils.transform(ItemDTO.class, entity);

    if (builder.hasContent()) {
      commitService.createCommit(appId, clusterName, namespaceName, builder.build(), itemDTO.getDataChangeLastModifiedBy());
    }

    return itemDTO;
  }
@Test
  @Sql(scripts = "/controller/test-itemset.sql", executionPhase = ExecutionPhase.BEFORE_TEST_METHOD)
  @Sql(scripts = "/controller/cleanup.sql", executionPhase = ExecutionPhase.AFTER_TEST_METHOD)
  public void testUpdate() {
    this.testCreate();

    String appId = "someAppId";
    AppDTO app = restTemplate.getForObject(appBaseUrl(), AppDTO.class, appId);
    assert app != null;
    ClusterDTO cluster = restTemplate.getForObject(clusterBaseUrl(), ClusterDTO.class, app.getAppId(), "default");
    assert cluster != null;
    NamespaceDTO namespace = restTemplate.getForObject(namespaceBaseUrl(),
        NamespaceDTO.class, app.getAppId(), cluster.getName(), "application");

    String itemKey = "test-key";
    String itemValue = "test-value-updated";

    long itemId = itemRepository.findByKey(itemKey, Pageable.ofSize(1))
        .getContent()
        .get(0)
        .getId();
    ItemDTO item = new ItemDTO(itemKey, itemValue, "", 1);
    item.setDataChangeLastModifiedBy("apollo");

    String updateUrl = url(  "/apps/{appId}/clusters/{clusterName}/namespaces/{namespaceName}/items/{itemId}");
    assert namespace != null;
    restTemplate.put(updateUrl, item, app.getAppId(), cluster.getName(), namespace.getNamespaceName(), itemId);

    itemRepository.findById(itemId).ifPresent(item1 -> {
      assertThat(item1.getValue()).isEqualTo(itemValue);
      assertThat(item1.getKey()).isEqualTo(itemKey);
    });

    List<Commit> commitList = commitRepository.findByAppIdAndClusterNameAndNamespaceNameOrderByIdDesc(app.getAppId(), cluster.getName(), namespace.getNamespaceName(),
        Pageable.ofSize(10));
    assertThat(commitList).hasSize(2);
  }