or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

configuration-encryption.mdconfiguration-loading.mdconfiguration-management.mdconfiguration-watching.mdindex.mdproperty-source-location.md

configuration-watching.mddocs/

0

# Configuration Watching

1

2

File system monitoring service that watches configuration files and directories for changes, automatically publishing configuration events when modifications are detected. The watching service integrates with CAS event system and supports both file and directory monitoring.

3

4

## Capabilities

5

6

### Configuration Watch Service

7

8

Primary service for monitoring configuration files and directories with automatic event publishing on changes.

9

10

```java { .api }

11

public class CasConfigurationWatchService implements Closeable, InitializingBean {

12

/**

13

* Constructor with application context for event publishing.

14

*

15

* @param applicationContext the configurable application context

16

*/

17

public CasConfigurationWatchService(ConfigurableApplicationContext applicationContext);

18

19

/**

20

* Initialize file and directory watchers based on environment configuration.

21

*/

22

public void initialize();

23

24

/**

25

* Close and cleanup all watch services.

26

*/

27

@Override

28

public void close();

29

30

/**

31

* InitializingBean callback method that calls initialize().

32

*/

33

@Override

34

public void afterPropertiesSet();

35

}

36

```

37

38

## Usage Examples

39

40

### Basic Watch Service Setup

41

42

```java

43

import org.apereo.cas.configuration.CasConfigurationWatchService;

44

import org.springframework.context.ConfigurableApplicationContext;

45

46

// Create watch service with application context

47

CasConfigurationWatchService watchService =

48

new CasConfigurationWatchService(applicationContext);

49

50

// Initialize watchers (automatically called by afterPropertiesSet)

51

watchService.initialize();

52

53

// The service will now monitor:

54

// - Standalone configuration file (if specified)

55

// - Standalone configuration directory (if exists)

56

57

// Later, cleanup when shutting down

58

watchService.close();

59

```

60

61

### Spring Bean Configuration

62

63

```java

64

import org.springframework.context.annotation.Bean;

65

import org.springframework.context.annotation.Configuration;

66

67

@Configuration

68

public class WatchServiceConfiguration {

69

70

@Bean

71

public CasConfigurationWatchService casConfigurationWatchService(

72

ConfigurableApplicationContext applicationContext) {

73

// Spring will automatically call afterPropertiesSet() after bean creation

74

return new CasConfigurationWatchService(applicationContext);

75

}

76

}

77

```

78

79

### Manual Watch Service Management

80

81

```java

82

// Create and configure watch service

83

CasConfigurationWatchService watchService =

84

new CasConfigurationWatchService(applicationContext);

85

86

// Manually initialize (normally done automatically)

87

watchService.initialize();

88

89

// Service is now monitoring for configuration changes

90

91

// At application shutdown

92

try {

93

watchService.close();

94

} catch (Exception e) {

95

logger.warn("Error closing configuration watch service", e);

96

}

97

```

98

99

## Monitoring Behavior

100

101

### File Monitoring

102

103

The watch service monitors the standalone configuration file when:

104

- `cas.standalone.configuration-file` property is set

105

- The specified file exists and is readable

106

107

```java

108

// Set standalone configuration file

109

System.setProperty("cas.standalone.configuration-file", "/etc/cas/config/cas.properties");

110

111

// Watch service will monitor this specific file for:

112

// - Creation (if file is created after service starts)

113

// - Modification (content changes)

114

// - Deletion (if file is removed)

115

```

116

117

### Directory Monitoring

118

119

The watch service monitors the configuration directory when:

120

- A configuration directory is found (via `cas.standalone.configuration-directory` or defaults)

121

- The directory exists and is readable

122

123

```java

124

// Set configuration directory

125

System.setProperty("cas.standalone.configuration-directory", "/etc/cas/config");

126

127

// Watch service will monitor the entire directory for:

128

// - New configuration files created

129

// - Existing configuration files modified

130

// - Configuration files deleted

131

```

132

133

### Default Directory Monitoring

134

135

If no specific directory is configured, the service checks default locations:

136

- `/etc/cas/config`

137

- `/opt/cas/config`

138

- `/var/cas/config`

139

140

The first existing directory will be monitored.

141

142

## Configuration Events

143

144

The watch service publishes different event types based on file system changes:

145

146

### Event Types

147

148

```java { .api }

149

// Event types published by the watch service

150

CasConfigurationCreatedEvent // When configuration files are created

151

CasConfigurationModifiedEvent // When configuration files are modified

152

CasConfigurationDeletedEvent // When configuration files are deleted

153

```

154

155

### Event Handling

156

157

```java

158

import org.apereo.cas.config.CasConfigurationModifiedEvent;

159

import org.springframework.context.event.EventListener;

160

import org.springframework.stereotype.Component;

161

162

@Component

163

public class ConfigurationChangeHandler {

164

165

@EventListener

166

public void handleConfigurationCreated(CasConfigurationCreatedEvent event) {

167

Path configPath = event.getFile();

168

System.out.println("Configuration file created: " + configPath);

169

// Handle new configuration file

170

}

171

172

@EventListener

173

public void handleConfigurationModified(CasConfigurationModifiedEvent event) {

174

Path configPath = event.getFile();

175

System.out.println("Configuration file modified: " + configPath);

176

// Reload configuration, restart services, etc.

177

}

178

179

@EventListener

180

public void handleConfigurationDeleted(CasConfigurationDeletedEvent event) {

181

Path configPath = event.getFile();

182

System.out.println("Configuration file deleted: " + configPath);

183

// Handle missing configuration

184

}

185

}

186

```

