-1

When developing a Grails 3.0 plugin:

  1. How should a domain be defined so that it can be extended by the application using the plugin?
  2. How does the plugin reference instances of the extended class?

As an example, a security plugin could have classes such as:

User.groovy

package com.example.plugins.security

class User {

   String  email
   String  hash
   Boolean enabled = true

}

SecurityService.groovy

package com.example.plugins.security

import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder

class SecurityService {

   def authenticate(String email, String password) {
      def user = User.findByEmail(email)  //instance of BookstoreUser???
      def encoder = new BCryptPasswordEncoder()
      return user && encoder.matches(password, user.hash) ? user : null
      }

}

The application would have a domain such as:

grails-app/domain/com/example/bookstore/BookstoreUser.groovy

package org.example.bookstore

import org.bson.types.ObjectId
import org.example.plugins.security.User

class BookstoreUser extends User {

   ObjectId id
   String   firstName
   String   lastName

   static mapWith = "mongo"

}

The rest of the code is at:
https://github.com/center-key/bookstore

Dem Pilafian
  • 5,625
  • 6
  • 39
  • 67

1 Answers1

0

How should a domain be defined so that it can be extended by the application using the plugin?

The same way you would define any other domain class. Declare the Groovy source file under grails-app/domain/.

How does the plugin reference instances of the extended class?

The code that you show in your question would work fine.

package com.example.plugins.security

class SecurityService {

   def disableUser(User user) {  //the instance should be a BookstoreUser
          user.enabled = false
          user.save()
      }
}

If an application writes a class like BookstoreUser that extends your User class, an instance of BookstoreUser can be passed into your disableUser method and that method will behave as you probably expect it should. The method will set the enabled property to false and will then save the updated instance.

Jeff Scott Brown
  • 26,804
  • 2
  • 30
  • 47
  • My bad... the `disableUser()` example was overly simplistic. I updated the question with the `authenticate()` method which is more interesting and does not have `user` passed in. How would the **service** know to `findByEmail` on `BookstoreUser` instead of `User`? – Dem Pilafian Jun 22 '15 at 06:41
  • `My bad... the disableUser() example was overly simplistic.` - Depending on some other factors not present in the question (like are there other `User` types in the system and is `email` unique across them) the solution that you have shown will likely work. I have to downvote your question. It is irresponsible to post a question, get an answer that specifically addresses the question then change the question to ask something else. You are actively wasting the time of folks who volunteered to help you. If you have a separate question that should be asked as a separate question. – Jeff Scott Brown Jun 22 '15 at 12:27
  • The example code was just to add a concrete reference to the question. The question still stands: `How does the plugin reference instances of the extended class?` I did not edit the question. Exploiting a technicality in the example code but not actually answering the question will not benefit future readers trying to build Grails plugins. I very deliberately worded the question to be generally helpful to the Grails community. – Dem Pilafian Jun 22 '15 at 19:36
  • `Exploiting a technicality in the example code but not actually answering the question will not benefit future readers trying to build Grails plugins.` - I can't tell if you are asserting that this answer does that or not. It may be that I am misunderstanding the question. It seems you may be asking how to point a reference of type `User` at an object on the heap that is an instance of some other class which extends `User`. If that is what you are asking, the answer above addresses that. If that isn't what you are asking, I apologize for not being able to help. – Jeff Scott Brown Jun 22 '15 at 21:02
  • It's often not possible to pass the instance into the plugin service, such as when the plugin service needs to create a new instance or search the DB to find an existing instance. For a security plugin, this is true for registering a new user and authenticating a user on sign in. For anyone still interested in this (which I presume should be pretty much all Grails plugin developers), here's a project with both a sample plugin and a test app: https://github.com/dpilafian/grails-plugin-experiment – Dem Pilafian Jun 26 '15 at 06:44
  • Your sample app demonstrates several problems which are not indicated in the original question. Now I understand what you are looking for. This is fairly simple to do. Tonight I will send you a pull request that I expect will clarify a number of things. – Jeff Scott Brown Jun 26 '15 at 12:06