Real-World Project, Deployment, and Best Practices

Harry · 13 Sep 2026 · 3 views

The Real-World Project

Everything so far combines into a complete User Management / HR-style application: user authentication, role-based access, CRUD, REST APIs, validation, security, and performance work together across the full stack.

Domain Model

class User {
    String username
    String email
    String password
    Boolean enabled = true
    Date dateCreated
    Date lastUpdated
    Department department

    static constraints = {
        username blank: false, unique: true
        email email: true, unique: true
        password blank: false
    }
}

class Role {
    String authority
    static constraints = { authority blank: false, unique: true }
}

class UserRole {
    User user
    Role role
    static mapping = { id composite: ['user', 'role']; version false }
}

class Department {
    String name
    static constraints = { name blank: false }
}

Business Logic in Services

class UserService {
    def passwordEncoder

    @Transactional
    def registerUser(Map params) {
        def user = new User(params)
        user.password = passwordEncoder.encode(user.password)
        user.save(failOnError: true)
        assignRole(user, Role.findByAuthority("ROLE_USER"))
        user
    }
}

Passwords are always hashed with BCrypt, never stored in plain text.

Thin Controllers and GSP

Controllers accept input, delegate to services, and point at GSP views. Views iterate the model with g:each, submit with g:form, and surface errors with g:hasErrors.

Spring Security Integration

// build.gradle
implementation "org.grails.plugins:spring-security-core:6.1.0"

Generate the security classes, then configure static rules:

grails.plugin.springsecurity.controllerAnnotations.staticRules = [
    [pattern: '/',         access: ['permitAll']],
    [pattern: '/login/**',  access: ['permitAll']],
    [pattern: '/admin/**',  access: ['ROLE_ADMIN']],
    [pattern: '/**',        access: ['ROLE_USER']]
]

Deployment

Build options:

grails build      # runnable JAR + embedded Tomcat
grails war        # WAR for an external Tomcat

Production checklist:

  • dbCreate: none in production; manage schema with Flyway/Liquibase.
  • Externalize secrets through environment variables.
  • Use HTTPS everywhere and BCrypt for passwords.
  • Dockerize with eclipse-temurin:17-jdk for consistent environments.
  • Configure Logback, health checks, and automated backups.

Monitoring and Maintenance

  • Log business events (info) and failures (error); debug only in development.
  • Expose /actuator/health for load balancers.
  • Track response times, memory, and database performance.
  • Automate backups and test restoration.
  • Schedule dependency updates and security patches.

Best Practices Quick Reference

  • Thin controllers, fat services, focused domain classes.
  • Prefer where queries, paginate always, avoid eager fetching.
  • BCrypt passwords, role-based authorization, never trust input.
  • Measure before optimizing; cache wisely; async for heavy tasks.
  • Unit test logic, integration test critical flows, automate in CI.
  • Use migrations, externalize config, monitor continuously.

Next Steps

Go further with: Grails microservices, advanced Spring Security (OAuth2/Keycloak), React/Vue frontends, migrating to Grails 7, and performance tuning at scale. Learn conventions deeply, respect simplicity, write tests early, and optimize only when needed.

Key Points

  • A full-stack Grails app ties every concept together.
  • Hash passwords, secure APIs, and never trust input.
  • Use JAR/WAR builds plus Docker for deployment.
  • Monitor, back up, and migrate schema like a production service.
Share this post:

Comments (0)

Please login or register to comment.