Skip to content

Commit 7648784

Browse files
authored
Merge pull request #48 from davidkron/grails5-config-without-dot-access
Refactoring config access for Grails 5
2 parents 48d2865 + 67f9a69 commit 7648784

File tree

8 files changed

+182
-117
lines changed

8 files changed

+182
-117
lines changed

grails-app/services/grails/plugins/mail/MailService.groovy

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,52 +16,71 @@
1616
package grails.plugins.mail
1717

1818
import grails.config.Config
19-
import grails.core.support.GrailsConfigurationAware
2019
import groovy.transform.CompileStatic
2120
import groovy.util.logging.Slf4j
2221
import org.springframework.beans.factory.DisposableBean
2322
import org.springframework.beans.factory.InitializingBean
23+
import org.springframework.boot.context.properties.ConfigurationProperties
24+
import org.springframework.boot.context.properties.bind.Bindable
25+
import org.springframework.boot.context.properties.bind.Binder
26+
import org.springframework.boot.context.properties.source.ConfigurationPropertySource
27+
import org.springframework.boot.context.properties.source.ConfigurationPropertySources
28+
import org.springframework.core.env.PropertiesPropertySource
29+
import org.springframework.core.env.PropertySource
2430
import org.springframework.mail.MailMessage
2531

2632
import java.util.concurrent.LinkedBlockingQueue
2733
import java.util.concurrent.ThreadPoolExecutor
2834
import java.util.concurrent.TimeUnit
35+
2936
/**
3037
* Provides the entry point to the mail sending API.
3138
*/
3239
@Slf4j
3340
@CompileStatic
34-
class MailService implements InitializingBean, DisposableBean, GrailsConfigurationAware {
41+
class MailService implements InitializingBean, DisposableBean {
3542

3643
static transactional = false
3744

38-
Config configuration
45+
MailConfigurationProperties mailConfigurationProperties
3946
MailMessageBuilderFactory mailMessageBuilderFactory
4047
ThreadPoolExecutor mailExecutorService
4148

4249
private static final Integer DEFAULT_POOL_SIZE = 5
4350

44-
MailMessage sendMail(Config config, @DelegatesTo(strategy = Closure.DELEGATE_FIRST, value = MailMessageBuilder) Closure callable) {
51+
private static final Bindable<MailConfigurationProperties> CONFIG_BINDABLE = Bindable.of(MailConfigurationProperties)
52+
53+
MailMessage sendMail(MailConfigurationProperties properties, @DelegatesTo(strategy = Closure.DELEGATE_FIRST, value = MailMessageBuilder) Closure callable) {
4554
if (isDisabled()) {
4655
log.warn("Sending emails disabled by configuration option")
4756
return
4857
}
4958

50-
MailMessageBuilder messageBuilder = mailMessageBuilderFactory.createBuilder(config)
59+
MailMessageBuilder messageBuilder = mailMessageBuilderFactory.createBuilder(properties)
5160
callable.delegate = messageBuilder
5261
callable.resolveStrategy = Closure.DELEGATE_FIRST
5362
callable.call(messageBuilder)
5463

5564
return messageBuilder.sendMessage(mailExecutorService)
5665
}
5766

67+
MailMessage sendMail(Config config, @DelegatesTo(strategy = Closure.DELEGATE_FIRST, value = MailMessageBuilder) Closure callable) {
68+
return sendMail(toMailProperties(config), callable)
69+
}
70+
5871
MailMessage sendMail(@DelegatesTo(strategy = Closure.DELEGATE_FIRST, value = MailMessageBuilder) Closure callable) {
59-
return sendMail(configuration, callable)
72+
return sendMail(mailConfigurationProperties, callable)
6073
}
6174

75+
private static MailConfigurationProperties toMailProperties(Config config) {
76+
PropertySource propertySource = new PropertiesPropertySource('mailProperties', config.toProperties())
77+
Iterable<ConfigurationPropertySource> configurationPropertySources = ConfigurationPropertySources.from(propertySource)
78+
Binder binder = new Binder(configurationPropertySources)
79+
return binder.bind(MailConfigurationProperties.PREFIX, CONFIG_BINDABLE).get()
80+
}
6281

6382
boolean isDisabled() {
64-
configuration.getProperty('grails.mail.disabled',Boolean, false)
83+
mailConfigurationProperties.disabled
6584
}
6685

6786
void setPoolSize(Integer poolSize){
@@ -79,7 +98,7 @@ class MailService implements InitializingBean, DisposableBean, GrailsConfigurati
7998
public void afterPropertiesSet() throws Exception {
8099
mailExecutorService = new ThreadPoolExecutor(1, 1, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>())
81100

82-
Integer poolSize = configuration.getProperty('grails.mail.poolSize', Integer)
101+
Integer poolSize = mailConfigurationProperties.poolSize
83102
try{
84103
((ThreadPoolExecutor)mailExecutorService).allowCoreThreadTimeOut(true)
85104
}catch(MissingMethodException e){

src/integration-test/groovy/grails/plugins/mail/MailServiceSpec.groovy

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ class MailServiceSpec extends Specification {
6969
)
7070
mimeCapableMailService = new MailService(
7171
mailMessageBuilderFactory: mimeMessageBuilderFactor,
72-
configuration: grailsApplication.config)
72+
mailConfigurationProperties: new MailConfigurationProperties())
7373
mimeCapableMailService.afterPropertiesSet()
7474

7575
MailSender simpleMailSender = new SimpleMailSender()
@@ -79,7 +79,7 @@ class MailServiceSpec extends Specification {
7979
)
8080
nonMimeCapableMailService = new MailService(
8181
mailMessageBuilderFactory: simpleMessageBuilderFactory,
82-
configuration: grailsApplication.config)
82+
mailConfigurationProperties: new MailConfigurationProperties())
8383
nonMimeCapableMailService.afterPropertiesSet()
8484
}
8585

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
package grails.plugins.mail
2+
3+
import grails.core.GrailsApplication
4+
import grails.plugins.GrailsPluginManager
5+
import grails.web.pages.GroovyPagesUriService
6+
import groovy.transform.CompileStatic
7+
import org.grails.gsp.GroovyPagesTemplateEngine
8+
import org.springframework.beans.factory.annotation.Autowired
9+
import org.springframework.beans.factory.annotation.Qualifier
10+
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
11+
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty
12+
import org.springframework.context.annotation.Bean
13+
import org.springframework.context.annotation.Configuration
14+
import org.springframework.jndi.JndiObjectFactoryBean
15+
import org.springframework.mail.MailSender
16+
import org.springframework.mail.javamail.JavaMailSenderImpl
17+
18+
import javax.mail.Session
19+
20+
@Configuration
21+
@CompileStatic
22+
class MailConfiguration {
23+
24+
@Bean
25+
MailConfigurationProperties mailConfigurationProperties() {
26+
return new MailConfigurationProperties()
27+
}
28+
29+
@Bean
30+
@ConditionalOnMissingBean(name = 'mailSession')
31+
@ConditionalOnProperty(prefix = 'grails.mail', name = 'jndiName')
32+
JndiObjectFactoryBean mailSession(MailConfigurationProperties mailProperties) {
33+
JndiObjectFactoryBean factory = new JndiObjectFactoryBean()
34+
factory.jndiName = mailProperties.jndiName
35+
return factory
36+
}
37+
38+
@Bean
39+
JavaMailSenderImpl mailSender(
40+
@Autowired(required = false) @Qualifier('mailSession') Session mailSession,
41+
MailConfigurationProperties mailProperties) {
42+
43+
JavaMailSenderImpl mailSender = new JavaMailSenderImpl()
44+
if (mailProperties.host) {
45+
mailSender.host = mailProperties.host
46+
} else if (!mailProperties.jndiName) {
47+
def envHost = System.getenv()['SMTP_HOST']
48+
if (envHost) {
49+
mailSender.host = envHost
50+
} else {
51+
mailSender.host = 'localhost'
52+
}
53+
}
54+
if (mailProperties.encoding) {
55+
mailSender.defaultEncoding = mailProperties.encoding
56+
} else if (!mailProperties.jndiName) {
57+
mailSender.defaultEncoding = 'utf-8'
58+
}
59+
if (mailSession != null) {
60+
mailSender.session = mailSession
61+
}
62+
if (mailProperties.port) {
63+
mailSender.port = mailProperties.port
64+
}
65+
if (mailProperties.username) {
66+
mailSender.username = mailProperties.username
67+
}
68+
if (mailProperties.password) {
69+
mailSender.password = mailProperties.password
70+
}
71+
if (mailProperties.protocol) {
72+
mailSender.protocol = mailProperties.protocol
73+
}
74+
if (mailProperties.props) {
75+
mailSender.javaMailProperties = mailProperties.props
76+
}
77+
return mailSender
78+
}
79+
80+
@Bean
81+
MailMessageBuilderFactory mailMessageBuilderFactory(
82+
MailSender mailSender,
83+
MailMessageContentRenderer mailMessageContentRenderer) {
84+
MailMessageBuilderFactory factory = new MailMessageBuilderFactory()
85+
factory.mailSender = mailSender
86+
factory.mailMessageContentRenderer = mailMessageContentRenderer
87+
return factory
88+
}
89+
90+
@Bean
91+
MailMessageContentRenderer mailMessageContentRenderer(
92+
GroovyPagesTemplateEngine groovyPagesTemplateEngine,
93+
GroovyPagesUriService groovyPagesUriService,
94+
GrailsApplication grailsApplication,
95+
GrailsPluginManager pluginManager) {
96+
MailMessageContentRenderer renderer = new MailMessageContentRenderer()
97+
renderer.groovyPagesTemplateEngine = groovyPagesTemplateEngine
98+
renderer.groovyPagesUriService = groovyPagesUriService
99+
renderer.grailsApplication = grailsApplication
100+
renderer.pluginManager = pluginManager
101+
return renderer
102+
}
103+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package grails.plugins.mail
2+
3+
import org.springframework.boot.context.properties.ConfigurationProperties
4+
5+
@ConfigurationProperties(MailConfigurationProperties.PREFIX)
6+
class MailConfigurationProperties {
7+
8+
public static final String PREFIX = 'grails.mail'
9+
10+
boolean disabled
11+
String overrideAddress
12+
Defaults defaults = new Defaults()
13+
14+
Integer poolSize
15+
String encoding
16+
String jndiName
17+
String protocol
18+
String host
19+
Integer port
20+
String username
21+
String password
22+
Properties props
23+
24+
/**
25+
* We can't use 'default' as a groovy property name as it is a reserved keyword.
26+
* But it is possible to define a getter for it to make it compatible.
27+
*/
28+
Defaults getDefault() {
29+
return defaults
30+
}
31+
32+
static class Defaults {
33+
String from
34+
String to
35+
}
36+
}

src/main/groovy/grails/plugins/mail/MailGrailsPlugin.groovy

Lines changed: 3 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@
1616
package grails.plugins.mail
1717

1818
import grails.plugins.Plugin
19-
import org.springframework.jndi.JndiObjectFactoryBean
20-
import org.springframework.mail.javamail.JavaMailSenderImpl
2119
import groovy.util.logging.Commons
2220

2321
@Commons
@@ -67,96 +65,9 @@ sendMail {
6765
"grails-app/views/_testemails/*.gsp"
6866
]
6967

70-
Integer mailConfigHash
71-
ConfigObject mailConfig
72-
boolean createdSession = false
73-
74-
75-
Closure doWithSpring() {
76-
{->
77-
mailConfig = grailsApplication.config.grails.mail
78-
mailConfigHash = mailConfig.hashCode()
79-
80-
configureMailSender(delegate, mailConfig)
81-
82-
mailMessageBuilderFactory(MailMessageBuilderFactory) {
83-
it.autowire = true
84-
}
85-
86-
mailMessageContentRenderer(MailMessageContentRenderer) {
87-
it.autowire = true
88-
}
89-
}
90-
}
91-
92-
93-
94-
95-
void onConfigChange(Map<String, Object> event) {
96-
ConfigObject newMailConfig = event.source.grails.mail
97-
Integer newMailConfigHash = newMailConfig.hashCode()
98-
99-
if (newMailConfigHash != mailConfigHash) {
100-
if (createdSession) {
101-
event.ctx.removeBeanDefinition("mailSession")
102-
}
103-
104-
event.ctx.removeBeanDefinition("mailSender")
105-
106-
mailConfig = newMailConfig
107-
mailConfigHash = newMailConfigHash
108-
109-
event.ctx.getBean(MailService.class).setPoolSize(mailConfig.poolSize?:null)
110-
111-
beans {
112-
configureMailSender(delegate, mailConfig)
113-
}
114-
}
115-
}
116-
117-
def configureMailSender(builder, config) {
118-
builder.with {
119-
if (config.jndiName && !springConfig.containsBean("mailSession")) {
120-
mailSession(JndiObjectFactoryBean) {
121-
jndiName = config.jndiName
122-
}
123-
createdSession = true
124-
} else {
125-
createdSession = false
126-
}
127-
128-
mailSender(JavaMailSenderImpl) {
129-
if (config.host) {
130-
host = config.host
131-
} else if (!config.jndiName) {
132-
def envHost = System.getenv()['SMTP_HOST']
133-
if (envHost) {
134-
host = envHost
135-
} else {
136-
host = "localhost"
137-
}
138-
}
139-
140-
if (config.encoding) {
141-
defaultEncoding = config.encoding
142-
} else if (!config.jndiName) {
143-
defaultEncoding = "utf-8"
144-
}
145-
146-
if (config.jndiName)
147-
session = ref('mailSession')
148-
if (config.port)
149-
port = config.port
150-
if (config.username)
151-
username = config.username
152-
if (config.password)
153-
password = config.password
154-
if (config.protocol)
155-
protocol = config.protocol
156-
if (config.props instanceof Map && config.props)
157-
javaMailProperties = config.props.toFlatConfig()
158-
}
68+
Closure doWithSpring() {
69+
{ ->
70+
mailConfiguration(MailConfiguration)
15971
}
16072
}
161-
16273
}

src/main/groovy/grails/plugins/mail/MailMessageBuilder.groovy

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
package grails.plugins.mail
1717

1818
import com.sun.mail.smtp.SMTPMessage
19-
import grails.config.Config
2019
import org.slf4j.Logger
2120
import org.slf4j.LoggerFactory
2221
import org.springframework.core.io.ByteArrayResource
@@ -71,13 +70,13 @@ class MailMessageBuilder {
7170
InputStreamSource toAdd
7271
}
7372

74-
MailMessageBuilder(MailSender mailSender, Config config, MailMessageContentRenderer mailMessageContentRenderer = null) {
73+
MailMessageBuilder(MailSender mailSender, MailConfigurationProperties properties, MailMessageContentRenderer mailMessageContentRenderer = null) {
7574
this.mailSender = mailSender
7675
this.mailMessageContentRenderer = mailMessageContentRenderer
7776

78-
this.overrideAddress = config.getProperty('grails.mail.overrideAddress')
79-
this.defaultFrom = overrideAddress ?: config.getProperty('grails.mail.default.from')
80-
this.defaultTo = overrideAddress ?: config.getProperty('grails.mail.default.to')
77+
this.overrideAddress = properties.overrideAddress
78+
this.defaultFrom = overrideAddress ?: properties.default.from
79+
this.defaultTo = overrideAddress ?: properties.default.to
8180
}
8281

8382
private MailMessage getMessage() {

0 commit comments

Comments
 (0)