0
# Core Plugin Development
1
2
Essential interfaces and base classes for creating Maven plugins. Provides the fundamental Mojo contract and ready-to-use AbstractMojo base class with logging and context support.
3
4
## Capabilities
5
6
### Mojo Interface
7
8
The main contract required for all Maven plugins to interact with the Maven infrastructure. Every plugin must implement this interface to define its execution behavior and integrate with Maven's logging system.
9
10
```java { .api }
11
/**
12
* Main contract for Maven plugins (Mojos) to interact with Maven infrastructure
13
*/
14
public interface Mojo {
15
/** The component role hint for Plexus container */
16
String ROLE = Mojo.class.getName();
17
18
/**
19
* Perform whatever build-process behavior this Mojo implements.
20
* Main trigger for the Mojo inside the Maven system.
21
*
22
* @throws MojoExecutionException if an unexpected problem occurs (BUILD ERROR)
23
* @throws MojoFailureException if an expected problem occurs (BUILD FAILURE)
24
*/
25
void execute() throws MojoExecutionException, MojoFailureException;
26
27
/**
28
* Inject a standard Maven logging mechanism
29
* @param log a new logger
30
*/
31
void setLog(Log log);
32
33
/**
34
* Get access to the Maven logging mechanism
35
* @return logger for creating messages at debug, info, warn, and error levels
36
*/
37
Log getLog();
38
}
39
```
40
41
### AbstractMojo Class
42
43
Abstract base class that provides most infrastructure required to implement a Mojo except for the execute method. Includes built-in logging management with fallback to SystemStreamLog and plugin context support.
44
45
```java { .api }
46
/**
47
* Abstract class providing Mojo infrastructure except for execute method.
48
* Use @Mojo annotation with goal name:
49
* @Mojo(name = "<goal-name>")
50
*/
51
public abstract class AbstractMojo implements Mojo, ContextEnabled {
52
53
/**
54
* Set the logger for this Mojo
55
* @param log the logger instance
56
*/
57
public void setLog(Log log);
58
59
/**
60
* Get the logger, creating SystemStreamLog if none injected
61
* @return logger instance, never null
62
*/
63
public Log getLog();
64
65
/**
66
* Get the plugin container context
67
* @return Map containing shared context data
68
*/
69
public Map getPluginContext();
70
71
/**
72
* Set the plugin container context
73
* @param pluginContext Map of shared context data
74
*/
75
public void setPluginContext(Map pluginContext);
76
}
77
```
78
79
**Usage Example:**
80
81
```java
82
import org.apache.maven.plugin.AbstractMojo;
83
import org.apache.maven.plugin.MojoExecutionException;
84
import org.apache.maven.plugin.MojoFailureException;
85
86
/**
87
* Example plugin demonstrating AbstractMojo usage
88
* @goal process-files
89
* @phase process-sources
90
*/
91
public class ProcessFilesMojo extends AbstractMojo {
92
93
/**
94
* Directory to process
95
* @parameter property="processDir" default-value="${project.basedir}/src/main/resources"
96
*/
97
private File processDirectory;
98
99
/**
100
* Skip processing
101
* @parameter property="skip" default-value="false"
102
*/
103
private boolean skip;
104
105
@Override
106
public void execute() throws MojoExecutionException, MojoFailureException {
107
if (skip) {
108
getLog().info("Skipping file processing");
109
return;
110
}
111
112
getLog().info("Processing files in: " + processDirectory);
113
114
if (!processDirectory.exists()) {
115
throw new MojoFailureException("Process directory does not exist: " + processDirectory);
116
}
117
118
try {
119
// Your plugin logic here
120
processFiles(processDirectory);
121
getLog().info("File processing completed successfully");
122
} catch (IOException e) {
123
throw new MojoExecutionException("Failed to process files", e);
124
}
125
}
126
127
private void processFiles(File directory) throws IOException {
128
getLog().debug("Starting file processing in " + directory);
129
// Implementation details...
130
}
131
}
132
```
133
134
### ContextEnabled Interface
135
136
Interface allowing Mojos to communicate with each other by sharing data through the plugin container context. The plugin manager populates the context before executing Mojos.
137
138
```java { .api }
139
/**
140
* Enables Mojos to share data with other Mojos beyond project's source root and attachments
141
*/
142
public interface ContextEnabled {
143
/**
144
* Set a new shared context Map to a mojo before executing it
145
* @param pluginContext a new Map for sharing data
146
*/
147
void setPluginContext(Map pluginContext);
148
149
/**
150
* Get the Map stored in the plugin container's context
151
* @return Map containing shared context data
152
*/
153
Map getPluginContext();
154
}
155
```
156
157
**Usage Example:**
158
159
```java
160
public class DataProducerMojo extends AbstractMojo {
161
@Override
162
public void execute() throws MojoExecutionException {
163
// Store data for other mojos
164
getPluginContext().put("processedData", someProcessedData);
165
getPluginContext().put("timestamp", System.currentTimeMillis());
166
}
167
}
168
169
public class DataConsumerMojo extends AbstractMojo {
170
@Override
171
public void execute() throws MojoExecutionException {
172
// Retrieve data from other mojos
173
Object data = getPluginContext().get("processedData");
174
Long timestamp = (Long) getPluginContext().get("timestamp");
175
176
if (data != null) {
177
getLog().info("Using data from previous mojo, created at: " + new Date(timestamp));
178
}
179
}
180
}
181
```
182
183
## Mojo Annotations
184
185
When extending AbstractMojo, use these key annotations to configure your plugin:
186
187
### @Mojo Annotation Attributes
188
189
```java
190
@Mojo(
191
name = "goal-name", // Required: Goal name users will invoke
192
defaultPhase = LifecyclePhase.COMPILE, // Optional: Default lifecycle phase
193
requiresDependencyResolution = ResolutionScope.COMPILE, // Optional: Dependency scope needed
194
threadSafe = true // Optional: Can run in parallel builds
195
)
196
```
197
198
### @Parameter Annotation
199
200
```java
201
/**
202
* @parameter property="propertyName" default-value="defaultValue"
203
* @required
204
*/
205
private String configValue;
206
```
207
208
### @Component Annotation
209
210
```java
211
/**
212
* @component
213
*/
214
private SomeComponent injectedComponent;
215
```
216
217
## Error Handling Best Practices
218
219
- **Use MojoExecutionException** for unexpected errors (system failures, I/O errors, etc.)
220
- **Use MojoFailureException** for expected failures (validation errors, missing files that users should fix)
221
- **Always include meaningful error messages** that help users understand what went wrong
222
- **Use the longMessage constructor** for detailed error information in build output