or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

core-marshalling.mdindex.mdjaxb-implementation.mdmime-support.mdsupport-utilities.mdxstream-implementation.md

mime-support.mddocs/

0

# MIME Attachment Support

1

2

MIME attachment support enables optimized handling of binary data in XML through MIME attachments using MTOM (Message Transmission Optimization Mechanism), XOP (XML-binary Optimized Packaging), or SwA (SOAP with Attachments) protocols.

3

4

## Core Interfaces

5

6

### MimeMarshaller

7

8

Extended marshaller interface that supports MIME attachments during marshalling.

9

10

```java { .api }

11

public interface MimeMarshaller extends Marshaller {

12

/**

13

* Marshals the object graph with the given root into the provided Result,

14

* writing binary data to a MimeContainer.

15

* @param graph the root of the object graph to marshal

16

* @param result the result to marshal to

17

* @param mimeContainer the MIME container to write extracted binary content to

18

* @throws XmlMappingException if the given object cannot be marshalled to the result

19

* @throws IOException if an I/O exception occurs

20

*/

21

void marshal(Object graph, Result result, @Nullable MimeContainer mimeContainer)

22

throws XmlMappingException, IOException;

23

}

24

```

25

26

### MimeUnmarshaller

27

28

Extended unmarshaller interface that supports MIME attachments during unmarshalling.

29

30

```java { .api }

31

public interface MimeUnmarshaller extends Unmarshaller {

32

/**

33

* Unmarshals the given provided Source into an object graph,

34

* reading binary attachments from a MimeContainer.

35

* @param source the source to marshal from

36

* @param mimeContainer the MIME container to read extracted binary content from

37

* @return the object graph

38

* @throws XmlMappingException if the given source cannot be mapped to an object

39

* @throws IOException if an I/O Exception occurs

40

*/

41

Object unmarshal(Source source, @Nullable MimeContainer mimeContainer)

42

throws XmlMappingException, IOException;

43

}

44

```

45

46

### MimeContainer

47

48

Container interface for managing MIME attachments and XOP packages.

49

50

```java { .api }

51

public interface MimeContainer {

52

/**

53

* Indicate whether this container is a XOP package.

54

* @return true when the constraints specified in XOP Documents are met

55

*/

56

boolean isXopPackage();

57

58

/**

59

* Turn this message into a XOP package.

60

* @return true when the message actually is a XOP package

61

*/

62

boolean convertToXopPackage();

63

64

/**

65

* Add the given data handler as an attachment to this container.

66

* @param contentId the content id of the attachment

67

* @param dataHandler the data handler containing the data of the attachment

68

*/

69

void addAttachment(String contentId, DataHandler dataHandler);

70

71

/**

72

* Return the attachment with the given content id, or null if not found.

73

* @param contentId the content id

74

* @return the attachment, as a data handler

75

*/

76

@Nullable

77

DataHandler getAttachment(String contentId);

78

}

79

```

80

81

## Usage Examples

82

83

### Basic MIME Marshalling

84

85

```java

86

import org.springframework.oxm.mime.MimeMarshaller;

87

import org.springframework.oxm.mime.MimeContainer;

88

import jakarta.activation.DataHandler;

89

import jakarta.activation.ByteArrayDataSource;

90

import javax.xml.transform.stream.StreamResult;

91

import java.io.StringWriter;

92

93

// Assuming you have a MimeMarshaller implementation (like Jaxb2Marshaller)

94

MimeMarshaller mimeMarshaller = // ... get mime marshaller

95

96

// Create a MimeContainer implementation

97

MimeContainer mimeContainer = new MimeContainer() {

98

private Map<String, DataHandler> attachments = new HashMap<>();

99

private boolean isXop = false;

100

101

@Override

102

public boolean isXopPackage() { return isXop; }

103

104

@Override

105

public boolean convertToXopPackage() {

106

isXop = true;

107

return true;

108

}

109

110

@Override

111

public void addAttachment(String contentId, DataHandler dataHandler) {

112

attachments.put(contentId, dataHandler);

113

}

114

115

@Override

116

public DataHandler getAttachment(String contentId) {

117

return attachments.get(contentId);

118

}

119

};

120

121

// Object with binary data

122

DocumentWithAttachment document = new DocumentWithAttachment();

123

document.setTitle("My Document");

124

document.setContent("Document content");

125

document.setBinaryData(new byte[]{ /* large binary data */ });

126

127

// Marshal with MIME container

128

StringWriter writer = new StringWriter();

129

mimeMarshaller.marshal(document, new StreamResult(writer), mimeContainer);

130

131

// The XML will contain references to attachments

132

String xml = writer.toString();

133

// Binary data is stored in mimeContainer attachments

134

```