187

188

### Event Information

189

190

Each configuration event includes:

191

- **Source**: The `CasConfigurationWatchService` instance

192

- **File Path**: Path to the affected configuration file

193

- **Client Info**: Client information from `ClientInfoHolder` (if available)

194

- **Timestamp**: When the event occurred

195

196

## Watch Service Implementation Details

197

198

### File Watcher Integration

199

200

The service uses CAS utility classes for file system monitoring:

201

202

```java

203

// File watching for specific files

204

FileWatcherService configurationFileWatch = new FileWatcherService(

205

configFile,

206

createConfigurationCreatedEvent.andNext(applicationContext::publishEvent),

207

createConfigurationModifiedEvent.andNext(applicationContext::publishEvent),

208

createConfigurationDeletedEvent.andNext(applicationContext::publishEvent)

209

);

210

211

// Directory watching for configuration directories

212

PathWatcherService configurationDirectoryWatch = new PathWatcherService(

213

configDirectory.toPath(),

214

createConfigurationCreatedEvent.andNext(applicationContext::publishEvent),

215

createConfigurationModifiedEvent.andNext(applicationContext::publishEvent),

216

createConfigurationDeletedEvent.andNext(applicationContext::publishEvent)

217

);

218

```

219

220

### Event Creation Functions

221

222

The service uses composable functions to create events:

223

224

```java { .api }

225

// Function composition for event creation and publishing

226

ComposableFunction<File, AbstractCasEvent> createConfigurationCreatedEvent = file ->

227

new CasConfigurationCreatedEvent(this, file.toPath(), ClientInfoHolder.getClientInfo());

228

229

ComposableFunction<File, AbstractCasEvent> createConfigurationModifiedEvent = file ->

230

new CasConfigurationModifiedEvent(this, file.toPath(), ClientInfoHolder.getClientInfo());

231

232

ComposableFunction<File, AbstractCasEvent> createConfigurationDeletedEvent = file ->

233

new CasConfigurationDeletedEvent(this, file.toPath(), ClientInfoHolder.getClientInfo());

234

```

235

236

## Configuration Properties

237

238

### Watch Service Configuration

239

240

The watch service behavior is controlled by these configuration properties:

241

242

```properties

243

# Standalone configuration file path

244

cas.standalone.configuration-file=/path/to/cas.properties

245

246

# Standalone configuration directory path

247

cas.standalone.configuration-directory=/etc/cas/config

248

249

# Profile settings that affect watching

250

spring.profiles.active=standalone

251

```

252

253

### Profile-Based Behavior

254

255

The watch service respects CAS profiles:

256

257

- **`none` profile**: Skips directory watching entirely

258

- **Other profiles**: Normal watching behavior

259

- **Multiple profiles**: Uses profile precedence rules

260

261

```java

262

// Profile "none" disables directory watching

263

System.setProperty("spring.profiles.active", "none");

264

// Directory watching will be skipped

265

266

// Standalone profile enables normal watching

267

System.setProperty("spring.profiles.active", "standalone");

268

// Normal file and directory watching

269

```

270

271

## Lifecycle Management

272

273

### Initialization Lifecycle

274

275

1. **Service Creation**: Constructor receives application context

276

2. **afterPropertiesSet()**: Spring calls this method after bean initialization

277

3. **initialize()**: Sets up file and directory watchers based on environment

278

4. **Watch Services Start**: Background threads begin monitoring file system

279

5. **Event Publishing**: Changes trigger event publication to application context

280

281

### Shutdown Lifecycle

282

283

1. **close()**: Called during application shutdown or manual cleanup

284

2. **Stop Watchers**: Background monitoring threads are stopped

285

3. **Resource Cleanup**: File handles and system resources are released

286

287

### Error Handling

288

289

The watch service handles various error conditions:

290

291

- **Missing Files**: Gracefully handles non-existent configuration files

292

- **Permission Errors**: Logs warnings for unreadable files or directories

293

- **I/O Errors**: Continues operation when individual file operations fail

294

- **Shutdown Errors**: Ensures cleanup even if watchers fail to stop cleanly

295

296

## Performance Considerations

297

298

### Resource Usage

299

300

- **File Handles**: One file handle per monitored file/directory

301

- **Background Threads**: Minimal thread usage for file system monitoring

302

- **Memory Usage**: Low memory footprint for event handling

303

304

### Monitoring Scope

305

306

- **File Monitoring**: Watches specific files only

307

- **Directory Monitoring**: Watches entire directories (not recursive)

308

- **Event Frequency**: Events published only on actual changes (not periodic checks)

309

310

### Scalability

311

312

- **Multiple Files**: Can monitor both file and directory simultaneously

313

- **Event Processing**: Asynchronous event publishing doesn't block file operations

314

- **Resource Limits**: Bounded by system file watching capabilities