@Override
  @TransactionAttribute(TransactionAttributeType.REQUIRED)
  public void updateName(String path, String value) throws GreetingServiceException {
    logger.info("updateName(...) called");
    logger.debug("params : path=" + path + ", value=" + value);

    try {
      // Checking if the connected user has the permission to update the resource giving pep :
      String caller = membership.getProfilePathForConnectedIdentifier();
      pep.checkSecurity(caller, path, "update");

      // Performing a lookup in the naming to recover the Resource Identifier
      FactoryResourceIdentifier identifier = binding.lookup(path);

      // Checking if this resource identifier is really a resource managed by this service (a Hello
      // resource)
      checkResourceType(identifier, Name.RESOURCE_NAME);

      // STARTING SPECIFIC EXTERNAL SERVICE RESOURCE LOADING OR METHOD CALLS
      Name name = em.find(Name.class, identifier.getId());
      if (name == null) {
        throw new GreetingServiceException("unable to find a name for id " + identifier.getId());
      }
      name.setValue(value);
      em.merge(name);
      // END OF EXTERNAL SERVICE INVOCATION

      // Need to set some properties on the node :
      binding.setProperty(
          path, FactoryResourceProperty.LAST_UPDATE_TIMESTAMP, System.currentTimeMillis() + "");

      // Using the notification service to throw an event :
      notification.throwEvent(
          new Event(
              path,
              caller,
              Name.RESOURCE_NAME,
              Event.buildEventType(GreetingService.SERVICE_NAME, Name.RESOURCE_NAME, "update"),
              ""));

      // Using the indexing service to reindex the name newly updated
      indexing.reindex(getServiceName(), path);

    } catch (Exception e) {
      //   ctx.setRollbackOnly();
      logger.error("unable to update the name at path " + path, e);
      throw new GreetingServiceException("unable to update the name at path " + path, e);
    }
  }
  @Override
  @TransactionAttribute(TransactionAttributeType.SUPPORTS)
  public String sayHello(String path) throws GreetingServiceException {
    logger.info("sayHello(...) called");
    logger.debug("params : path=" + path);

    try {
      // Checking if the connected user has the permission to say-hello the resource giving pep :
      String caller = membership.getProfilePathForConnectedIdentifier();
      pep.checkSecurity(caller, path, "say-hello");

      // Performing a lookup in the naming to recover the Resource Identifier
      FactoryResourceIdentifier identifier = binding.lookup(path);

      // Checking if this resource identifier is really a resource managed by this service (a Hello
      // resource)
      checkResourceType(identifier, Name.RESOURCE_NAME);

      // STARTING SPECIFIC EXTERNAL SERVICE RESOURCE LOADING OR METHOD CALLS
      Name name = em.find(Name.class, identifier.getId());
      if (name == null) {
        throw new GreetingServiceException("unable to find a name for id " + identifier.getId());
      }
      // END OF EXTERNAL SERVICE INVOCATION

      // Building hello message :
      String message = "Hello dear " + name.getValue() + " !!";

      // Using the notification service to throw an event :
      notification.throwEvent(
          new Event(
              path,
              caller,
              Name.RESOURCE_NAME,
              Event.buildEventType(GreetingService.SERVICE_NAME, Name.RESOURCE_NAME, "say-hello"),
              ""));

      return message;
    } catch (Exception e) {
      //  ctx.setRollbackOnly();
      logger.error("unable to say hello to the name at path " + path, e);
      throw new GreetingServiceException("unable to say hello to the name at path " + path, e);
    }
  }
  /**
   * Give name at the given path.
   *
   * @param pepCheck true to make the check.
   * @param path the path to the name.
   * @throws GreetingServiceException if the name can't be find.
   */
  @TransactionAttribute(TransactionAttributeType.SUPPORTS)
  private Name readName(String path, boolean pepCheck) throws GreetingServiceException {
    try {
      // Checking if the connected user has the permission to read the resource giving pep :
      String caller = membership.getProfilePathForConnectedIdentifier();

      if (pepCheck) pep.checkSecurity(caller, path, "read");

      // Performing a lookup in the naming to recover the Resource Identifier
      FactoryResourceIdentifier identifier = binding.lookup(path);

      // Checking if this resource identifier is really a resource managed by this service (a Hello
      // resource)
      checkResourceType(identifier, Name.RESOURCE_NAME);

      // STARTING SPECIFIC EXTERNAL SERVICE RESOURCE LOADING OR METHOD CALLS
      Name name = em.find(Name.class, identifier.getId());
      if (name == null) {
        throw new GreetingServiceException("unable to find a name for id " + identifier.getId());
      }
      name.setResourcePath(path);
      // END OF EXTERNAL SERVICE INVOCATION

      // Using the notification service to throw an event :
      notification.throwEvent(
          new Event(
              path,
              caller,
              Name.RESOURCE_NAME,
              Event.buildEventType(GreetingService.SERVICE_NAME, Name.RESOURCE_NAME, "read"),
              ""));

      return name;
    } catch (Exception e) {
      logger.error("unable to read the name at path " + path, e);
      throw new GreetingServiceException("unable to read the name at path " + path, e);
    }
  }
  @Override
  public IndexableDocument getIndexableDocument(String path) throws IndexingServiceException {
    try {
      // use internal findResource
      Name name = (Name) findResource(path, false);
      IndexableContent content = new IndexableContent();
      content.addContentPart(name.getValue());

      IndexableDocument doc = new IndexableDocument();

      doc.setIndexableContent(content);
      doc.setResourceService(getServiceName());
      doc.setResourceShortName(name.getValue());
      doc.setResourceType(Name.RESOURCE_NAME);
      doc.setResourcePath(path);
      doc.setResourceFRI(name.getFactoryResourceIdentifier());

      return doc;
    } catch (Exception e) {
      ctx.setRollbackOnly();
      logger.error("unable to convert name to IndexableContent " + path, e);
      throw new IndexingServiceException("unable to convert name to IndexableContent" + path, e);
    }
  }
  @Override
  @TransactionAttribute(TransactionAttributeType.REQUIRED)
  public void createName(String path, String value) throws GreetingServiceException {

    logger.info("createName(...) called");
    logger.debug("params : path=" + path + ", value=" + value);

    try {
      // Checking if the connected user has the permission to create a resource giving pep :
      //  - the profile path of the connected user (caller)
      //  - the parent of the path (we check the 'create' permission on the parent of the given
      // path)
      //  - the name of the permission to check ('create')
      String caller = membership.getProfilePathForConnectedIdentifier();
      pep.checkSecurity(caller, PathHelper.getParentPath(path), "create");

      // STARTING SPECIFIC EXTERNAL SERVICE RESOURCE CREATION OR METHOD CALL
      Name name = new Name();
      name.setId(UUID.randomUUID().toString());
      name.setValue(value);
      em.persist(name);
      // END OF EXTERNAL INVOCATION

      // Binding the external resource in the naming using the generated resource ID :
      binding.bind(name.getFactoryResourceIdentifier(), path);

      // Need to set some properties on the node :
      binding.setProperty(
          path, FactoryResourceProperty.CREATION_TIMESTAMP, "" + System.currentTimeMillis());
      binding.setProperty(
          path, FactoryResourceProperty.LAST_UPDATE_TIMESTAMP, "" + System.currentTimeMillis());
      binding.setProperty(path, FactoryResourceProperty.AUTHOR, caller);

      // Need to create a new security policy for this resource :
      // Giving the caller the Owner permission (aka all permissions)
      String policyId = UUID.randomUUID().toString();
      pap.createPolicy(policyId, PAPServiceHelper.buildOwnerPolicy(policyId, caller, path));
      pap.createPolicy(
          UUID.randomUUID().toString(),
          PAPServiceHelper.buildPolicy(policyId, caller, path, new String[] {"read"}));

      // Setting security properties on the node :
      binding.setProperty(path, FactoryResourceProperty.OWNER, caller);
      binding.setProperty(path, FactoryResourceProperty.POLICY_ID, policyId);

      // Using the notification service to throw an event :
      notification.throwEvent(
          new Event(
              path,
              caller,
              Name.RESOURCE_NAME,
              Event.buildEventType(GreetingService.SERVICE_NAME, Name.RESOURCE_NAME, "create"),
              ""));

      // Using the indexing service to index the name newly created
      indexing.index(getServiceName(), path);
    } catch (Exception e) {
      ctx.setRollbackOnly();
      logger.error("unable to create the name at path " + path, e);
      throw new GreetingServiceException("unable to create the name at path " + path, e);
    }
  }