135

136

### MIME Unmarshalling

137

138

```java

139

import org.springframework.oxm.mime.MimeUnmarshaller;

140

import javax.xml.transform.stream.StreamSource;

141

import java.io.StringReader;

142

143

// Assuming you have the XML and populated MimeContainer from marshalling

144

String xmlWithReferences = // ... XML with attachment references

145

MimeContainer populatedContainer = // ... container with attachments

146

147

MimeUnmarshaller mimeUnmarshaller = // ... get mime unmarshaller

148

149

// Unmarshal with MIME container

150

StringReader reader = new StringReader(xmlWithReferences);

151

DocumentWithAttachment document = (DocumentWithAttachment)

152

mimeUnmarshaller.unmarshal(new StreamSource(reader), populatedContainer);

153

154

// Binary data is restored from attachments

155

byte[] binaryData = document.getBinaryData();

156

```

157

158

### JAXB with MIME Support

159

160

The `Jaxb2Marshaller` implements both `MimeMarshaller` and `MimeUnmarshaller`:

161

162

```java

163

import org.springframework.oxm.jaxb.Jaxb2Marshaller;

164

import jakarta.xml.bind.annotation.XmlRootElement;

165

import jakarta.xml.bind.annotation.XmlMimeType;

166

import jakarta.activation.DataHandler;

167

168

// JAXB class with MIME type annotation

169

@XmlRootElement

170

public class DocumentWithImage {

171

private String title;

172

173

@XmlMimeType("image/jpeg")

174

private DataHandler imageData;

175

176

// getters and setters...

177

}

178

179

// Configure JAXB marshaller for MIME support

180

Jaxb2Marshaller marshaller = new Jaxb2Marshaller();

181

marshaller.setClassesToBeBound(DocumentWithImage.class);

182

marshaller.setMtomEnabled(true); // Enable MTOM support

183

marshaller.afterPropertiesSet();

184

185

// Create document with image

186

DocumentWithImage doc = new DocumentWithImage();

187

doc.setTitle("Document with Image");

188

189

// Create DataHandler for image

190

byte[] imageBytes = // ... load image data

191

DataHandler imageHandler = new DataHandler(

192

new ByteArrayDataSource(imageBytes, "image/jpeg")

193

);

194

doc.setImageData(imageHandler);

195

196

// Marshal with MIME container

197

MimeContainer container = // ... your container implementation

198

StringWriter writer = new StringWriter();

199

marshaller.marshal(doc, new StreamResult(writer), container);

200

```

201

202

### XOP Package Handling

203

204

```java

205

// Working with XOP packages

206

MimeContainer container = // ... your container

207

208

// Check if container supports XOP

209

if (!container.isXopPackage()) {

210

// Convert to XOP package for optimized binary handling

211

boolean converted = container.convertToXopPackage();

212

if (converted) {

213

System.out.println("Container converted to XOP package");

214

}

215

}

216

217

// Add binary data as attachment

218

byte[] binaryData = // ... your binary data

219

DataHandler dataHandler = new DataHandler(

220

new ByteArrayDataSource(binaryData, "application/octet-stream")

221

);

222

container.addAttachment("binary-content-1", dataHandler);

223

```

224

225

### Custom MimeContainer Implementation

226

227

```java

228

import java.util.concurrent.ConcurrentHashMap;

229

import java.util.Map;

230

231

public class SimpleMimeContainer implements MimeContainer {

232

private final Map<String, DataHandler> attachments = new ConcurrentHashMap<>();

233

private volatile boolean isXopPackage = false;

234

235

@Override

236

public boolean isXopPackage() {

237

return isXopPackage;

238

}

239

240

@Override

241

public boolean convertToXopPackage() {

242

this.isXopPackage = true;

243

return true;

244

}

245

246

@Override

247

public void addAttachment(String contentId, DataHandler dataHandler) {

248

if (contentId == null || dataHandler == null) {

249

throw new IllegalArgumentException("ContentId and DataHandler cannot be null");

250

}

251

attachments.put(contentId, dataHandler);

252

}

253

254

@Override

255

public DataHandler getAttachment(String contentId) {

256

return attachments.get(contentId);

257

}

258

259

// Additional utility methods

260

public Set<String> getAttachmentIds() {

261

return attachments.keySet();

262

}

263

264

public int getAttachmentCount() {

265

return attachments.size();

266

}

267

268

public void clearAttachments() {

269

attachments.clear();

270

}

271

}

272

```

