Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in / Register
Toggle navigation
S
spring-boot
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
DEMO
spring-boot
Commits
fe1f344a
Commit
fe1f344a
authored
Jun 01, 2015
by
Phillip Webb
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add livereload auto-configuration
Add auto-configuration to start and trigger livereload. Closes gh-3085
parent
a9f69e86
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
273 additions
and
0 deletions
+273
-0
DeveloperToolsProperties.java
...evelopertools/autoconfigure/DeveloperToolsProperties.java
+39
-0
LocalDeveloperToolsAutoConfiguration.java
...s/autoconfigure/LocalDeveloperToolsAutoConfiguration.java
+42
-0
OptionalLiveReloadServer.java
...evelopertools/autoconfigure/OptionalLiveReloadServer.java
+77
-0
LocalDeveloperToolsAutoConfigurationTests.java
...oconfigure/LocalDeveloperToolsAutoConfigurationTests.java
+64
-0
OptionalLiveReloadServerTests.java
...pertools/autoconfigure/OptionalLiveReloadServerTests.java
+51
-0
No files found.
spring-boot-developer-tools/src/main/java/org/springframework/boot/developertools/autoconfigure/DeveloperToolsProperties.java
View file @
fe1f344a
...
@@ -31,10 +31,16 @@ public class DeveloperToolsProperties {
...
@@ -31,10 +31,16 @@ public class DeveloperToolsProperties {
private
Restart
restart
=
new
Restart
();
private
Restart
restart
=
new
Restart
();
private
Livereload
livereload
=
new
Livereload
();
public
Restart
getRestart
()
{
public
Restart
getRestart
()
{
return
this
.
restart
;
return
this
.
restart
;
}
}
public
Livereload
getLivereload
()
{
return
this
.
livereload
;
}
/**
/**
* Restart properties
* Restart properties
*/
*/
...
@@ -68,4 +74,37 @@ public class DeveloperToolsProperties {
...
@@ -68,4 +74,37 @@ public class DeveloperToolsProperties {
}
}
/**
* LiveReload properties
*/
public
static
class
Livereload
{
/**
* Enable a livereload.com compatible server.
*/
private
boolean
enabled
=
true
;
/**
* Server port.
*/
private
int
port
=
35729
;
public
boolean
isEnabled
()
{
return
this
.
enabled
;
}
public
void
setEnabled
(
boolean
enabled
)
{
this
.
enabled
=
enabled
;
}
public
int
getPort
()
{
return
this
.
port
;
}
public
void
setPort
(
int
port
)
{
this
.
port
=
port
;
}
}
}
}
spring-boot-developer-tools/src/main/java/org/springframework/boot/developertools/autoconfigure/LocalDeveloperToolsAutoConfiguration.java
View file @
fe1f344a
...
@@ -27,10 +27,13 @@ import org.springframework.boot.developertools.classpath.ClassPathChangedEvent;
...
@@ -27,10 +27,13 @@ import org.springframework.boot.developertools.classpath.ClassPathChangedEvent;
import
org.springframework.boot.developertools.classpath.ClassPathFileSystemWatcher
;
import
org.springframework.boot.developertools.classpath.ClassPathFileSystemWatcher
;
import
org.springframework.boot.developertools.classpath.ClassPathRestartStrategy
;
import
org.springframework.boot.developertools.classpath.ClassPathRestartStrategy
;
import
org.springframework.boot.developertools.classpath.PatternClassPathRestartStrategy
;
import
org.springframework.boot.developertools.classpath.PatternClassPathRestartStrategy
;
import
org.springframework.boot.developertools.livereload.LiveReloadServer
;
import
org.springframework.boot.developertools.restart.ConditionalOnInitializedRestarter
;
import
org.springframework.boot.developertools.restart.ConditionalOnInitializedRestarter
;
import
org.springframework.boot.developertools.restart.RestartScope
;
import
org.springframework.boot.developertools.restart.Restarter
;
import
org.springframework.boot.developertools.restart.Restarter
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.context.event.ContextRefreshedEvent
;
import
org.springframework.context.event.EventListener
;
import
org.springframework.context.event.EventListener
;
/**
/**
...
@@ -52,6 +55,45 @@ public class LocalDeveloperToolsAutoConfiguration {
...
@@ -52,6 +55,45 @@ public class LocalDeveloperToolsAutoConfiguration {
return
new
LocalDeveloperPropertyDefaultsPostProcessor
();
return
new
LocalDeveloperPropertyDefaultsPostProcessor
();
}
}
/**
* Local LiveReload configuration.
*/
@ConditionalOnProperty
(
prefix
=
"spring.developertools.livereload"
,
name
=
"enabled"
,
matchIfMissing
=
true
)
static
class
LiveReloadConfiguration
{
@Autowired
private
DeveloperToolsProperties
properties
;
@Autowired
(
required
=
false
)
private
LiveReloadServer
liveReloadServer
;
@Bean
@RestartScope
@ConditionalOnMissingBean
public
LiveReloadServer
liveReloadServer
()
{
return
new
LiveReloadServer
(
this
.
properties
.
getLivereload
().
getPort
(),
Restarter
.
getInstance
().
getThreadFactory
());
}
@EventListener
public
void
onContextRefreshed
(
ContextRefreshedEvent
event
)
{
optionalLiveReloadServer
().
triggerReload
();
}
@EventListener
public
void
onClassPathChanged
(
ClassPathChangedEvent
event
)
{
if
(!
event
.
isRestartRequired
())
{
optionalLiveReloadServer
().
triggerReload
();
}
}
@Bean
public
OptionalLiveReloadServer
optionalLiveReloadServer
()
{
return
new
OptionalLiveReloadServer
(
this
.
liveReloadServer
);
}
}
/**
/**
* Local Restart Configuration.
* Local Restart Configuration.
*/
*/
...
...
spring-boot-developer-tools/src/main/java/org/springframework/boot/developertools/autoconfigure/OptionalLiveReloadServer.java
0 → 100644
View file @
fe1f344a
/*
* Copyright 2012-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
org
.
springframework
.
boot
.
developertools
.
autoconfigure
;
import
javax.annotation.PostConstruct
;
import
org.apache.commons.logging.Log
;
import
org.apache.commons.logging.LogFactory
;
import
org.springframework.boot.developertools.livereload.LiveReloadServer
;
/**
* Manages an optional {@link LiveReloadServer}. The {@link LiveReloadServer} may
* gracefully fail to start (e.g. because of a port conflict) or may be omitted entirely.
*
* @author Phillip Webb
* @since 1.3.0
*/
public
class
OptionalLiveReloadServer
{
private
static
final
Log
logger
=
LogFactory
.
getLog
(
OptionalLiveReloadServer
.
class
);
private
LiveReloadServer
server
;
/**
* Create a new {@link OptionalLiveReloadServer} instance.
* @param server the server to manage or {@code null}
*/
public
OptionalLiveReloadServer
(
LiveReloadServer
server
)
{
this
.
server
=
server
;
}
/**
* {@link PostConstruct} method to start the server if possible.
* @throws Exception
*/
@PostConstruct
public
void
startServer
()
throws
Exception
{
if
(
this
.
server
!=
null
)
{
try
{
if
(!
this
.
server
.
isStarted
())
{
this
.
server
.
start
();
}
logger
.
info
(
"LiveReload server is running on port "
+
this
.
server
.
getPort
());
}
catch
(
Exception
ex
)
{
logger
.
warn
(
"Unable to start LiveReload server"
);
logger
.
debug
(
"Live reload start error"
,
ex
);
this
.
server
=
null
;
}
}
}
/**
* Trigger LiveReload if the server is up an running.
*/
public
void
triggerReload
()
{
if
(
this
.
server
!=
null
)
{
this
.
server
.
triggerReload
();
}
}
}
spring-boot-developer-tools/src/test/java/org/springframework/boot/developertools/autoconfigure/LocalDeveloperToolsAutoConfigurationTests.java
View file @
fe1f344a
...
@@ -30,19 +30,24 @@ import org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfigurati
...
@@ -30,19 +30,24 @@ import org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfigurati
import
org.springframework.boot.developertools.classpath.ClassPathChangedEvent
;
import
org.springframework.boot.developertools.classpath.ClassPathChangedEvent
;
import
org.springframework.boot.developertools.classpath.ClassPathFileSystemWatcher
;
import
org.springframework.boot.developertools.classpath.ClassPathFileSystemWatcher
;
import
org.springframework.boot.developertools.filewatch.ChangedFiles
;
import
org.springframework.boot.developertools.filewatch.ChangedFiles
;
import
org.springframework.boot.developertools.livereload.LiveReloadServer
;
import
org.springframework.boot.developertools.restart.MockRestartInitializer
;
import
org.springframework.boot.developertools.restart.MockRestartInitializer
;
import
org.springframework.boot.developertools.restart.MockRestarter
;
import
org.springframework.boot.developertools.restart.MockRestarter
;
import
org.springframework.boot.developertools.restart.Restarter
;
import
org.springframework.boot.developertools.restart.Restarter
;
import
org.springframework.context.ConfigurableApplicationContext
;
import
org.springframework.context.ConfigurableApplicationContext
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.context.annotation.Import
;
import
org.springframework.context.annotation.Import
;
import
org.springframework.context.event.ContextRefreshedEvent
;
import
org.springframework.util.SocketUtils
;
import
org.springframework.util.SocketUtils
;
import
org.thymeleaf.templateresolver.TemplateResolver
;
import
org.thymeleaf.templateresolver.TemplateResolver
;
import
static
org
.
hamcrest
.
Matchers
.
equalTo
;
import
static
org
.
hamcrest
.
Matchers
.
equalTo
;
import
static
org
.
hamcrest
.
Matchers
.
notNullValue
;
import
static
org
.
hamcrest
.
Matchers
.
notNullValue
;
import
static
org
.
junit
.
Assert
.
assertThat
;
import
static
org
.
junit
.
Assert
.
assertThat
;
import
static
org
.
mockito
.
Mockito
.
mock
;
import
static
org
.
mockito
.
Mockito
.
never
;
import
static
org
.
mockito
.
Mockito
.
never
;
import
static
org
.
mockito
.
Mockito
.
reset
;
import
static
org
.
mockito
.
Mockito
.
verify
;
import
static
org
.
mockito
.
Mockito
.
verify
;
/**
/**
...
@@ -77,6 +82,53 @@ public class LocalDeveloperToolsAutoConfigurationTests {
...
@@ -77,6 +82,53 @@ public class LocalDeveloperToolsAutoConfigurationTests {
assertThat
(
resolver
.
isCacheable
(),
equalTo
(
false
));
assertThat
(
resolver
.
isCacheable
(),
equalTo
(
false
));
}
}
@Test
public
void
liveReloadServer
()
throws
Exception
{
this
.
context
=
initializeAndRun
(
Config
.
class
);
LiveReloadServer
server
=
this
.
context
.
getBean
(
LiveReloadServer
.
class
);
assertThat
(
server
.
isStarted
(),
equalTo
(
true
));
}
@Test
public
void
liveReloadTriggeredOnContextRefresh
()
throws
Exception
{
this
.
context
=
initializeAndRun
(
ConfigWithMockLiveReload
.
class
);
LiveReloadServer
server
=
this
.
context
.
getBean
(
LiveReloadServer
.
class
);
reset
(
server
);
this
.
context
.
publishEvent
(
new
ContextRefreshedEvent
(
this
.
context
));
verify
(
server
).
triggerReload
();
}
@Test
public
void
liveReloadTriggerdOnClassPathChangeWithoutRestart
()
throws
Exception
{
this
.
context
=
initializeAndRun
(
ConfigWithMockLiveReload
.
class
);
LiveReloadServer
server
=
this
.
context
.
getBean
(
LiveReloadServer
.
class
);
reset
(
server
);
ClassPathChangedEvent
event
=
new
ClassPathChangedEvent
(
this
.
context
,
Collections
.<
ChangedFiles
>
emptySet
(),
false
);
this
.
context
.
publishEvent
(
event
);
verify
(
server
).
triggerReload
();
}
@Test
public
void
liveReloadNotTriggerdOnClassPathChangeWithRestart
()
throws
Exception
{
this
.
context
=
initializeAndRun
(
ConfigWithMockLiveReload
.
class
);
LiveReloadServer
server
=
this
.
context
.
getBean
(
LiveReloadServer
.
class
);
reset
(
server
);
ClassPathChangedEvent
event
=
new
ClassPathChangedEvent
(
this
.
context
,
Collections
.<
ChangedFiles
>
emptySet
(),
true
);
this
.
context
.
publishEvent
(
event
);
verify
(
server
,
never
()).
triggerReload
();
}
@Test
public
void
liveReloadDisabled
()
throws
Exception
{
Map
<
String
,
Object
>
properties
=
new
HashMap
<
String
,
Object
>();
properties
.
put
(
"spring.developertools.livereload.enabled"
,
false
);
this
.
context
=
initializeAndRun
(
Config
.
class
,
properties
);
this
.
thrown
.
expect
(
NoSuchBeanDefinitionException
.
class
);
this
.
context
.
getBean
(
OptionalLiveReloadServer
.
class
);
}
@Test
@Test
public
void
restartTriggerdOnClassPathChangeWithRestart
()
throws
Exception
{
public
void
restartTriggerdOnClassPathChangeWithRestart
()
throws
Exception
{
this
.
context
=
initializeAndRun
(
Config
.
class
);
this
.
context
=
initializeAndRun
(
Config
.
class
);
...
@@ -142,4 +194,16 @@ public class LocalDeveloperToolsAutoConfigurationTests {
...
@@ -142,4 +194,16 @@ public class LocalDeveloperToolsAutoConfigurationTests {
}
}
@Configuration
@Import
({
LocalDeveloperToolsAutoConfiguration
.
class
,
ThymeleafAutoConfiguration
.
class
})
public
static
class
ConfigWithMockLiveReload
{
@Bean
public
LiveReloadServer
liveReloadServer
()
{
return
mock
(
LiveReloadServer
.
class
);
}
}
}
}
spring-boot-developer-tools/src/test/java/org/springframework/boot/developertools/autoconfigure/OptionalLiveReloadServerTests.java
0 → 100644
View file @
fe1f344a
/*
* Copyright 2012-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
org
.
springframework
.
boot
.
developertools
.
autoconfigure
;
import
org.junit.Test
;
import
org.springframework.boot.developertools.livereload.LiveReloadServer
;
import
static
org
.
mockito
.
BDDMockito
.
willThrow
;
import
static
org
.
mockito
.
Mockito
.
mock
;
import
static
org
.
mockito
.
Mockito
.
never
;
import
static
org
.
mockito
.
Mockito
.
verify
;
/**
* Tests for {@link OptionalLiveReloadServer}.
*
* @author Phillip Webb
*/
public
class
OptionalLiveReloadServerTests
{
@Test
public
void
nullServer
()
throws
Exception
{
OptionalLiveReloadServer
server
=
new
OptionalLiveReloadServer
(
null
);
server
.
startServer
();
server
.
triggerReload
();
}
@Test
public
void
serverWontStart
()
throws
Exception
{
LiveReloadServer
delegate
=
mock
(
LiveReloadServer
.
class
);
OptionalLiveReloadServer
server
=
new
OptionalLiveReloadServer
(
delegate
);
willThrow
(
new
RuntimeException
(
"Error"
)).
given
(
delegate
).
start
();
server
.
startServer
();
server
.
triggerReload
();
verify
(
delegate
,
never
()).
triggerReload
();
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment