Skip to content

feat(core)!: add entity post and path#23

Open
RVANDO12 wants to merge 7 commits intomainfrom
feat/entity/post
Open

feat(core)!: add entity post and path#23
RVANDO12 wants to merge 7 commits intomainfrom
feat/entity/post

Conversation

@RVANDO12
Copy link
Copy Markdown
Collaborator

@RVANDO12 RVANDO12 commented Apr 10, 2026

PR Description

What this PR Provides

need #19 before

full post entity endpoint created

Update static swagger, and test containers

image

How to test

call GET /api/v1/entity-templates to get a template identifier
call POST /api/v1/entities/{template-identifier}

  • 201 | Entity created successfully
  • 404 | Template not found with identifier:
  • 409 | Conflict, entity always exist
  • 400 | name and identifier of entity is mandatory
  • 400 | if exist in body, relastions must have name and target_entity_identifiers not empty

call
/api/v1/entity-templates?page=0&size=20&sort=identifier%2Casc' \

to get template list

get one without properties or relations

{
  "identifier": "data-pipeline",
  "name": "Data Pipeline",
  "description": "Template for data processing pipelines",
  "properties_definitions": [],
  "relations_definitions": []
}

and one with rules defined on it

{
  "identifier": "web-service",
  "name": "Web Service",
  "description": "Template for REST API web services",
  "properties_definitions": [
    {
      "name": "applicationName",
      "description": "Name of the application",
      "type": "STRING",
      "required": true,
      "rules": {
        "id": "550e8400-e29b-41d4-a716-446655440003",
        "format": null,
        "enum_values": null,
        "regex": "^[a-zA-Z0-9-]+$",
        "max_length": 50,
        "min_length": 3,
        "max_value": null,
        "min_value": null
      }
    },
    {
      "name": "baseUrl",
      "description": "Base URL for the service",
      "type": "STRING",
      "required": true,
      "rules": {
        "id": "550e8400-e29b-41d4-a716-446655440004",
        "format": "URL",
        "enum_values": null,
        "regex": "^https?://.*",
        "max_length": 255,
        "min_length": 8,
        "max_value": null,
        "min_value": null
      }
...
}

get entities from each :
data-pipeline

{
  "content": [],
  "page": {
    "size": 20,
    "number": 0,
    "total_elements": 0,
    "total_pages": 0
  }
}

monitoring-service

  {
    "content": [
      {
        "identifier": "monitoring-service-1",
        "name": "Monitoring Service 1",
        "properties": {},
        "relations": {},
        "relations_as_target": {},
        "template_identifier": "monitoring-service"
      },
      {
        "identifier": "monitoring-service-2",
        "name": "Monitoring Service 2",
        "properties": {},
        "relations": {},
        "relations_as_target": {},
        "template_identifier": "monitoring-service"
      },
      {
        "identifier": "monitoring-service-3",
        "name": "Monitoring Service 3",
        "properties": {},
        "relations": {},
        "relations_as_target": {},
        "template_identifier": "monitoring-service"
      },
      {
        "identifier": "monitoring-service-4",
        "name": "Monitoring Service 4",
        "properties": {},
        "relations": {},
        "relations_as_target": {},
        "template_identifier": "monitoring-service"
      },
      {
        "identifier": "monitoring-service-5",
        "name": "Monitoring Service 5",
        "properties": {},
        "relations": {},
        "relations_as_target": {},
        "template_identifier": "monitoring-service"
      },
      {
        "identifier": "monitoring-service-6",
        "name": "Monitoring Service 6",
        "properties": {},
        "relations": {},
        "relations_as_target": {},
        "template_identifier": "monitoring-service"
      }
    ],
    "page": {
      "size": 20,
      "number": 0,
      "total_elements": 6,
      "total_pages": 1
    }
  }

try to create entity for each :
data-pipeline :

curl -X 'POST' \
  'http://localhost:8084/api/v1/entities/data-pipeline' \
  -H 'accept: */*' \
  -H 'Content-Type: application/json' \
  -d '{
  "name": "data-001",
  "identifier": "data-001",
  "properties": {
    "type": "SQL",
    "environment": "dev"
  },
  "relations": [  ]
}'

201 entity created

trying call get :

curl -X 'GET' \
  'http://localhost:8084/api/v1/entities/data-pipeline?page=0&size=20&sort=identifier%2Casc' \
  -H 'accept: */*'


  
  {
    "content": [
      {
        "identifier": "data-001",
        "name": "data-001",
        "properties": {
          "environment": "dev",
          "type": "SQL"
        },
        "relations": {
          "depends-on": []
        },
        "relations_as_target": {},
        "template_identifier": "data-pipeline"
      }
    ],
    "page": {
      "size": 20,
      "number": 0,
      "total_elements": 1,
      "total_pages": 1
    }
  }

try to post same thing two time :

{
  "error": "CONFLICT",
  "error_description": "Entity with name 'data-001' already exists for template 'data-pipeline'"
}

Call new one with relations from previous :

{
  "name": "data-021",
  "identifier": "data-021",
  "properties": {
    "type": "SQL",
    "environment": "dev"
  },
  "relations": [
    {
      "name": "depends-on",
      "target_entity_identifiers": [
        "data-001"
      ]
    }
  ]
}

and get :

  {
    "content": [
      {
        "identifier": "data-001",
        "name": "data-001",
        "properties": {
          "environment": "dev",
          "type": "SQL"
        },
        "relations": {
          "depends-on": []
        },
        "relations_as_target": {
          "depends-on": [
            {
              "identifier": "data-021",
              "name": "data-021"
            }
          ]
        },
        "template_identifier": "data-pipeline"
      },
      {
        "identifier": "data-021",
        "name": "data-021",
        "properties": {
          "environment": "dev",
          "type": "SQL"
        },
        "relations": {
          "depends-on": [
            {
              "identifier": "data-001",
              "name": "data-001"
            }
          ]
        },
        "relations_as_target": {},
        "template_identifier": "data-pipeline"
      }
    ],
    "page": {
      "size": 20,
      "number": 0,
      "total_elements": 2,
      "total_pages": 1
    }
  }

try on one with rules :

  curl -X 'POST' \
    'http://localhost:8084/api/v1/entities/web-service' \
    -H 'accept: */*' \
    -H 'Content-Type: application/json' \
    -d '{
    "name": "data-test1",
    "identifier": "data-test1",
    "properties": {
      "applicationName": 12
    },
    "relations": [
    ]
  }'


  
  {
  "error": "BAD_REQUEST",
  "error_description": "Entity validation failed: Property 'applicationName' must be of type STRING; Property 'baseUrl' is required by template 'web-service'; Property 'environment' is required by template 'web-service'; Property 'ownerEmail' is required by template 'web-service'; Property 'port' is required by template 'web-service'; Property 'programmingLanguage' is required by template 'web-service'; Property 'protocol' is required by template 'web-service'; Property 'teamName' is required by template 'web-service'; Property 'version' is required by template 'web-service'"
  }