273

274

## JAXB MIME Annotations

275

276

When using JAXB with MIME support, use these annotations:

277

278

```java

279

import jakarta.xml.bind.annotation.*;

280

import jakarta.activation.DataHandler;

281

import java.awt.Image;

282

283

@XmlRootElement

284

public class MultimediaDocument {

285

286

@XmlElement

287

private String title;

288

289

// Binary data as DataHandler with MIME type

290

@XmlMimeType("image/jpeg")

291

private DataHandler photo;

292

293

// Binary data as byte array

294

@XmlMimeType("application/pdf")

295

private byte[] pdfContent;

296

297

// Image data

298

@XmlMimeType("image/png")

299

private Image diagram;

300

301

// getters and setters...

302

}

303

```

304

305

## MTOM Configuration

306

307

Message Transmission Optimization Mechanism (MTOM) configuration:

308

309

```java

310

import org.springframework.oxm.jaxb.Jaxb2Marshaller;

311

312

Jaxb2Marshaller marshaller = new Jaxb2Marshaller();

313

marshaller.setClassesToBeBound(MultimediaDocument.class);

314

315

// Enable MTOM for optimized binary transfer

316

marshaller.setMtomEnabled(true);

317

318

// Configure attachment marshaller/unmarshaller if needed

319

marshaller.setAttachmentMarshaller(customAttachmentMarshaller);

320

marshaller.setAttachmentUnmarshaller(customAttachmentUnmarshaller);

321

322

marshaller.afterPropertiesSet();

323

```

324

325

## Error Handling

326

327

```java

328

try {

329

MimeContainer container = new SimpleMimeContainer();

330

DocumentWithAttachment doc = new DocumentWithAttachment();

331

332

StringWriter writer = new StringWriter();

333

mimeMarshaller.marshal(doc, new StreamResult(writer), container);

334

335

} catch (XmlMappingException e) {

336

System.err.println("MIME marshalling failed: " + e.getMessage());

337

338

// Check for specific MIME-related errors

339

Throwable cause = e.getCause();

340

if (cause instanceof jakarta.xml.bind.MarshalException) {

341

System.err.println("JAXB marshalling error: " + cause.getMessage());

342

}

343

}

344

```

345

346

## Required Imports

347

348

```java

349

import org.springframework.oxm.mime.MimeMarshaller;

350

import org.springframework.oxm.mime.MimeUnmarshaller;

351

import org.springframework.oxm.mime.MimeContainer;

352

import org.springframework.oxm.XmlMappingException;

353

354

import jakarta.activation.DataHandler;

355

import jakarta.activation.DataSource;

356

import jakarta.activation.ByteArrayDataSource;

357

import jakarta.xml.bind.annotation.XmlMimeType;

358

import jakarta.xml.bind.attachment.AttachmentMarshaller;

359

import jakarta.xml.bind.attachment.AttachmentUnmarshaller;

360

361

import javax.xml.transform.Result;

362

import javax.xml.transform.Source;

363

import javax.xml.transform.stream.StreamResult;

364

import javax.xml.transform.stream.StreamSource;

365

366

import java.io.IOException;

367

import java.util.Map;

368

import java.util.HashMap;

369

import java.util.concurrent.ConcurrentHashMap;

370

```

371

372

## Best Practices

373

374

1. **Use MTOM for large binary data**: Enable MTOM when dealing with large binary attachments

375

2. **Content-ID management**: Use meaningful content IDs for attachments

376

3. **Memory considerations**: Be aware that large attachments are held in memory

377

4. **Security**: Validate attachment content types and sizes

378

5. **Cleanup**: Properly dispose of DataHandler resources when done

379

6. **XOP package conversion**: Convert to XOP packages for better optimization when dealing with multiple binary attachments