<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Java on Roland Huß</title><link>https://ro14nd.de/tags/java/</link><description>Recent content in Java on Roland Huß</description><generator>Hugo -- gohugo.io</generator><language>en</language><copyright>© 2026 Roland Huß</copyright><lastBuildDate>Tue, 03 Jul 2018 00:00:00 +0000</lastBuildDate><atom:link href="https://ro14nd.de/tags/java/index.xml" rel="self" type="application/rss+xml"/><item><title>Elegant Camel route configuration</title><link>https://ro14nd.de/camel-routes-simplified/</link><pubDate>Tue, 03 Jul 2018 00:00:00 +0000</pubDate><guid>https://ro14nd.de/camel-routes-simplified/</guid><description>&lt;p&gt;I&amp;rsquo;m a big fan of the &lt;a href="https://camel.apache.org/java-dsl.html" target="_blank" rel="noreferrer"&gt;Camel Java DSL&lt;/a&gt; for defining Camel routes with a &lt;code&gt;RouteBuilder&lt;/code&gt;. This is super easy and slim. However, in this blog post I show you a nerdy trick how this can be done even more elegant.&lt;/p&gt;
&lt;!--
&lt;img src="https://ro14nd.de/images/camel-routes-simplified/camel-logo.png" style="margin-top: 0px; margin-left: 40px; float: right"/&gt;
--&gt;
&lt;p&gt;If you are a Camel user, you know, that defining a route for a given Camel context &lt;code&gt;ctx&lt;/code&gt; ist just a matter to implement the &lt;code&gt;configure()&lt;/code&gt; method of the abstract &lt;code&gt;RouteBuilder&lt;/code&gt; class:&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ctx.&lt;span style="color:#a6e22e"&gt;add&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; RouteBuilder {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;@Override&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;configure&lt;/span&gt;() &lt;span style="color:#66d9ef"&gt;throws&lt;/span&gt; Exception {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; from(&lt;span style="color:#e6db74"&gt;&amp;#34;file:data/inbox?noop=true&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .&lt;span style="color:#a6e22e"&gt;to&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;file:data/outbox&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Its really simple and you can use the whole Camel machinery from within your &lt;code&gt;configure()&lt;/code&gt; method.&lt;/p&gt;
&lt;p&gt;However, this kind of configuration can be performed even simpler. Let&amp;rsquo;s assume that you have a no-op default implementation of &lt;code&gt;RouteBuilder&lt;/code&gt; called &lt;code&gt;Routes&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;Routes&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;extends&lt;/span&gt; RouteBuilder {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;@Override&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;configure&lt;/span&gt;() &lt;span style="color:#66d9ef"&gt;throws&lt;/span&gt; Exception { }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Then, the configuration can be rewritten simply as&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ctx.&lt;span style="color:#a6e22e"&gt;add&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; Routes {{
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; from(&lt;span style="color:#e6db74"&gt;&amp;#34;file:data/inbox?noop=true&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; .&lt;span style="color:#a6e22e"&gt;to&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;file:data/outbox&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}});&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;This trick just uses Java&amp;rsquo;s &lt;a href="https://docs.oracle.com/javase/tutorial/java/javaOO/initial.html" target="_blank" rel="noreferrer"&gt;object initializers&lt;/a&gt;, a not so well known language feature. The inspiration for providing the DSL context like this comes from &lt;a href="https://jmockit.github.io/tutorial/Mocking.html#expectation" target="_blank" rel="noreferrer"&gt;JMockit&lt;/a&gt; which defines its mock expectations the same way. I think object initializers are really an elegant albeit hipster way to implement DSLs.&lt;/p&gt;
&lt;p&gt;Although you can easily define the &lt;code&gt;Routes&lt;/code&gt; class on your own, you might vote for this Camel &lt;a href="https://issues.apache.org/jira/browse/CAMEL-12608" target="_blank" rel="noreferrer"&gt;issue&lt;/a&gt; or &lt;a href="https://github.com/apache/camel/pull/2401" target="_blank" rel="noreferrer"&gt;pull request&lt;/a&gt; if you want to have this in upstream Camel, too.&lt;/p&gt;</description></item><item><title>Java EE Management is dead</title><link>https://ro14nd.de/java-management-is-dead/</link><pubDate>Mon, 10 Oct 2016 00:00:00 +0000</pubDate><guid>https://ro14nd.de/java-management-is-dead/</guid><description>&lt;p&gt;Now that some weeks has been passed we all had time to absorb the &lt;a href="https://java.net/downloads/javaee-spec/JavaEE8Update.pdf" target="_blank" rel="noreferrer"&gt;revised Java EE 8 proposal&lt;/a&gt; presented at Java One. As you know, some JSRs remained, some things were added and some stuff was dropped. &lt;a href="https://www.jcp.org/en/jsr/detail?id=373" target="_blank" rel="noreferrer"&gt;Java EE Management API 2.0&lt;/a&gt;, supposed to be a modern successor of JSR 77, is one of the three JSRs to be dropped.&lt;/p&gt;
&lt;p&gt;What does this mean for the future of Java EE management and monitoring ?&lt;/p&gt;
&lt;p&gt;First of all it&amp;rsquo;s fair to state that &lt;a href="https://www.jcp.org/en/jsr/detail?id=373" target="_blank" rel="noreferrer"&gt;JSR 373&lt;/a&gt; never really took off. Since February 2015 there were not more than &lt;a href="https://java.net/projects/javaee-mgmt/lists/jsr373-experts/archive" target="_blank" rel="noreferrer"&gt;86 mails&lt;/a&gt; on the expert group mailing list, half of them written in March 2015 during incubation. At the latest of January 2016 it was clear that JSR-373 &lt;a href="https://java.net/projects/javaee-mgmt/lists/jsr373-experts/archive/2016-01/message/2" target="_blank" rel="noreferrer"&gt;is not on Oracle&amp;rsquo;s focus anymore&lt;/a&gt;. To be honest, even we members of the expert group, we were not able to push this JSR further.&lt;/p&gt;
&lt;p&gt;How did it come that far ? Let&amp;rsquo;s have a look back into history.&lt;/p&gt;
&lt;p&gt;All starts with &lt;a href="https://jcp.org/en/jsr/detail?id=3" target="_blank" rel="noreferrer"&gt;JSR 3&lt;/a&gt; back in 1999. This first JMX specification is the foundation of all Java resources management. As it can been seen by its age, Java folks took care about Management and Monitoring from the very beginning on. And even better, since &lt;a href="http://docs.oracle.com/javase/1.5.0/docs/guide/management/index.html" target="_blank" rel="noreferrer"&gt;JS2E 5&lt;/a&gt; JMX is integral part of Java SE so its available on every JVM out there.&lt;/p&gt;
&lt;p&gt;Over the years, additional JSRs were added on top of this base:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://jcp.org/en/jsr/detail?id=160" target="_blank" rel="noreferrer"&gt;JSR 160&lt;/a&gt; defines a remote protocol for JMX,, which is based on &lt;a href="http://www.oracle.com/technetwork/java/javase/tech/index-jsp-136424.html" target="_blank" rel="noreferrer"&gt;RMI&lt;/a&gt;. This might have been a good decision in 2003, but turned out to be awful to use especially for non-Java based monitoring systems.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://jcp.org/en/jsr/detail?id=262" target="_blank" rel="noreferrer"&gt;JSR 262&lt;/a&gt; was started to overcome this by defined a &amp;ldquo;WebServices Connector for Java Management Extensions Agents&amp;rdquo; which was mostly around SOAP services. However although even an initial implementation existed, it was withdrawn before the final release. It&amp;rsquo;s not completely clear why it was stopped in 2008 and later withdrawn, as the &lt;a href="https://jcp.org/en/jsr/results?id=4548" target="_blank" rel="noreferrer"&gt;public review ballot has been approved&lt;/a&gt;, although it was a tight result. The biggest objections were on dependencies on &amp;ldquo;proprietary&amp;rdquo; WS-* specifications.&lt;/li&gt;
&lt;li&gt;&amp;ldquo;J2EE Management&amp;rdquo; &lt;a href="https://jcp.org/en/jsr/detail?id=77" target="_blank" rel="noreferrer"&gt;JSR 77&lt;/a&gt; was finished in 2002 and defines a hierarchy how Management and Monitoring resources exposed by a Java EE server is structured. It allows a uniform interface for how to access the various Java EE resources, like web applications or connector pools. Beside this it also defines how statistics are exposed by defining various metrics formats. However, implementing the &lt;code&gt;StatisticsProvider&lt;/code&gt; model is not mandatory and from my personal experience it was implemented only rarely by some vendors and if so, not for every resource.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://jcp.org/en/jsr/detail?id=88" target="_blank" rel="noreferrer"&gt;JSR 88&lt;/a&gt; complements JSR 77 and defines a common format for deploying Java EE artefacts.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://jcp.org/en/jsr/detail?id=255" target="_blank" rel="noreferrer"&gt;JSR 255&lt;/a&gt; was started to be the next version of JMX and supposed to be included in Java 7. Although it was already nearly finished and integrated, &lt;a href="https://community.oracle.com/blogs/emcmanus/2009/06/16/jsr-255-jmx-api-20-postponed" target="_blank" rel="noreferrer"&gt;it didn&amp;rsquo;t make it into Java 7&lt;/a&gt; (nor Java 8). The spec was then dormant until it was finally withdrawn in 2016.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With the dead of JMX 2.0 in 2009 the evolution of JMX as a standard for Java SE has stalled. But what&amp;rsquo;s about Java EE Management ? At least JSR 77 is still part of Java EE 7 and for Java EE 8 the successor was supposed to be JSR 373. JSR 373 tackles the problem of remote access, whereas JSR 77 still relies on RMI as a standard implementation protocol as defined in JSR 160.&lt;/p&gt;
&lt;p&gt;The two major goals of JSR 373 were:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Provide an update of the hierarchal resource and statistics structure as defined by JSR 77&lt;/li&gt;
&lt;li&gt;Provide a REST access to these resources independent of JMX&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In the often cited &lt;a href="https://java.net/downloads/javaee-spec/JavaEE8_Community_Survey_Results.pdf" target="_blank" rel="noreferrer"&gt;Java EE 8 Community Survey&lt;/a&gt; more than 60% were in favour of defining a new API for managing application, which should be based on REST (83% pro-votes). This finally lead to JSR 373. However, as it seems in retrospective, a deep interest in this topic was not really given and probably lead to this final decision to drop JSR 373 from Java EE 8.&lt;/p&gt;
&lt;p&gt;So, what is the state of Monitoring and Management of Java and in particular Java EE applications nowadays and what can be expected in the future ? Let&amp;rsquo;s have a look into the crystal ball.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;JMX is here to stay&lt;/strong&gt;. It is part of Java SE and I don&amp;rsquo;t know of any plans for removing it from future Java editions. Ok, it feels a bit rusty but it is still rock solid and gives you deep insight in the state of your JVM. With tools like &lt;a href="https://jolokia.org/" target="_blank" rel="noreferrer"&gt;Jolokia&lt;/a&gt; you can overcome most of the restrictions JSR 160 imposes. (Disclaimer: since I&amp;rsquo;m the author of Jolokia all my personal opinions given here should be evaluated in this light :)&lt;/li&gt;
&lt;li&gt;It is not clear how the Management API of Java EE 8 and beyond looks like. It does not look like that JSR 77 will survive. Will there be a standard for Java EE management at all ? Probably not, and so there is the danger that vendors will push their proprietary management APIs, which already &lt;a href="https://docs.jboss.org/author/display/WFLY10/The&amp;#43;HTTP&amp;#43;management&amp;#43;API" target="_blank" rel="noreferrer"&gt;happens&lt;/a&gt; to some extent. Luckily, most of these proprietary APIs are also mirrored in JMX these days.&lt;/li&gt;
&lt;li&gt;On the other hand, it could be also a good thing that there is no other Management API which is not based on JMX. That&amp;rsquo;s because you will always need JMX to monitor the basic aspects like Heap Memory usage or Thread count, which are covered by Java SE. Adding a different, REST like protocol for Java EE monitoring requires operators to access a Java EE server with two different protocols (JMX &lt;strong&gt;and&lt;/strong&gt; Rest), duplicating configuration efforts on the monitoring side. This can only be avoided if the &lt;a href="https://java.net/projects/javaee-mgmt/lists/jsr373-experts/archive/2016-06/message/1" target="_blank" rel="noreferrer"&gt;Java EE resources are mirrored in JMX&lt;/a&gt;, too.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To sum it up, I think its a shame that Management and Monitoring, which played a prominent role over the whole evolution of Java EE, will probably be dropped completely in Java EE 8. As a replacement the new &lt;a href="https://java.net/downloads/javaee-spec/JavaEE8Update.pdf" target="_blank" rel="noreferrer"&gt;Health Check&lt;/a&gt; API has been announced, but to be honest, that can&amp;rsquo;t be a full replacement for classical management and monitoring where the evaluation of a system&amp;rsquo;s health is done on a dedicated monitoring platform (e.g. like Nagios or Prometheus). These platforms take the plain metrics data exposed by the application and does the data evaluation on their own.&lt;/p&gt;
&lt;p&gt;The good thing is still that you have JMX to the rescue and I&amp;rsquo;m pretty sure that this technology will survive also this storm. Especially if vendors are willing to support it for their application server metrics, too.&lt;/p&gt;
&lt;p&gt;Even without a Java EE standard.&lt;/p&gt;</description></item><item><title>Docker for (Java) Developers</title><link>https://ro14nd.de/docker-for-developers/</link><pubDate>Mon, 25 Aug 2014 00:00:00 +0000</pubDate><guid>https://ro14nd.de/docker-for-developers/</guid><description>&lt;p&gt;Recently I gave a Meetup talk for the &lt;a href="http://www.meetup.com/Docker-Munich/" target="_blank" rel="noreferrer"&gt;Docker Munich&lt;/a&gt; Meetup Group which explained how Docker can help developers to improve integration tests and to ship applications.&lt;/p&gt;
&lt;p&gt;The &lt;a href="http://ro14nd.de/meetup-docker-developer-slides" target="_blank" rel="noreferrer"&gt;slides&lt;/a&gt; are online as well as the &lt;a href="https://github.com/rhuss/meetup-docker-demo" target="_blank" rel="noreferrer"&gt;demo project&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;During the demo I used &lt;a href="https://github.com/paradoxxxzero/butterfly" target="_blank" rel="noreferrer"&gt;Butterfly&lt;/a&gt; for an in-browser shell, which was quite cool, I guess ;-) (This is obviously not enabled in the online slides).&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m going to continue to celebrate my Docker-♡ with another two talks in autumn:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://onedaytalk.org/index.php/program?id=194" target="_blank" rel="noreferrer"&gt;Boosting your developer toolbox with Docker&lt;/a&gt; at JBoss One Day Talk, September, 29. in Germering (Munich, Germany)&lt;/li&gt;
&lt;li&gt;&lt;a href="http://jax.de/wjax2014/sessions/docker-fuer-java-entwickler" target="_blank" rel="noreferrer"&gt;Docker für Java Entwickler&lt;/a&gt; (in german) at W-JAX 14, November, 3. - 7. in Munich&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And there is a slight chance (since the CFP has not yet been declined ;-) to talk at &lt;a href="http://www.devoxx.be/" target="_blank" rel="noreferrer"&gt;Devoxx&lt;/a&gt; about Docker. &lt;a href="http://2014.javazone.no/" target="_blank" rel="noreferrer"&gt;JavaZone&lt;/a&gt; unfortunately declined my CFP, I guess there are already too many riding the docker horse (which is a good thing).&lt;/p&gt;
&lt;p&gt;Nevertheless I will attend both conferences with talks about &lt;a href="http://www.jolokia.org" target="_blank" rel="noreferrer"&gt;Jolokia&lt;/a&gt;, and I&amp;rsquo;m really looking forward to it.&lt;/p&gt;
&lt;p&gt;&amp;lsquo;guess it will become a hot autumn (hotter than this german 2014 summer for sure) &amp;hellip;.&lt;/p&gt;</description></item><item><title>Removing attachments with JavaMail</title><link>https://ro14nd.de/removing-attachments-with-javamail/</link><pubDate>Mon, 29 Mar 2010 00:00:00 +0000</pubDate><guid>https://ro14nd.de/removing-attachments-with-javamail/</guid><description>&lt;p&gt;If you have ever sent or received mail messages via Java, chances are high that you have used JavaMail for this task.
Most of the time JavaMail does an excellent job and a lot of use cases are described in the JavaMail FAQ.
But there are still some additional quirks you should be aware of when doing advanced mail operations like adding or removing attachments (or “Parts”) from existing mails retreived from some IMAP or POP3 store.
This post gives a showcase for how to remove an attachment from a mail at an arbitrary level which has been obtained from an IMAP store.&lt;/p&gt;
&lt;p&gt;It points to the pitfalls which are waiting and shows some possible solutions.
The principles laid out here are important for adding new attachments to a mail as well, but that’s yet another story.&lt;/p&gt;

&lt;h3 class="relative group"&gt;JavaMail objects
 &lt;div id="javamail-objects" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#javamail-objects" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;Before we start manipulating mail messages it is important to understand how these are represented in the JavaMail world.&lt;/p&gt;
&lt;p&gt;The starting point is the &lt;code&gt;Message&lt;/code&gt;. It has a content and a content type. The content can be any Java object representing the mail content, like a plain text (&lt;code&gt;String&lt;/code&gt;) or raw image data. But it can also be a &lt;code&gt;Multipart&lt;/code&gt; object: this is the case when a message’s content consists of more than a single item. A &lt;code&gt;Multipart&lt;/code&gt; object is a container which holds one ore more &lt;code&gt;BodyPart&lt;/code&gt; objects. These &lt;code&gt;BodyParts&lt;/code&gt;, like a &lt;code&gt;Message&lt;/code&gt;, have a content and a content type (in fact, both &lt;code&gt;Message&lt;/code&gt; and &lt;code&gt;BodyPart&lt;/code&gt; implement the same interface &lt;code&gt;Part&lt;/code&gt; which carries these properties).&lt;/p&gt;
&lt;p&gt;Beside plain content, A &lt;code&gt;BodyPart&lt;/code&gt; can contain another &lt;code&gt;Multipart&lt;/code&gt; or even another &lt;code&gt;Message&lt;/code&gt;, a so called &lt;em&gt;nested message&lt;/em&gt; (e.g. a message forwarded as attachment) with content type &lt;code&gt;message/rfc822&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;As you can see, the structure of a &lt;code&gt;Message&lt;/code&gt; can be rather heterogenous, a tree with nodes of different types. The following picture illustrates the tree structure for a sample message.&lt;/p&gt;
&lt;img src="https://ro14nd.de/images/removing-attachments-with-javamail/javamail-message.png" style="margin: auto;"/&gt;
&lt;p&gt;This object tree can be navigated in both directions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;getContent()&lt;/em&gt; on &lt;code&gt;Part&lt;/code&gt;s like &lt;code&gt;Message&lt;/code&gt; or &lt;code&gt;BodyPart&lt;/code&gt; to get to the child of this node. The return type is a &lt;code&gt;java.lang.Object&lt;/code&gt; and in case of a plain &lt;code&gt;BodyPart&lt;/code&gt; can be quite huge. Before calling &lt;code&gt;Part.getContent()&lt;/code&gt; be sure to check whether it contains a container by checking for its content type via &lt;code&gt;Part.isMimeType(&amp;quot;multipart/*&amp;quot;)&lt;/code&gt; or &lt;code&gt;Part.isMimeType(&amp;quot;message/rfc822&amp;quot;)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;getParent()&lt;/em&gt; on &lt;code&gt;Multipart&lt;/code&gt; or &lt;code&gt;BodyPart&lt;/code&gt; returns the parent node, which is of type &lt;code&gt;BodyPart&lt;/code&gt;. Note that there is no way to get from a nested &lt;code&gt;Message&lt;/code&gt; to its parent &lt;code&gt;BodyPart&lt;/code&gt;. If you need to traverse the tree upwards with nested messages on the way, you first have to extract the path to this node from the top down. E.g. while identifying the part to remove you could store the parent &lt;code&gt;BodyPart&lt;/code&gt;s on a stack.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 class="relative group"&gt;First approach
 &lt;div id="first-approach" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#first-approach" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;Back to our use case of removing an attachment at an arbitrary level within a mail. First, a &lt;code&gt;Message&lt;/code&gt; from the IMAP Store needs to be obtained, e.g. by looking it up in an &lt;code&gt;IMAPFolder&lt;/code&gt; via its UID:&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Session session &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Session.&lt;span style="color:#a6e22e"&gt;getDefaultInstance&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; Properties());
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Store store &lt;span style="color:#f92672"&gt;=&lt;/span&gt; session.&lt;span style="color:#a6e22e"&gt;getStore&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;imap&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;store.&lt;span style="color:#a6e22e"&gt;connect&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;imap.example.com&amp;#34;&lt;/span&gt;,&lt;span style="color:#f92672"&gt;-&lt;/span&gt;1,&lt;span style="color:#e6db74"&gt;&amp;#34;user&amp;#34;&lt;/span&gt;,&lt;span style="color:#e6db74"&gt;&amp;#34;password&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;IMAPFolder folder &lt;span style="color:#f92672"&gt;=&lt;/span&gt; (IMAPFolder) store.&lt;span style="color:#a6e22e"&gt;getFolder&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;INBOX&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;IMAPMessage originalMessage &lt;span style="color:#f92672"&gt;=&lt;/span&gt; (IMAPMessage) folder.&lt;span style="color:#a6e22e"&gt;getMessageByUID&lt;/span&gt;(42L);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Next, the fetched message is copied over to a fresh &lt;code&gt;MimeMessage&lt;/code&gt; since the &lt;code&gt;IMAPMimeMessage&lt;/code&gt; obtained from the store is marked as read-only and can&amp;rsquo;t be modified:&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Message message &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; MimeMessage(originalMessage);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// Mark original message for a later expunge&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;originalMessage.&lt;span style="color:#a6e22e"&gt;setFlag&lt;/span&gt;(Flags.&lt;span style="color:#a6e22e"&gt;Flag&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;DELETED&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Now the part to be removed needs to be identified. The detailed code is not shown here, but it is straight forward: You need to traverse the cloned &lt;code&gt;Message&lt;/code&gt; top down to identify the &lt;code&gt;Part&lt;/code&gt;, e.g. by its part number (a positional index) or by its content id. Be careful, though, not to call &lt;code&gt;getContent()&lt;/code&gt; except for &lt;code&gt;BodyPart&lt;/code&gt;s of type &lt;code&gt;multipart/*&lt;/code&gt; or &lt;code&gt;message/rfc822&lt;/code&gt;, since this would trigger a lazy fetch of the part&amp;rsquo;s content into memory. Probably not something you want to do while looking up a part. I think, I already said this. ;-)&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;MimePart partToRemove &lt;span style="color:#f92672"&gt;=&lt;/span&gt; partExtractor.&lt;span style="color:#a6e22e"&gt;getPartByPartNr&lt;/span&gt;(message,&lt;span style="color:#e6db74"&gt;&amp;#34;2.1&amp;#34;&lt;/span&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;It&amp;rsquo;s time to remove the body part from its parent in the hierarchy and store the changed message back into the store. You can mark the original message as &lt;code&gt;DELETED&lt;/code&gt; and expunge it on the folder. If you have the &lt;em&gt;UIDEXTENSION&lt;/em&gt; available on your IMAP store, you can selectively delete this single message, otherwise your only choice is to remove all messages marked as deleted at once (&amp;ldquo;Empty Trash&amp;rdquo;).&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Multipart parent &lt;span style="color:#f92672"&gt;=&lt;/span&gt; partToRemove.&lt;span style="color:#a6e22e"&gt;getParent&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;parent.&lt;span style="color:#a6e22e"&gt;removeBodyPart&lt;/span&gt;(partToRemove);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// Update headers and append new message to folder&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;message.&lt;span style="color:#a6e22e"&gt;saveChanges&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;folder.&lt;span style="color:#a6e22e"&gt;appendMessages&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; Message&lt;span style="color:#f92672"&gt;[]&lt;/span&gt; { message });
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// Mark as deleted and expunge&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;originalMessage.&lt;span style="color:#a6e22e"&gt;setFlag&lt;/span&gt;(Flags.&lt;span style="color:#a6e22e"&gt;Flag&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;DELETED&lt;/span&gt;, &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;folder.&lt;span style="color:#a6e22e"&gt;expunge&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; Message&lt;span style="color:#f92672"&gt;[]&lt;/span&gt;{ originalMessage });&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;We are done now.&lt;/p&gt;

&lt;h3 class="relative group"&gt;But wait, that&amp;rsquo;s not good enough &amp;hellip;
 &lt;div id="but-wait-thats-not-good-enough-" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#but-wait-thats-not-good-enough-" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;If you try the code above, you will probably be a bit surprised. If you fetch back the newly saved message from the folder, you will find that the attachment has &lt;strong&gt;not&lt;/strong&gt; been removed at all.&lt;/p&gt;
&lt;p&gt;Dragons are waiting here.&lt;/p&gt;
&lt;p&gt;The problem is that a JavaMail Part does heavy internal caching: it keeps a so called &lt;em&gt;content stream&lt;/em&gt; until a new &lt;em&gt;content&lt;/em&gt; is set for it.
So even if you modify the hierarchy of objects as described above, the original content is kept until you update the content of the parents yourself and the cache is thrown away.
Our part has not been removed because the cached content stream has not yet been invalidated. The solution is to get rid of the cached content stream (aka &amp;lsquo;refresh the message&amp;rsquo;).
You could set the content directly via &lt;code&gt;Part.setContent(oldPart.getContent(),oldPart.getContentType())&lt;/code&gt;, but this is dangerous in so far as it will load the part content into memory. (Did I already mention this?)
That&amp;rsquo;s really not something you are keen on if you want to remove this Britney Spears Video to save some IMAP space.
The alternative is to work on the wrapped &lt;code&gt;DataHandler&lt;/code&gt; only. A &lt;code&gt;DataHandler&lt;/code&gt; (defined in &lt;a href="http://java.sun.com/javase/technologies/desktop/javabeans/glasgow/javadocs/javax/activation/package-summary.html" target="_blank" rel="noreferrer"&gt;Java Activation&lt;/a&gt;) is not much more than a &lt;em&gt;reference&lt;/em&gt; to the content stream. Setting the &lt;code&gt;DataHandler&lt;/code&gt; on a &lt;code&gt;Part&lt;/code&gt; via &lt;code&gt;Part.setDataHandler()&lt;/code&gt; also causes it to invalidate its cached content, so a later &lt;code&gt;Part.writeTo()&lt;/code&gt; will stream out the new content.
Unfortunately, this has to be done on every parent up to the root. A brute force solution is to start from the top and refresh every content with&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// Recursively go through and save all changes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (message.&lt;span style="color:#a6e22e"&gt;isMimeType&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;multipart/*&amp;#34;&lt;/span&gt;)) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; refreshRecursively((Multipart) message.&lt;span style="color:#a6e22e"&gt;getContent&lt;/span&gt;());
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Multipart part &lt;span style="color:#f92672"&gt;=&lt;/span&gt; (Multipart) message.&lt;span style="color:#a6e22e"&gt;getContent&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;message.&lt;span style="color:#a6e22e"&gt;setContent&lt;/span&gt;(part);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;message.&lt;span style="color:#a6e22e"&gt;saveChanges&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;refreshRecursively&lt;/span&gt;(Multipart pPart)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;throws&lt;/span&gt; MessagingException, IOException {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;for&lt;/span&gt; (&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; i&lt;span style="color:#f92672"&gt;=&lt;/span&gt;0;i&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;pPart.&lt;span style="color:#a6e22e"&gt;getCount&lt;/span&gt;();i&lt;span style="color:#f92672"&gt;++&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; MimeBodyPart body &lt;span style="color:#f92672"&gt;=&lt;/span&gt; (MimeBodyPart) pPart.&lt;span style="color:#a6e22e"&gt;getBodyPart&lt;/span&gt;(i);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (body.&lt;span style="color:#a6e22e"&gt;isMimeType&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;message/rfc822&amp;#34;&lt;/span&gt;)) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Refresh a nested message&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Message nestedMsg &lt;span style="color:#f92672"&gt;=&lt;/span&gt; (Message) body.&lt;span style="color:#a6e22e"&gt;getContent&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (nestedMsg.&lt;span style="color:#a6e22e"&gt;isMimeType&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;multipart/*&amp;#34;&lt;/span&gt;)) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Multipart mPart &lt;span style="color:#f92672"&gt;=&lt;/span&gt; (Multipart) body.&lt;span style="color:#a6e22e"&gt;getContent&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; refreshRecursively(mPart);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; nestedMsg.&lt;span style="color:#a6e22e"&gt;setContent&lt;/span&gt;(mPart);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; nestedMsg.&lt;span style="color:#a6e22e"&gt;saveChanges&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; } &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (body.&lt;span style="color:#a6e22e"&gt;isMimeType&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#34;multipart/*&amp;#34;&lt;/span&gt;)) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Multipart mPart &lt;span style="color:#f92672"&gt;=&lt;/span&gt; (Multipart) body.&lt;span style="color:#a6e22e"&gt;getContent&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; refreshRecursively(mPart);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; body.&lt;span style="color:#a6e22e"&gt;setDataHandler&lt;/span&gt;(body.&lt;span style="color:#a6e22e"&gt;getDataHandler&lt;/span&gt;());
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;However, we can be smarter here: Since we already identified the part to remove, we can make our way upwards to the root message via the &lt;code&gt;getParent()&lt;/code&gt; method on &lt;code&gt;Multipart&lt;/code&gt; and &lt;code&gt;BodyPart&lt;/code&gt; (which, by the way are not connected via any interface or inheritance relationship).&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;BodyPart bodyParent &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Multipart multipart &lt;span style="color:#f92672"&gt;=&lt;/span&gt; parent;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;do&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;if&lt;/span&gt; (multipart.&lt;span style="color:#a6e22e"&gt;getParent&lt;/span&gt;() &lt;span style="color:#66d9ef"&gt;instanceof&lt;/span&gt; BodyPart) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; bodyParent &lt;span style="color:#f92672"&gt;=&lt;/span&gt; (BodyPart) multipart.&lt;span style="color:#a6e22e"&gt;getParent&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; bodyParent.&lt;span style="color:#a6e22e"&gt;setDataHandler&lt;/span&gt;(bodyParent.&lt;span style="color:#a6e22e"&gt;getDataHandler&lt;/span&gt;());
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; multipart &lt;span style="color:#f92672"&gt;=&lt;/span&gt; bodyParent.&lt;span style="color:#a6e22e"&gt;getParent&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; } &lt;span style="color:#66d9ef"&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// It&amp;#39;s a Message, probably the toplevel message&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// but could be a nested message, too (in which&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// case we have to stop here, too)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; bodyParent &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;} &lt;span style="color:#66d9ef"&gt;while&lt;/span&gt; (bodyParent &lt;span style="color:#f92672"&gt;!=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;null&lt;/span&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Finally you need to update the uppermost message headers, too with a&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;MimeMessage.&lt;span style="color:#a6e22e"&gt;saveChanges&lt;/span&gt;()&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;As you might have noticed, this works as long as there is no nested message in the chain of &lt;code&gt;BodyPart&lt;/code&gt;s up to the root.
Since a &lt;code&gt;Message&lt;/code&gt; doesn&amp;rsquo;t have any parent, we need some other means to get the &lt;code&gt;BodyPart&lt;/code&gt; which is the parent of an enclosed &lt;code&gt;Message&lt;/code&gt;. One way is to keep track of the chain of parent &lt;code&gt;BodyPart&lt;/code&gt;s when identifying the part to remove e.g. by extending the part extractor to support a stack of parent &lt;code&gt;BodyParts&lt;/code&gt; which will be in:&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Stack&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;MimeBodyPart&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt; parentBodys &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; Stack&lt;span style="color:#f92672"&gt;&amp;lt;&lt;/span&gt;MimeBodyPart&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;MimePart partToRemove &lt;span style="color:#f92672"&gt;=&lt;/span&gt; partExtractor.&lt;span style="color:#a6e22e"&gt;getPartByPartNr&lt;/span&gt;(message,&lt;span style="color:#e6db74"&gt;&amp;#34;2.1&amp;#34;&lt;/span&gt;,parentBodys);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ....&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;This example could be extended to remove multipart containers on the fly, if only one part is left after removal and replace the multipart with its then last child or remove an empty multipart altogether when its last child has been removed.&lt;/p&gt;

&lt;h3 class="relative group"&gt;Summary
 &lt;div id="summary" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#summary" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;Hopefully, I could sketch out that there are several points to take care of when manipulating existing JavaMail &lt;code&gt;Messages&lt;/code&gt; (it&amp;rsquo;s not that difficult if you build up one from scratch). The code shown above is only a starting point, but it hopefully saves you some time when you start wondering why on earth your nicely trimmed message isn&amp;rsquo;t stored correctly on the IMAP store.&lt;/p&gt;</description></item></channel></rss>