This guide walks you through the complete setup process for both microservices, from database creation to running your first queries.
Prerequisites
Ensure you have the following installed:
Java Development Kit Java 17 or higher Check version:
MySQL Database MySQL 8.0 or higher Check version:
API Testing Tool curl, Postman, or similar For testing REST APIs
Step 1: Database Setup
Start MySQL Server
Ensure MySQL is running: # Linux/Mac
sudo systemctl start mysql
# or
brew services start mysql
# Windows
net start MySQL80
Create Database
Log into MySQL and create the database: CREATE DATABASE bd_envio_encomienda ;
Verify: Tables will be created automatically by JPA/Hibernate when you start the shipment service.
Create Database User (Optional)
For security, create a dedicated user: CREATE USER ' envio_user '@ 'localhost' IDENTIFIED BY 'secure_password' ;
GRANT ALL PRIVILEGES ON bd_envio_encomienda. * TO 'envio_user' @ 'localhost' ;
FLUSH PRIVILEGES;
Verify Connection
Test the connection: mysql -u envio_user -p bd_envio_encomienda
Navigate to Service Directory
Edit application.properties
Open src/main/resources/application.properties and configure: spring.application.name =svc-envio-encomienda
server.port =8080
# Database Configuration
spring.datasource.url =jdbc:mysql://localhost:3306/bd_envio_encomienda
spring.datasource.username =root
spring.datasource.password =your_password
# JPA/Hibernate Configuration
spring.jpa.properties.hibernate.dialect =org.hibernate.dialect.MySQLDialect
spring.jpa.hibernate.ddl-auto =update
spring.jpa.show-sql =true
spring.jpa.properties.hibernate.format_sql =true
# Semantic Service Endpoint
microservicio.semantica.url =http://localhost:8081/api/v1/grafo
Change spring.datasource.username and spring.datasource.password to match your MySQL credentials.
Understand Configuration Options
Key Configuration Properties: Property Description Values spring.jpa.hibernate.ddl-autoSchema generation strategy update, create, create-drop, validate, nonespring.jpa.show-sqlShow SQL in logs true, falseserver.portHTTP port 8080 (default)microservicio.semantica.urlSemantic service URL http://localhost:8081/api/v1/grafo
Use ddl-auto=update for development (auto-creates/updates tables). Use validate or none for production.
Navigate to Service Directory
Edit application.properties
Open src/main/resources/application.properties: spring.application.name =web-semantica
server.port =8081
# Jena TDB Directory (created automatically)
jena.tdb.directory =tdb_data
The tdb_data/ directory will be created automatically in the service root when the service starts.
Verify Ontology File
Ensure the ontology file exists: ls src/main/resources/encomiendas.ttl
This file defines the semantic structure and is loaded on startup.
Step 4: Build and Run Services
Start Order Matters: Always start the semantic service (port 8081) before the shipment service (port 8080) to ensure proper synchronization.
Build Both Services
Build to ensure no compilation errors: # Shipment service
cd svc-envio-encomienda
mvn clean install -DskipTests
# Semantic service
cd ../svc-web-semantica
mvn clean install -DskipTests
Start Semantic Service (Terminal 1)
cd svc-web-semantica
mvn spring-boot:run
Expected Output: Started SvcWebSemanticaApplication in X.XXX seconds
Tomcat started on port(s): 8081 (http)
You’ll see the tdb_data/ directory created in the service root.
Start Shipment Service (Terminal 2)
Open a new terminal: cd svc-envio-encomienda
mvn spring-boot:run
Expected Output: HikariPool-1 - Starting...
HikariPool-1 - Start completed.
Started SvcEnvioEncomiendaApplication in X.XXX seconds
Tomcat started on port(s): 8080 (http)
You should see SQL CREATE TABLE statements in the logs as Hibernate creates the schema.
Verify Services
Check Shipment Service: curl http://localhost:8080/api/v1/envios
# Expected: [] (empty array)
Check Semantic Service: curl -X GET "http://localhost:8081/api/v1/grafo/buscar?texto=todos"
# Expected: [] (empty array)
Step 5: Seed Initial Data
Create Branches (Sucursales)
curl -X POST http://localhost:8080/api/v1/sucursales \
-H "Content-Type: application/json" \
-d '{
"nombre": "Sucursal Centro Cajamarca",
"ciudad": "Cajamarca",
"direccion": "Jr. Amalia Puga 450",
"telefono": "076345678"
}'
curl -X POST http://localhost:8080/api/v1/sucursales \
-H "Content-Type: application/json" \
-d '{
"nombre": "Sucursal Miraflores Lima",
"ciudad": "Lima",
"direccion": "Av. Larco 1234",
"telefono": "014567890"
}'
Create Clients
curl -X POST http://localhost:8080/api/v1/clientes \
-H "Content-Type: application/json" \
-d '{
"nombreCompleto": "Juan Pérez",
"dni": "12345678",
"telefono": "987654321",
"correo": "[email protected] "
}'
curl -X POST http://localhost:8080/api/v1/clientes \
-H "Content-Type: application/json" \
-d '{
"nombreCompleto": "Ana López",
"dni": "23456789",
"telefono": "976543210",
"correo": "[email protected] "
}'
Create Test Shipments
curl -X POST http://localhost:8080/api/v1/envios \
-H "Content-Type: application/json" \
-d '{
"remitenteId": 1,
"encomienda": {
"descripcion": "Laptop Dell XPS 15",
"peso": 2.5,
"dimensiones": "40x30x10"
},
"nombreDestinatario": "María García",
"dniDestinatario": "87654321",
"sucursalOrigenId": 1,
"sucursalDestinoId": 2,
"precio": 35.50
}'
Save the codigoSeguimiento and contrasenaEntrega from the response for testing state transitions.
Verify Semantic Synchronization
curl -X GET "http://localhost:8081/api/v1/grafo/buscar?texto=envios+pendientes"
You should see the shipment you just created.
Step 6: Test State Transitions
Assign Vehicle (PENDIENTE → EN_TRANSITO)
curl -X POST http://localhost:8080/api/v1/envios/asignar-placa \
-H "Content-Type: application/json" \
-d '{
"envioId": 1,
"placa": "ABC-123"
}'
Mark Available (EN_TRANSITO → DISPONIBLE)
curl -X PUT http://localhost:8080/api/v1/envios/1/disponible
Deliver Package (DISPONIBLE → ENTREGADO)
curl -X POST http://localhost:8080/api/v1/envios/retirar \
-H "Content-Type: application/json" \
-d '{
"codigoSeguimiento": "ENV-1234567890",
"contrasenaEntrega": "1234"
}'
Replace with your actual tracking code and password.
Test Semantic Search
# Search delivered shipments
curl -X GET "http://localhost:8081/api/v1/grafo/buscar?texto=entregados"
# Search by weight
curl -X GET "http://localhost:8081/api/v1/grafo/buscar?texto=entre+2+y+5+kg"
# Search by city
curl -X GET "http://localhost:8081/api/v1/grafo/buscar?texto=destino+Lima"
Production Configuration
Security Best Practices
Production Settings: # Use dedicated user with limited privileges
spring.datasource.username =envio_prod_user
spring.datasource.password =${DB_PASSWORD}
# Disable schema auto-generation
spring.jpa.hibernate.ddl-auto =validate
# Don't expose SQL in logs
spring.jpa.show-sql =false
Use environment variables for sensitive data: export DB_PASSWORD = secure_production_password
Configure HikariCP for optimal performance: spring.datasource.hikari.maximum-pool-size =10
spring.datasource.hikari.minimum-idle =5
spring.datasource.hikari.connection-timeout =30000
spring.datasource.hikari.idle-timeout =600000
spring.datasource.hikari.max-lifetime =1800000
Configure logging levels: logging.level.root =INFO
logging.level.org.jchilon3mas =DEBUG
logging.level.org.hibernate.SQL =WARN
logging.file.name =logs/envio-service.log
logging.file.max-size =10MB
logging.file.max-history =30
If accessing from web frontend: @ Configuration
public class CorsConfig {
@ Bean
public WebMvcConfigurer corsConfigurer () {
return new WebMvcConfigurer () {
@ Override
public void addCorsMappings ( CorsRegistry registry ) {
registry . addMapping ( "/api/**" )
. allowedOrigins ( "https://yourdomain.com" )
. allowedMethods ( "GET" , "POST" , "PUT" , "DELETE" )
. allowedHeaders ( "*" );
}
};
}
}
External Configuration
Use Spring Cloud Config or environment-specific profiles:
# application-prod.properties
spring.datasource.url = ${ DATABASE_URL }
spring.datasource.username = ${ DATABASE_USER }
spring.datasource.password = ${ DATABASE_PASSWORD }
microservicio.semantica.url = ${ SEMANTIC_SERVICE_URL }
Run with profile:
java -jar svc-envio-encomienda.jar --spring.profiles.active=prod
Running as System Services
systemd (Linux)
Create Service File
Create /etc/systemd/system/envio-service.service: [Unit]
Description =Shipment Service
After =network.target mysql.service
[Service]
Type =simple
User =envio
WorkingDirectory =/opt/envio-service
ExecStart =/usr/bin/java -jar /opt/envio-service/svc-envio-encomienda.jar
Restart =on-failure
RestartSec =10
StandardOutput =journal
StandardError =journal
[Install]
WantedBy =multi-user.target
Enable and Start
sudo systemctl daemon-reload
sudo systemctl enable envio-service
sudo systemctl start envio-service
sudo systemctl status envio-service
Docker Deployment
Create Dockerfile
FROM openjdk:17-jdk-slim
WORKDIR /app
COPY target/svc-envio-encomienda-0.0.1-SNAPSHOT.jar app.jar
EXPOSE 8080
ENTRYPOINT [ "java" , "-jar" , "app.jar" ]
Build Image
mvn clean package -DskipTests
docker build -t envio-service:latest .
Run Container
docker run -d \
--name envio-service \
-p 8080:8080 \
-e SPRING_DATASOURCE_URL=jdbc:mysql://host.docker.internal:3306/bd_envio_encomienda \
-e SPRING_DATASOURCE_USERNAME=root \
-e SPRING_DATASOURCE_PASSWORD=password \
envio-service:latest
Troubleshooting
Symptoms: com.mysql.cj.jdbc.exceptions.CommunicationsException: Communications link failure
Solutions:
Verify MySQL is running: sudo systemctl status mysql
Check credentials in application.properties
Ensure database exists: SHOW DATABASES;
Check MySQL is listening on 3306: netstat -an | grep 3306
Symptoms: Port 8080 was already in use.
Solutions:
Find process: lsof -i :8080 (Mac/Linux) or netstat -ano | findstr :8080 (Windows)
Kill process or change port in application.properties:
Semantic Service Not Found
Symptoms: Connection refused: http://localhost:8081/api/v1/grafo
Solutions:
Ensure semantic service is running: curl http://localhost:8081/api/v1/grafo/buscar?texto=test
Check microservicio.semantica.url in application.properties
Start semantic service before shipment service
Symptoms: TDB Exception: Dataset locked
Solutions:
Stop semantic service
Delete lock file: rm tdb_data/tdb.lock
Restart semantic service
Symptoms: Table 'bd_envio_encomienda.envios' doesn't exist
Solutions:
Verify spring.jpa.hibernate.ddl-auto=update in application.properties
Check Hibernate logs for schema generation
Manually create tables if needed (check logs for CREATE statements)
Health Checks
Add Spring Boot Actuator for monitoring:
< dependency >
< groupId > org.springframework.boot </ groupId >
< artifactId > spring-boot-starter-actuator </ artifactId >
</ dependency >
management.endpoints.web.exposure.include =health,info,metrics
management.endpoint.health.show-details =always
Check Health:
curl http://localhost:8080/actuator/health
Next Steps
Create Shipments Learn to create shipments via API
Semantic Search Use natural language queries
Architecture Understand system design
State Lifecycle Master state transitions