or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

core-plugin-development.mdexception-handling.mdindex.mdlogging-system.mdplugin-descriptors.md

core-plugin-development.mddocs/

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