Breaking changes (if any)

  • Modify post entity and entity validation

  • add mock for local test

  • change unique constraint key on identifier =>

    ALTER TABLE entity DROP CONSTRAINT entity_identifier_key;
    
    ALTER TABLE entity ADD CONSTRAINT entity_identifier_template_identifier_key
        UNIQUE (identifier, template_identifier);
    

Context of the Breaking Change

For example: we redefined the component types list in the DPAC referential

Result of the Breaking Change

For example: your component of type xxx will migrate to the type yyy

@RVANDO12 RVANDO12 force-pushed the feat/entity/post branch 2 times, most recently from b9987ed to 59810a8 Compare April 24, 2026 12:05
@RVANDO12 RVANDO12 changed the title chore(feat): add entity post and path feat(core): add entity post and path Apr 24, 2026
@RVANDO12 RVANDO12 force-pushed the feat/entity/post branch 3 times, most recently from edaf96e to 99c4786 Compare April 24, 2026 12:22
@RVANDO12 RVANDO12 marked this pull request as ready for review April 24, 2026 12:22
@RVANDO12 RVANDO12 force-pushed the feat/entity/post branch 5 times, most recently from ea6834b to dacabf1 Compare April 28, 2026 13:20
Comment thread src/main/java/com/decathlon/idp_core/domain/service/EntityService.java Outdated
Comment thread src/main/java/com/decathlon/idp_core/domain/service/EntityService.java Outdated
Comment thread src/main/resources/application-local.yml Outdated
Comment thread src/main/java/com/decathlon/idp_core/domain/service/EntityService.java Outdated
Comment thread src/main/java/com/decathlon/idp_core/domain/service/EntityService.java Outdated
@RVANDO12 RVANDO12 changed the title feat(core): add entity post and path feat(core)!: add entity post and path Apr 29, 2026
@RVANDO12 RVANDO12 force-pushed the feat/entity/post branch 3 times, most recently from c018c8c to ddb79e0 Compare May 4, 2026 06:50
@RVANDO12 RVANDO12 force-pushed the feat/entity/post branch from ddb79e0 to d807c69 Compare May 4, 2026 06:58
Comment thread src/main/java/com/decathlon/idp_core/domain/service/entity/EntityService.java Outdated
@Transactional
public Entity createEntity(@Valid Entity entity) {
// Add validations
entityValidationService.checkTemplateExist(entity.templateIdentifier());
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

update for entityValidationService.validateForCreate

/// Check entity template existence to ensure valid template reference before deeper validations.
/// @param entity the entity whose template existence is to be checked
/// @throws EntityTemplateNotFoundException if the template referenced by the entity does not exist
void checkTemplateExist(final String entity) {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this and use EntityTemplateValidation.validateIfExists i the EntityService

}
}

private void validateEntityHeader(Entity entity, Violations violations) {
Copy link
Copy Markdown
Collaborator

@brandPittCode brandPittCode May 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is already validated using the annotations in the Entity record.

/// Checks for existing entity with same template and identifier to prevent duplicates.
/// @param entity the entity to check for existence
/// @throws EntityAlreadyExistsException if an entity with the same template and identifier already exists
void checkEntityAlreadyExist(final Entity entity) {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
void checkEntityAlreadyExist(final Entity entity) {
void validateUniqueness(final Entity entity) {

String value
String value,

Object rawValue
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lets's check if it we can get around without this parameter using only casting validation.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer keeping the Property model limited to business-related information and handling validation via casting, even if certain cases—like a numeric string—might pass through.

violations.addIfBlank(entity.identifier(), ENTITY_IDENTIFIER_MANDATORY);
}

private void validatePropertiesShape(List<Property> properties, Violations violations) {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we rally need this. Isn't performed also by the annotations?

@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented May 5, 2026

throw new EntityAlreadyExistsException(entity.templateIdentifier(), entity.identifier());
}
}
}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we really need this validations?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants