June 01, 2024
How to collect a Java Stream into a primitive Collection
by Donald Raab at June 01, 2024 06:13 PM
Discover a primitive collection bridge for Java Stream to avoid boxing.
Take the boxing gloves off
Boxed collection types in Java are types like Set<Integer> or List<Double>, where the primitive values like int and double in a collection have to be stored in a boxed wrapper like Integer and Double. Boxed wrappers and collection types in Java quietly eat up memory, waste time and take energy. The cost of a single boxed collection is usually insignificant. Unfortunately, boxed collections quietly pollute millions of Java heaps, possibly helping melt the ice out from under one or two unsuspecting polar bears.
I’ve blogged previously why I believe boxing in Java is evil, and some options we have as Java developers to remove the memory and performance inefficiencies from our applications and libraries. Please read the following blog if you want to understand why I think boxing is evil.
The missing Java data structures no one ever told you about — Part 3
So how can we bridge the wonderful world of Java Stream and the efficient world of primitive collections in Java ?
Let’s take our boxing gloves off and take a look at some solutions.
Java primitive Streams
Java provides Stream support for three primitive types. There are IntStream, LongStream, and DoubleStream types. We can transform from an Object Stream to one of these primitive Stream types using mapToInt, mapToLong, mapToDouble. If we want to transform a primitive Stream into a Collection we have limited options.
The default and most used option we are left with is to collect primitive Streams back into boxed collections like List<Integer>. This is exactly what we are looking to avoid.
Another option is to convert a primitive Stream into a primitive array. Unfortunately, arrays in Java have no useful behavior. They can tell us their length and give us mutable access to their elements so we can loop over them or change them. We can rewrap int[], long[], and double[] arrays into primitive Streams by using the overloaded Arrays.stream() method.
Both of these solutions also only work for int, long, and double. What do we do for boolean, byte, char, short, float? Are there solutions to mapping a Java Stream into a primitive Collection type that will support all eight Java primitives?
Yes, there are.
Call collect!
For those that may not have experienced the joy of calling someone collect... In the good ol’ days when public pay phones were the only way of calling someone if you needed something, we used to make collect calls. This was preferable to carrying around a lot of quarters, which were much better spent playing arcade machines. Calling collect meant asking an operator to bill the call to the person who would pick up the phone on the receiving end. That person would then have to accept the charges and the call would be added to their phone bill. I’m really not sure how we learned to give up this amazing convenience and saddle ourselves with cell phones instead.
Java developers have had a decade to work with Java Stream, and most will have encountered the inability to use a Collector with a primitive Stream. There are no primitive Collection types in Java, so there has been no need for primitive Collection Collectors.
Why don't primitive Stream have collect(Collector)?
If we want to map from a Java Stream and collect a primitive Collection, we have to accept a dependency on Eclipse Collections or another primitive collection library which will give us access to primitive Collections for all eight Java primitive types. Before we add this dependency, let’s see what we can get.
Option 1: Call the Three Musketeer collect
There is a Three Musketeer version of collect available on IntStream, LongStream, DoubleStream. The names of the Three Musketeers in the primitive collect method are:
- Supplier
- Obj(Int/Long/Double)Consumer
- BiConsumer
These three Functional Interfaces are stand-in actors for the missing collect method on primitive Streams that would take a primitive Collector. The Three Musketeer version of collect can be used to create primitive collections in Eclipse Collections as we can see in the following examples.
IntStream collect to IntList
@Test
public void intStreamToIntList()
{
IntStream intStream =
IntStream.of(1, 2, 3, 4, 5);
// Three Musketeer collect
IntList ints =
intStream.collect(
IntLists.mutable::empty, // Supplier
MutableIntList::add, // ObjIntConsumer
MutableIntList::addAll); // BiConsumer
IntList expected =
IntLists.mutable.of(1, 2, 3, 4, 5);
Assertions.assertEquals(expected, ints);
}
LongStream collect to LongSet
@Test
public void longStreamToLongSet()
{
LongStream longStream =
LongStream.rangeClosed(1, 5);
// Three Musketeer collect
LongSet longs =
longStream.collect(
LongSets.mutable::empty, // Supplier
MutableLongSet::add, // ObjIntConsumer
MutableLongSet::addAll); // BiConsumer;
LongSet expected =
LongSets.mutable.of(1L, 2L, 3L, 4L, 5L);
Assertions.assertEquals(expected, longs);
}
This approach works with DoubleStream as well, and there are primitive Lists, Sets, Bags in Eclipse Collections that can work with the Three Musketeer collect.
But how can we collect the other five primitive types from a Java Stream?
Option 2: Use a primitive Collector with an Object Stream
Wait! There are no primitive collection Collectors in Java!
Correct. There are no primitive collection Collectors in Java, because there are no primitive collections in Java. There are however primitive Collector instances available in Eclipse Collections. There is a utility class named Collectors2 which can help us build a bridge between Java Stream and primitive collections. We will see how we can use Collectors2 to convert from an Object Stream to any primitive collection type (Set, List, Bag) for any of the eight primitive Java types (boolean, byte, char, short, int, float, long, double)
Let’s start with a Stream of some Object type and see how we can convert that Stream into various primitive collections for all eight primitive types.
Stream<String> collect to BooleanBag
This example converts a Stream of String into a BooleanBag and then counts the occurrences of true and false.
@Test
public void streamToBooleanBag()
{
Stream<String> stream =
Stream.of("true", "false", "true", "false", "true");
BooleanBag booleans = stream.collect(
Collectors2.collectBoolean(
Boolean::parseBoolean,
BooleanBags.mutable::empty));
Assertions.assertEquals(3, booleans.occurrencesOf(true));
Assertions.assertEquals(2, booleans.occurrencesOf(false));
}
Stream<String> collect to ByteList
This example converts a Stream of String into a ByteList.
@Test
public void streamToByteList()
{
Stream<String> stream = Stream.of("1", "2", "3", "4", "5");
ByteList bytes = stream.collect(
Collectors2.collectByte(
Byte::parseByte,
ByteLists.mutable::empty));
ByteList expected = ByteLists.mutable.with(
(byte) 1,
(byte) 2,
(byte) 3,
(byte) 4,
(byte) 5);
Assertions.assertEquals(expected, bytes);
}
Stream<Character> collect to CharSet
This example converts a Stream of Character instances to a CharSet.
@Test
public void streamToCharSet()
{
Stream<Character> stream =
Stream.of('a', 'b', 'c', 'd', 'e');
CharSet characters = stream.collect(
Collectors2.collectChar(
Character::charValue,
CharSets.mutable::empty));
CharSet expected =
CharSets.mutable.with('a', 'b', 'c', 'd', 'e');
Assertions.assertEquals(expected, characters);
}
Stream<Sh> collect to ShortBag
I created a Java record for this example named Sh… Sh was shorter than Short. Sh holds onto a short, which is cast in the constructor from int. Like byte, there is no short short literal in Java, so we have to cast an int literal to a short. The Sh record allowed me to cast in one place.
@Test
public void streamToShortBag()
{
record Sh(short value)
{
public Sh(int intValue)
{
this((short) intValue);
}
};
Stream<Sh> stream =
Stream.of(new Sh(1), new Sh(2), new Sh(3), new Sh(4), new Sh(5));
ShortBag shorts = stream.collect(
Collectors2.collectShort(
Sh::value,
ShortBags.mutable::empty));
ShortBag expected =
ShortBags.mutable.with(
(short) 1,
(short) 2,
(short) 3,
(short) 4,
(short) 5);
Assertions.assertEquals(expected, shorts);
}
Stream<BigInteger> collect to IntList
I didn’t know there were four singleton values for BigInteger until I wrote this example test. Now we all know.
@Test
public void streamToIntList()
{
Stream<BigInteger> stream =
Stream.of(
BigInteger.ZERO,
BigInteger.ONE,
BigInteger.TWO,
BigInteger.TEN);
IntList ints = stream.collect(
Collectors2.collectInt(
BigInteger::intValueExact,
IntLists.mutable::empty));
IntList expected =
IntLists.mutable.with(0, 1, 2, 10);
Assertions.assertEquals(expected, ints);
}
Stream<BigDecimal> collect to FloatSet
This example converts from a Stream of BigDecimal to a FloatSet.
@Test
public void streamToFloatSet()
{
Stream<BigDecimal> stream =
Stream.of(
BigDecimal.ZERO,
BigDecimal.ONE,
BigDecimal.TWO,
BigDecimal.TEN);
FloatSet floats = stream.collect(
Collectors2.collectFloat(
BigDecimal::floatValue,
FloatSets.mutable::empty));
FloatSet expected =
FloatSets.mutable.with(0.0f, 1.0f, 2.0f, 10.0f);
Assertions.assertEquals(expected, floats);
}
Stream<LocalDate> collect to LongBag
This example converts from a Stream of LocalDate to a LongBag containing the LocalDate instances converted to their epochDay.
@Test
public void streamToLongBag()
{
LocalDate now = LocalDate.now();
Stream<LocalDate> stream =
Stream.of(
now,
now.plusDays(1L),
now.plusDays(2L),
now.plusDays(3L));
LongBag longs = stream.collect(
Collectors2.collectLong(
LocalDate::toEpochDay,
LongBags.mutable::empty));
LongBag expected =
LongBags.mutable.with(19872L, 19873L, 19874L, 19875L);
Assertions.assertEquals(expected, longs);
}
Stream<BigDecimal> collect to DoubleList
This example converts from a Stream of BigDecimal to a DoubleList.
@Test
public void streamToDoubleList()
{
Stream<BigDecimal> stream =
Stream.of(
BigDecimal.ZERO,
BigDecimal.ONE,
BigDecimal.TWO,
BigDecimal.TEN);
DoubleList doubles = stream.collect(
Collectors2.collectDouble(
BigDecimal::doubleValue,
DoubleLists.mutable::empty));
DoubleList expected =
DoubleLists.mutable.with(0.0d, 1.0d, 2.0d, 10.0d);
Assertions.assertEquals(expected, doubles);
}
Efficiency is still our problem
I love Java, and can’t wait for Project Valhalla to fully land in future versions of the language. I waited ten years for concise lambda expressions, and have now been waiting for ten years for Project Valhalla. The problem for me and the applications I have worked on in Financial Services over the past 20 years is that I didn’t have time to wait for the Java language and standard library to evolve to solve the problems I was faced with. Much of the work me and my colleagues did was driven by memory and some by performance pressure. I won’t claim the work we did was part of some greater philanthropy to save the planet by getting rid of all instances of HashSet<Integer>. I do occasionally dream about getting rid of all instances of HashSet<Integer> in the world though. :)
The good news is that we don’t have to wait for Valhalla if we have a need for primitive collections in Java today, or just want to take up a more efficient coding style to do our part to reduce our global computing footprint. There are solutions available to help us write more efficient Java code when we want to. Some of these solutions have been in development for 20 years. There is a cost to learning new types, methods and adding a dependency on a third-party library. If there’s no benefit, then there’s no point in incurring the cost of the dependency. But we should think about it every time we type new HashSet<Integer>. When we type or see this code in our applications, I want us to think about the polar bears.
When Valhalla arrives, I hope all of us will learn about it and take the time to leverage it in our applications so we can take advantages of new efficiencies and collectively reduce our footprint and increase our application performance. Efficiency is our problem. Whether we adopt solutions available today or wait for Project Valhalla to write more efficient Collections code, the problem is ours. Perhaps Valhalla will introduce some efficiencies that will magically deliver memory and performance savings without us having to do any work. That will of course be very welcome!
Thank you for reading, and I hope you learned something new and useful!
I am the creator of and committer for the Eclipse Collections OSS project, which is managed at the Eclipse Foundation. Eclipse Collections is open for contributions.
May 31, 2024
Announcing the Deprecation of the Eclipse User Storage Service (USS) API and SDK
May 31, 2024 02:54 PM
Today, we are announcing the deprecation of the Eclipse User Storage Service SDK (the Eclipse project) and the Eclipse User Storage Service API (hosted and maintained by the Eclipse Foundation).
The Eclipse User Storage Service (USS) API was created in 2015 to enable Eclipse projects to store and retrieve user data and preferences from our servers. Complementing this is the Eclipse User Storage Service SDK which offers a user-friendly Java library tailored for Eclipse RCP-based applications to simplify the integration with Eclipse USS API by managing the authentication and login processes.
Despite their past utility, the usage of this service has been steadily declining, and the costs associated with maintaining it are increasing.
Our current plan is to remove the Eclipse USS SDK from SimRel before the release of Eclipse IDE 2025-03 and to shut down the API service by 2 July 2025.
We appreciate your understanding and cooperation as we navigate these changes. If you have any questions or require further assistance, please don’t hesitate to reach out via our helpdesk issue #4696.
References
May 28, 2024
Join the Conversation: The 2024 IoT & Embedded Developer Survey is Now Open!
by Jacob Harris at May 28, 2024 05:36 PM
Since 2015, we've been at the forefront of exploring the IoT development landscape, uncovering invaluable insights into the challenges faced by developers, the usage of programming languages, operating systems, architectures, and the industries that benefit from IoT innovation.
Join the Conversation: The 2024 IoT & Embedded Developer Survey is Now Open!
by Clark Roundy at May 28, 2024 04:41 PM
Exciting news - the 2024 IoT & Embedded Developer Survey is now open! This comprehensive survey provides developers and industry professionals with a unique opportunity to shape the future of IoT and embedded systems by sharing their insights and experiences.
Since 2015, we've been at the forefront of exploring the IoT development landscape, uncovering invaluable insights into the challenges faced by developers, the usage of programming languages, operating systems, architectures, and the industries that benefit from IoT innovation.
Last year's survey highlighted the prominence of AI in edge computing workloads, identified industrial automation and agriculture as leading IoT & edge market segments, and noted an overall increase in development activities across all sectors. Your input is crucial in assessing how the landscape has evolved since then.
This year, our focus extends to the embedded systems industry, looking into whether the factors impacting IoT development are also influencing embedded developers. Key areas of focus include:
- Security and Deployment Concerns: What are the challenges and priorities of today's developers amidst growing cybersecurity concerns?
- Open Source Engagement: How are developers engaging with open source projects to drive innovation within IoT and embedded applications?
- Developer Preferences: What features and functionality do developers prioritise when it comes to application development frameworks?
- Influence of Safety Certifications: How do safety certifications impact adoption of operating systems or other software components in embedded applications?
- Hardware Platforms: Which architectures are favoured by device designers?
- Operating Systems: What are the dominant real-time operating systems for embedded devices? What are the preferred options for edge nodes?
Powered by Participation
Join us in shaping the future of IoT and embedded systems. Your input is essential in highlighting technologies, tools, and practices that drive innovation and identifying areas needing support. By participating, you not only contribute to an invaluable industry resource, but also gain insights that can help guide your own strategies and development efforts.
You can also help by sharing the survey within your network. The more voices we hear, the clearer the picture we can paint of the IoT and embedded systems landscape.
Take the survey now – it only takes 10 minutes, and your responses are completely confidential. Let's shape the future of IoT and embedded systems together!
Eclipse Foundation and the Adoptium Working Group Announce Latest Eclipse Temurin Open Source Java SE Release
by Jacob Harris at May 28, 2024 11:00 AM
BRUSSELS – 28 May 2024 – The Eclipse Foundation, a leading open source foundation, in collaboration with the Adoptium Working Group, has announced the latest release of Eclipse Temurin’s Java SE runtime. This landmark release supports 54 version/platform combinations and five major OpenJDK versions, underscoring Adoptium's commitment to a diverse and comprehensive range of supported builds, spanning Linux, Mac, Windows, and various architectures, including x64, ARM, and RISC-V.
“The incredible growth of Eclipse Temurin reflects a strong demand among developers for secure, high-quality, and community-driven open source Java runtimes,” said Thabang Mashologu, vice president, Community and Outreach for the Eclipse Foundation. “The Adoptium Working Group’s efforts have been instrumental in delivering free-to-use, enterprise-ready runtime binaries and expanding the potential use cases for open source Java. Eclipse Temurin is one of the first open source Java distributions to support RISC-V, introducing new opportunities for Java in Industrial IoT and beyond.”
In conjunction with this release, the Working Group has also shared several significant Eclipse Temurin updates and developments:
- Unprecedented Growth and Adoption: Eclipse Temurin is the fastest-growing open source Java SE runtime, currently exceeding 23 million downloads per month and more than 380 million downloads to date. A recent independent report (New Relic, State of the Java Ecosystem, April 2024) confirms Temurin momentum with 50% year-over-year growth and representing 18% of the Java market as the second most popular JDK vendor.
- Security Enhancements: Eclipse Temurin is building the world’s most secure OpenJDK distribution and pioneering software supply chain security practices. Nominated platform builds are independently verified, and include a comprehensive software bill of materials. The Working Group recently launched a case study that highlights this commitment.
- RISC-V Support: Eclipse Temurin now supports RISC-V microprocessors, broadening its applications to embedded technologies, IoT, machine learning, automotive software, and high-performance computing.
Eclipse Temurin, an open source Java SE distribution based on OpenJDK, is available for a wide range of platforms and Java SE versions. There are multiple commercial support options available for Temurin, ensuring Temurin adopters can receive enterprise-grade support coverage for their mission-critical Java workloads. Members of the Adoptium Working Group, including Azul Systems, IBM, Open Elements, and Red Hat, offer this support.
To learn more about Eclipse Temurin or the Adoptium Working Group, join us at the Open Community for Java event during Open Community Experience (OCX), a transformative open source developer conference set for 22-24 October 2024 in Mainz, Germany. The event will cover topics related to Jakarta EE, Adoptium, MicroProfile, and open source enterprise Java. For sponsorship and participation details, visit the OCX website. The Call for Proposals is now open, with an early bird deadline of 31 May 2024, for those interested in submitting a talk for consideration.
About the Adoptium Working Group
The Adoptium Working Group promotes and supports secure, high-quality, TCK-certified runtimes and associated technologies, backed by 84 dedicated contributors and 12 member companies, including Java ecosystem leaders and enterprise users. The Strategic Members of the Adoptium Working Group include Alibaba Cloud, Azul Systems, Google, Huawei, Microsoft, Red Hat, and Rivos. The Adoptium Marketplace extends this leadership role and gives even more organisations a means of distributing their binaries.
If your organisation is interested in participating in the Adoptium Working Group, you can view the Charter and Participation Agreement or email us at membership@eclipse.org. Companies can also participate as a sponsor; interested parties can view the Sponsorship Agreement. Both membership and sponsorship help assure the sustainability of the Adoptium Working Group and certified open source runtimes for the developer community.
About the Eclipse Foundation
The Eclipse Foundation provides our global community of individuals and organisations with a business-friendly environment for open source software collaboration and innovation. We host the Eclipse IDE, Adoptium, Software Defined Vehicle, Jakarta EE, and over 415 open source projects, including runtimes, tools, specifications, and frameworks for cloud and edge applications, IoT, AI, automotive, systems engineering, open processor designs, and many others. Headquartered in Brussels, Belgium, the Eclipse Foundation is an international non-profit association supported by over 360 members. Visit us at this year’s Open Community Experience (OCX) conference on 22-24 October 2024 in Mainz, Germany. To learn more, follow us on social media @EclipseFdn, LinkedIn, or visit eclipse.org.
Third-party trademarks mentioned are the property of their respective owners.
###
Media contacts:
Schwartz Public Relations for the Eclipse Foundation, AISBL (Germany)
Gloria Huppert/Julia Rauch
Sendlinger Straße 42A
80331 Munich
EclipseFoundation@schwartzpr.de
+49 (89) 211 871 -70/-43
Nichols Communications for the Eclipse Foundation, AISBL
Jay Nichols
+1 408-772-1551
514 Media Ltd for the Eclipse Foundation, AISBL (France, Italy, Spain)
Benoit Simoneau
M: +44 (0) 7891 920 370
![alt](https://newsroom.eclipse.org/sites/default/files/news/PR%20-%20adoptium%20temurin%20release.png)
May 27, 2024
Native Notebook support for Eclipse Theia
May 27, 2024 12:00 AM
May 21, 2024
Eclipse Cloud DevTools Contributor Award: Rob Moran and Jens Reinecke for their outstanding contributions to CDT Cloud
by John Kellerman at May 21, 2024 07:23 PM
The Eclipse Cloud Developer Tools (ECDT) community is happy to announce Rob Moran and Jens Reinecke from Arm as the recipients of the Contributor Award in the second quarter 2024 for their continuous, strategic, and highly valuable contributions to CDT Cloud. Their exceptional efforts, technical domain knowledge and leadership within the community continue to significantly advance our tools and our projects.
Rob and Jens have been instrumental in several key areas of CDT Cloud:
- Embedded Peripheral Inspector: Their initiative to add the Embedded Peripheral Inspector to CDT Cloud, along with their ongoing enhancements of this crucial component, have provided developers with an invaluable tool for inspecting and managing embedded peripherals, greatly simplifying debugging and development processes.
- Memory Inspector: Rob and Jens have consistently contributed to the Memory Inspector, ensuring it remains an essential, flexible and user-friendly tool for developers needing to inspect and manage memory during development.
- Serial Monitor: They initiated the Serial Monitor, adding crucial functionality for developers working with serial communication in their projects.
- WebSocket Debug Adapter: Their initial contribution of the WebSocket Debug Adapter has enabled efficient debugging over WebSocket, expanding the versatility and applicability of our debugging tools.
Rob and Jens bring an exceptional understanding of embedded systems, which continues to be instrumental in creating high-quality, reliable tools that meet the needs of our community. Beyond their technical contributions, Rob and Jens have shown continuous leadership and active steering within the CDT Cloud community. Their guidance and commitment have been pivotal in driving the community forward, fostering collaboration, and ensuring the continuous improvement of our tools and projects.
We extend our warmest congratulations to Rob Moran and Jens Reinecke for this well-deserved recognition! Their work exemplifies the high standards and collaborative spirit that drive the Eclipse Cloud Developer Tools community forward.
This Eclipse Cloud DevTools contributor award is sponsored by EclipseSource, providing consulting and implementation services for web-based tools, Eclipse GLSP, Eclipse Theia, and VS Code, as well as for tailored AI Assistance in Tools and IDEs.
May 19, 2024
Map-Oriented Programming in Java
by Donald Raab at May 19, 2024 06:01 PM
Using MOP may be convenient sometimes, but it can also be messy.
To the Batpoles!
I created polls in Twitter(!X) and LinkedIn asking if developers use a Bag/Multiset type or if they just use Java Map. Unsurprisingly, java.util.Map is dominating both polls.
Donald Raab on Twitter: "Do you use Guava Multiset, Apache Collections Bag, or Eclipse Collections Bag types? Or do you just get by with trusty Java Map? / Twitter"
Do you use Guava Multiset, Apache Collections Bag, or Eclipse Collections Bag types? Or do you just get by with trusty Java Map?
(Apologies for anyone who hasn’t seen the 1960s TV version of Batman… the Batpoles were two poles hidden behind a sliding bookcase and Batman and Robin would use them to slide down to the Batcave.)
The question is not meant to determine whether Bag or Map is a better type. Both interfaces serve different purposes, and have different behaviors. A Map associates keys to values. A Bag is an unordered non-unique collection that makes it easy to track counts of things, and is usually backed by a Map to speed up lookups. A Map can be used to keep track of counts, the same as a hammer can be used to punch a hole through concrete instead of using a jackhammer. No one I know would argue that a hammer is a better tool to punch a hole through concrete, but if you don’t have a jackhammer on hand, you whack the heck out of that concrete with the hammer that you do have.
When your only tool is a Map, everything else is a key-value pair
Anyway, back to the poll and the ultimate question… There are three libraries named in the poll that provide a Bag/Multiset type in Java — Google Guava, Apache Commons Collections, and Eclipse Collections. Then there is Map from Java. The question is really are you willing to take a third-party dependency in your application to get a Bag/Multiset type, or are you happy to stick with Map-Oriented Programming (MOP)? Most developers these days try to limit their third-party dependencies for a variety of reasons (binary size, version conflict resolution, potential vulnerabilities, etc.). This leaves most developers in a position to just leverage the Map-Oriented Programming alternatives sometimes provided by the JDK, or alternatively build their own Bag/Multiset solution. Most developers I know, go with the Map-Oriented Programming solution.
The following quote is the essence of Map-Oriented Programming (MOP).
We need to get $h!t done now! We’ve got a Map and we’re not afraid to use it!
The problem with MOP is that while Map is super flexible with the data it can contain in the key and value slots is provides, it’s behavior stays the same. It’s just a Map. You can put things in, and get things out… including null or any other random type. Over the years, the Java Map interface has added new Map specific behavior that enhances the flexibility like being able to merge elements, compute them or get a default value if a key is absent. More specialized behavior, like counting or adding to/removing from a collection in one of the value slots, which is not part of the Map contract leaks out into your code, or into algorithms tacked on to Stream and Collector. You lose the ability to have types and structures that provide augmented behavior on top of the Map.
I’ve enjoyed the benefits of using both dynamic type systems and static type systems having worked professionally in both Smalltalk and Java. Data structures like Map sometimes give you the feeling of the benefits of a dynamic type system, without the benefits of the static type system. I like having a static type system for a lot of reasons, even though it sometimes slows me down when I am developing on my own. I’m not a fan of Map-Oriented Programming, but I will confess to having used it on occasion when it provided a short-term convenience where adding new types was a hassle. When I discover the need for a new type, I usually add it. This is sometimes the hard path, but it is usually the right path. There is a cost for every new type we add to our applications, but there are also the benefits of communication, clarity, encapsulation, reduction in code duplication, increased safety, and improved performance.
Shortcuts aren’t
There are three types the JDK is missing, that have been represented with Map as an alternative. Using Map is leveraging existing type flexibility to avoid cost, in this case for the framework developers. Any incurred cost is moved instead to the application developers that use Map as a return type. The following Map return types used in Collectors can never be changed. These Map return types were introduced on Collectors when Java 8 was released.
// Map<Boolean, List<T>> -> Pair<T, T>
Collectors.partitioningBy()
// Map<T, Long> -> Bag<T>
Collectors.groupingBy(Collectors.counting)
// Map<K, Collection<V>> -> Multimap<K, V>
Collectors.groupingBy()
Pair, Bag, and Multimap are just some of the types missing from the JDK. We can call Pair something more specific in the case of partitioningBy like Partition, but it’s still essentially a Pair of two things of the same type.
We don’t need a Pair type!
A well-reasoned decision was made to not add a generic Pair type or support for generic tuples in Java. Instead, the use of named types created via Java Records are recommended for Java developers since Java 16 was released. This is a reasoned decision, that I fully support, even if the open source framework I created (Eclipse Collections) has Pair and Triple types. I appreciate creating specialized types for things, and being able to do so with very little ceremony using Java Records is awesome.
Please fasten your seatbelts for what comes next.
We’ve got a Map!
Using a Map as a generic Pair type is arguably worse than adding a generic Pair type. How do you use a Map as a Pair? There is an example in the Stream and Collectors code in the JDK with partitioningBy.
Let’s look at the following example of partitioningBy, where we will one pass filter a Stream of Integer into separate List instances of evens and odds.
@Test
public void partitioningBy()
{
Map<Boolean, List<Integer>> map =
IntStream.rangeClosed(1, 10)
.boxed()
.collect(Collectors.partitioningBy(each -> each % 2 == 0));
List<Integer> evens = map.get(true);
List<Integer> odds = map.get(false);
List<Integer> ummm = map.get(null);
List<Integer> ohno = map.get(new Object());
Assertions.assertEquals(List.of(2, 4, 6, 8, 10), evens);
Assertions.assertEquals(List.of(1, 3, 5, 7, 9), odds);
Assertions.assertNull(ummm);
Assertions.assertNull(ohno);
ummm = map.getOrDefault(null, evens);
Assertions.assertEquals(List.of(2, 4, 6, 8, 10), ummm);
ohno = map.getOrDefault(new Object(), odds);
Assertions.assertEquals(List.of(1, 3, 5, 7, 9), ohno);
}
This code takes a Stream of Integer from 1 to 10 and filters the even values into one List and the odd values into another List using partitioningBy. The result is a Map<Boolean, List<Integer>>. The true values in the Map are the ones that filter inclusively. The false values in the Map are the ones that filter exclusively. The null values in the Map are the ones that… wait, why are there null values in the Map? Why is there a new Object() lookup in a Map<Boolean, List<Integer>>? What is happening here!?! Recall that Map existed before Java 5 when generics were added to Java, and the get method on Map is not generic and accepts any Object. Ahhhh… Map.
If you’ve never dug into the result of partitioningBy before, it returns an instance of type named Partition that is a an inner class in Collectors. I knew the partitioningBy method returned a Map<Boolean, List<Type>>, but wasn’t aware of the actual implementation until I looked today. The Partition type is immutable, but still behaves like a Map as I illustrate above. The get method on Map is not generic, so accepts ANY object of ANY type. The Partition class does not throw on non-boolean access via get, but instead returns null. Lookups with potentially any type will result in null. The method getOrDefault or any of the other read-only Map methods behave consistently with other Map types. Mutable methods like put throw exceptions.
What about using a primitive BooleanObjectMap?
For those wondering if I would propose using a primitive version of a BooleanObjectMap from Eclipse Collections to solve the generic get problem with Map… I wouldn’t, and I can’t. A BooleanObjectMap type doesn’t exist in Eclipse Collections. When we designed the primitive Map hierarchy, we made a conscious decision to remove ALL combinations of primitive maps with boolean as a key. There are no boolean to anything maps in Eclipse Collections.
Why?
Having a Map of boolean to anything had a design smell of using Map as a hammer. If you need two values, one for true and one for false, then use two variables to hold the values and put those values in a specific type. The variables in this new type can have intention revealing names (e.g. selected and rejected, in Eclipse Collections PartitionIterable) instead of less meaningful names like ifTrue and ifFalse, or Boolean values in a Map. If you want to pass these values around together in a single generic instance of something, because you can’t or don’t want to add a new type, then use a generic Pair. Buyer beware. You will get less meaningful names for your contained values with a Pair as well (one and two, or left and right).
What if we used an Enum for the key type instead of Boolean?
Another option using a Map to represent a pair of the same type would be to use an Enum for the key, where the names in the Enum have intention revealing names (eg. Filter.SELECTED, Filter.REJECTED). Then we could write map.get(Filter.SELECTED) instead of map.get(true).
Why not?
This solution requires a new type of Enum to be created to hold these key names. If we already have to add a new type, and it would just be better to define the specific type we need with the named variables and types. (e.g. Partition type with the selected and rejected variables). The better names in the Enum also wouldn’t solve the generic problems with the get method on Map. In fact, you could still write map.get(true) and it would return null.
Stop Hammer time!
I think it is better for the JDK to leverage its static typing benefits and return specific types instead of returning Map, whenever possible. I think returning the Partition type for partitioningBy would have made more sense to return instead of a Map. This would have meant exposing a new public type. The Partition type is private static. The new public type wouldn’t need to be a completely generic type like Pair. Eclipse Collections partition method on RichIterable returns a PartitionIterable type. There is a cost to adding/maintaining this type and all of its subtypes that is handled by the Eclipse Collections developers. This gives developers who use the library the safest most specific alternative at various levels in the type hierarchy.
@Test
public void partition()
{
PartitionMutableList<Integer> partition =
Interval.oneTo(10)
.partition(each -> each % 2 == 0);
MutableList<Integer> selected = partition.getSelected();
MutableList<Integer> rejected = partition.getRejected();
Assertions.assertEquals(List.of(2, 4, 6, 8, 10), selected);
Assertions.assertEquals(List.of(1, 3, 5, 7, 9), rejected);
}
There are two other places where Collectors returns Map as a type that would have been better off as more specific types. The problem is convenience and cost. It was more convenient in the Java 8 release to return a Map, instead of a Bag or Multimap , because it would have meant introducing Bag and Multimap types and implementations, which would have delayed the Java 8 release, potentially significantly. Having seen these types created in Eclipse Collections many years ago, I can confirm they are both expensive to build and to test. Unfortunately, we are stuck with the decision to go with convenience and return type of Map forever in Collectors.
I have blogged previously about Map vs. Bag and Map vs. Multimap. Read the blogs at the links below if you would like to understand more.
For some other examples and details of partition in Eclipse Collections, there is a blog for that below. The most interesting thing for some developers in this blog may be the PartitionIterable hierarchy that was implemented to support the covariant nature of the partition method.
Eclipse Collections by Example: Partitioning
Whither Map-Oriented Programming
Map is a hammer. It’s a very useful and convenient tool, but we fall back on Map as an all purpose tool and flexible return type too much. Java Records give us a new level of convenience with the benefit of static typing. Additional Collection types like Bag and Multimap augment the capabilities of Map with different specialized behaviors for developers to leverage.
In the data-oriented programming space, I prefer solutions like Dataframe libraries which are much more specific than row-based Collection of Map about their features and purpose. I think Java Record gives a nice low-ceremony alternative for creating Collection of Record types that can be statically type checked. This helps provide type safety, memory efficiency, and performance.
I hope to see additional Collection types incorporated in the JDK, instead of continuing to use Map as a convenient but messy alternative. I believe the JDK should have Partition, Bag, and Multimap types. Partition is already there as an implementation. Partition just needs to stop pretending to be a Map and made public or represented by a more specific and constrained interface. Unfortunately, since partitioningBy already returns a Map, this method will not likely ever be changed, but could be instead deprecated and replaced by an alternative with a better return type.
I hope this blog made you think about the cost/benefit of using Map as an all purpose return type. My recommendation — don’t! Use Map as a return type only when it is the absolute best option available for a method. If another type would be a better option as a return type, then create it or use it if it already exists.
Thank you for reading!
I am the creator of and committer for the Eclipse Collections OSS project, which is managed at the Eclipse Foundation. Eclipse Collections is open for contributions.
Map-Oriented Programming in Java was originally published in Level Up Coding on Medium, where people are continuing the conversation by highlighting and responding to this story.
May 16, 2024
Participate in the Open Source Global South Developer Survey
by Jacob Harris at May 16, 2024 07:49 PM
If you live in the Global South, take a few minutes to participate in our new survey. Your insights help strengthen our understanding of open source worldwide.
May 13, 2024
Java News Roundup: New JEPs, Payara Platform, Spring Boot 10th Anniversary Podcast
by Michael Redlich at May 13, 2024 02:30 AM
![](https://res.infoq.com/news/2024/05/java-news-roundup-may06-2024/en/headerimage/java-istock-image-01-1715542205342.jpg)
This week's Java roundup for May 6th, 2024, features news highlighting: the May edition of the Payara Platform; and new JEP candidates, namely: JEP 477, Implicitly Declared Classes and Instance Main Methods (Third Preview), JEP 480, Structured Concurrency (Third Preview), JEP 479, Remove the Windows 32-bit x86 Port, and JEP 478, Key Derivation API (Preview).
By Michael RedlichMay 08, 2024
Eclipse Theia 1.49 Release: News and Noteworthy
by Jonas, Maximilian & Philip at May 08, 2024 12:00 AM
We are happy to announce the Eclipse Theia 1.49 release! The release contains 53 merged pull requests. In this article we will highlight some selected improvements and provide an overview of the …
The post Eclipse Theia 1.49 Release: News and Noteworthy appeared first on EclipseSource.
May 02, 2024
Comparing Collections in Java
by Donald Raab at May 02, 2024 04:54 AM
Learn when to use List, Set, Bag or Map if you don’t have a Bag.
Test Infected and Happy!
I love writing executable code examples in unit tests. Using JUnit Assertions is so much more interesting and sometimes more challenging than just writing a main() method with some System.out.println() methods to experiment. Writing tests gives me confidence that my code works today, and confidence tomorrow that the code I wrote still works as written. If it doesn’t work, the test will fail and tell me.
Two of the most common JUnit 5 Assertions that I use are assertEquals and assertNotEquals. When these methods fail, they provide useful messages explaining what the difference is between the two objects being compared based on their toString result.
These two Assertions are very useful when it comes to comparing two Collections in Java. Developers who use the Java Collection Framework have three basic Collection types that they can use to compare for equality. These types are java.util.List, java.util.Set, and java.util.Map. In Eclipse Collections, there is a fourth type named Bag.
Comparing Collections for Equality
A Collection is equal to another Collection of the same type. So a List can be equal to a List, a Set can be equal to a Set, and a Bag can be equal to a Bag. SortedSet can be equal to another Set (which may be a SortedSet). SortedBag can be equal to a Bag (which may be a SortedBag). We may need to convert a Collection to the type we want to use for the equality test we are interested in.
Collection Equality Examples
For the test examples, I will use a simple Fruit enum with APPLE, BANANA, and CHERRY.
enum Fruit
{
APPLE, BANANA, CHERRY;
}
The following are some examples of testing equality for a List.
@Test
public void listEquality()
{
MutableList<Fruit> list =
Lists.mutable.of(Fruit.BANANA, Fruit.BANANA, Fruit.APPLE, Fruit.CHERRY);
// Equality of List is based on Type, Size, Contents, and Order
// List allows duplicates
// Order DOES impact the equality of a List
Assertions.assertEquals(
list,
List.of(Fruit.BANANA, Fruit.BANANA, Fruit.APPLE, Fruit.CHERRY));
Assertions.assertNotEquals(
list,
List.of(Fruit.APPLE, Fruit.BANANA, Fruit.CHERRY));
Assertions.assertNotEquals(
list,
List.of(Fruit.CHERRY, Fruit.BANANA, Fruit.BANANA, Fruit.APPLE));
}
The following are some examples of testing equality for a Set.
@Test
public void setEquality()
{
MutableSet<Fruit> set =
Sets.mutable.of(Fruit.BANANA, Fruit.APPLE, Fruit.CHERRY);
// Equality of Set is based on Type, Size and Contents.
// Set allows unique elements only.
// Order DOES NOT impact the equality of a Set
Assertions.assertEquals(
set,
Sets.mutable.of(Fruit.APPLE, Fruit.BANANA, Fruit.CHERRY));
Assertions.assertEquals(
set,
Sets.mutable.of(Fruit.CHERRY, Fruit.BANANA, Fruit.APPLE));
Assertions.assertNotEquals(
set,
Sets.mutable.of(Fruit.APPLE, Fruit.BANANA));
Assertions.assertNotEquals(
set,
Sets.mutable.of(Fruit.BANANA, Fruit.CHERRY));
}
The following are some examples of testing equality for a Bag.
@Test
public void bagEquality()
{
MutableBag<Fruit> bag =
Bags.mutable.of(Fruit.APPLE, Fruit.BANANA, Fruit.BANANA, Fruit.CHERRY);
// Equality of Bag is based on Type, Size and Contents
// Bag allows duplicates
// Order DOES NOT impact the equality of a Bag
Assertions.assertEquals(
bag,
Bags.mutable.of(Fruit.BANANA, Fruit.APPLE, Fruit.BANANA, Fruit.CHERRY));
Assertions.assertEquals(
bag,
Bags.mutable.of(Fruit.CHERRY, Fruit.BANANA, Fruit.APPLE, Fruit.BANANA));
Assertions.assertNotEquals(
bag,
Bags.mutable.of(Fruit.APPLE, Fruit.BANANA, Fruit.APPLE, Fruit.CHERRY));
Assertions.assertNotEquals(
bag,
Bags.mutable.of(Fruit.APPLE, Fruit.BANANA, Fruit.CHERRY));
}
Converting Collections to Test for Equality
Sometimes we will need to convert a Collection from one type to another in order to apply the equality comparison we are most interested in. The following table lists several types of equality tests we may want to perform on a Collection of items, with the best Collection type to use in those circumstances.
![](https://cdn-images-1.medium.com/max/1024/1*ioLqYq7sL_CoHHvF0V-IaA.png)
The Java Collection Framework does not have a Bag type, so a Map type would need to be used to simulate a Bag.
Converting to a sorted List for Equality Test
Using Eclipse Collections MutableList as a source type, we can convert the List to a sorted List using toSortedList. There is no SortedList type, so sorting doesn’t actually change the type, but toSortedList will create a sorted copy of the List, so the source List remains unchanged.
The following code copies a MutableList<Fruit> to a new MutableList<Fruit> and sorts it in natural order using toSortedList.
@Test
public void convertToSortedListForEquality()
{
MutableList<Fruit> list =
Lists.mutable.of(Fruit.BANANA, Fruit.BANANA, Fruit.APPLE, Fruit.CHERRY);
// Sorting the List we can more predictably compare the contents
List<Fruit> sortedList = list.toSortedList();
Assertions.assertEquals(
sortedList,
List.of(Fruit.APPLE, Fruit.BANANA, Fruit.BANANA, Fruit.CHERRY));
Assertions.assertNotEquals(
sortedList,
List.of(Fruit.CHERRY, Fruit.BANANA, Fruit.CHERRY, Fruit.APPLE));
}
Converting to a Set for Equality Test
Using Eclipse Collections MutableList as a source type, we can convert the List to a Set using toSet.
@Test
public void convertToSetForEquality()
{
MutableList<Fruit> list =
Lists.mutable.of(Fruit.BANANA, Fruit.BANANA, Fruit.APPLE, Fruit.CHERRY);
// Using a Set we can test unique contents without caring for order
Set<Fruit> set = list.toSet();
Assertions.assertEquals(
set,
Set.of(Fruit.CHERRY, Fruit.BANANA, Fruit.APPLE));
Assertions.assertEquals(
set,
Set.of(Fruit.APPLE, Fruit.BANANA, Fruit.CHERRY));
Assertions.assertNotEquals(
set,
Set.of(Fruit.APPLE, Fruit.BANANA));
}
Converting to a Bag for Equality Test
Using Eclipse Collections MutableList as a source type, we can convert the List to a Bag using toBag.
@Test
public void convertToBagForEquality()
{
MutableList<Fruit> list =
Lists.mutable.of(Fruit.BANANA, Fruit.BANANA, Fruit.APPLE, Fruit.CHERRY);
// Using a Bag we can test size and contents without caring about order
Bag<Fruit> bag = list.toBag();
Assertions.assertEquals(
bag,
Bags.mutable.of(Fruit.CHERRY, Fruit.BANANA, Fruit.BANANA, Fruit.APPLE));
Assertions.assertNotEquals(
bag,
Bags.mutable.of(Fruit.CHERRY, Fruit.BANANA, Fruit.CHERRY, Fruit.APPLE));
}
I often find Bag is the most useful Collection type to use for equality testing, unless I care explicitly about the order.
What if I don’t have a Bag?
My recommendation would be to download Eclipse Collections and get yourself a reusable Bag for your Fruit! ���
If you can’t afford a Bag type in your code base for some reason, you can convert the List to a Map as follows. It’s just a bit more verbose.
@Test
public void convertToMapForEquality()
{
List<Fruit> list =
List.of(Fruit.BANANA, Fruit.BANANA, Fruit.APPLE, Fruit.CHERRY);
// Converting to Map we can also test size and contents without order
Map<Fruit, Long> simulatedBag = list.stream()
.collect(Collectors.groupingBy(each -> each, Collectors.counting()));
Assertions.assertEquals(
simulatedBag,
Map.of(Fruit.BANANA, 2L, Fruit.CHERRY, 1L, Fruit.APPLE, 1L));
Assertions.assertNotEquals(
simulatedBag,
Map.of(Fruit.BANANA, 1L, Fruit.CHERRY, 2L, Fruit.APPLE, 1L));
}
Summary
Comparing two Collections using equals tests a bunch of things simultaneously. Using equals will test the type, the size, the contents, and sometimes the order of the contents, depending on the equals contract of a particular type. Knowing when to use equals with two instances of List, Set, Bag, or Map can help you write more concise and meaningful assertions. Using equals is better than just testing size, and less lines of code if you have to call contains multiple times. Sometimes it helps to convert a particular Collection to another type to test for equality, depending on what you are looking to test.
Thank you for reading, and I hope you find this blog useful!
I am the creator of and committer for the Eclipse Collections OSS project, which is managed at the Eclipse Foundation. Eclipse Collections is open for contributions.
May 01, 2024
Eclipse Cloud DevTools Digest - March and April, 2024
by John Kellerman at May 01, 2024 06:29 PM
Improved Performance in Theia IDE
Earlier, Matthew Khouzam and I wrote and article about the hard work that went into a Eclipse Theia IDE delivers a noticeable boost in performance over the “Theia Blueprints” releases 3 months ago. This is a look into recent work to instrument, measure, and ultimately improve the performance of Eclipse Theia IDE.
Artificial Intelligence (AI) Integration with IDEs
Jonas, Maximilian, and Philip of EclipseSource penned a compelling article on the integration of Artificial Intelligence (AI) with IDEs, as we see in offerings like Github Copilot, Codeium, Tabine, ChatGPT. They opine AI will have the same transformative potential for graphical languages and modeling tools.
Contributor Award to Marc Dumai
We announced Marc Dumais as the recipient of the Contributor Award for the first quarter of 2024. This is in recognition of Marc's outstanding contributions that have significantly simplified third-party license checks across ECDT projects, contributing to enhanced project integrity and compliance.
Eclipse Theia Community Call in March
On March 14th we conducted our most recent community call. This is an open forum intended to provide updates on Theia, foster discussion within the ecosystem, and engage the community of Theia adopters, contributors, and users. More details on our agenda and discussion.
Cloud DevTools at EclipseCon 2024
![OCX 2024](https://images-eur.cvent.com/pr53/2ac5396347b34ca6bedd995a5179b7c7/pix/5e7fb1216e5145bd849927952f5f8603!_!32c604f0679bcda44f0aa44bbf8fc0a1.png?f=webp)
The Eclipse Foundation announced the launch of Open Community Experience (OCX), a transformative open source developer conference set to take place 22-24 October 2024 in Mainz, Germany. Look for Cloud DevTools and Open VSX as part of the OCX EclipseCon main event. Sponsor packages include multiple event passes, are available. The Call for Proposals is now open, with an early bird deadline of 31 May 2024.
Langium 3.0
![Langium](https://blogs.eclipse.org/sites/default/files/styles/large/public/2024-03/langium.png?itok=jVLYLdfj)
The Langium team announced the release of Langium 3.0. Overall, this release is more focused on improving the way Langium is used in projects, in support of larger frameworks, and as a parsing tool in conjunction with an IDE. Enhancements include, among other things, async parsing support, reduced bundle size, and enhanced error reporting.
Theia 1.47 and 1.48
![Theia](https://blogs.eclipse.org/sites/default/files/styles/large/public/2023-07/image1.png?itok=oCtAW012)
The Theia team announced the releases of Theia 1.47 and 1.48. Enhancements include secondary window support for text editors, file link navigation in the terminal view, an updated Monaco dependency, editor tab decorations, installing plugins/extensions from the command line and .vsix files from explorer view, and more! See the release notes for the complete stories.
If you are looking for a simple way to check out the new release, please download and install the Theia IDE, which is based on Theia 1.48.
Other Recent Releases
Cloud Tool Time Webinars
We are now scheduling Cloud Tool Time webinars for 2023. Be sure to Sign up now to get on the calendar and let us help tell your story. You can see past sessions on our Youtube channel.
Eclipse Cloud DevTools Projects
Explore the Eclipse Cloud DevTools ecosystem! Check out our projects page to find out more about open source innovation for cloud IDEs, extension marketplaces, frameworks and more.
Getting Listed on the Cloud DevTools Blog
If you are working with, or on, anything in the Cloud DevTools space, learn how to get your writings posted in our blog section.
April 27, 2024
Docendo discimus and Retroactive Interference
by Donald Raab at April 27, 2024 01:58 AM
By teaching, we learn and when we learn, we sometimes forget.
docendo discimus
This Latin phrase translates to “by teaching, we learn.� Thanks to Chandra Guntur for teaching this phrase to me, a few days before a talk I gave at QCon New York in 2018. I have used this phrase so many times over the last six years, that I included it in a new category in the Desktop Don Reference with the title of “Communication� .
I was reminded about how much I love teaching, by my former colleague Bhavana Hindupur, in a LinkedIn post yesterday. Thank you, Bhavana! I thought I would take some time to share a lesson I learned while teaching the Eclipse Collections Katas over the years.
I have taught the Eclipse Collections Katas since 2007. In the early days, there was one kata — The Company Kata. This kata was originally developed by John Tobin and later evolved into training materials developed by Craig Motlin. We would teach the Company Kata in Goldman Sachs as an eight hour training class for Java developers. In 2014, I would write a two part series of InfoQ articles with the title “GS Collections by Example�. In Part 2, I would introduce a set of examples that Nikhil Nanivadekar would later convert into the Pet Kata. We would start teaching the Pet Kata as a four hour class. Spending eight hours on intense focused learning is exhausting and hard to fit in some folks schedules. Four hours proved more manageable.
There were many things I have learned while teaching these katas over the past 17 years. I was reminded of one thing I learned while explaining a “fused� Eclipse Collections method in a tweet earlier today. One thing I saw every time I taught the Company Kata was how new learning can sometimes obscure old knowledge.
In exercise two of the Company Kata, developers would learn how to use anySatisfy with a Predicate to determine if any Customers lived in “London�. In exercise four of the Company kata, they would need to find a way of finding a Supplier who supplies a “sandwich toaster�. After a bit of a struggle, most of the developers would figure out how to use anySatisfy to solve the problem. The better solution is to use contains. The method named contains is part of the standard Java Collection protocol. Unfortunately, in the exercise, the data structure that developers would need use contains on is not a Collection, it is an array. An array in Java has no behavior. Developers had learned in the class how to use ArrayIterate
When I would explain my solutions to the developers in the class, I would explain that contains can be implemented in terms of anySatisfy, using an “equals� Predicate. The developers had good intuition, but in the midst of learning new things (anySatisfy), had forgotten about old things they knew (contains).
Retroactive Interference
Chandra taught me the Psychology term for this phenomenon today. He said it is called “retroactive inhibition/interference�.
Most Java developers will learn Java Stream anyMatch after learning Collection contains first. I wouldn’t be surprised if some Java developers are using anyMatch instead of contains to solve some problems. This would be unfortunate, as contains is optimized for Set and Bag.
We have to learn and remember a lot as developers. The more we practice, the more we can remember. It is helpful to learn basic patterns like anySatisfy, and then fused patterns like contains (anySatisfy + Equals Predicate).
The tweet I mentioned earlier in this blog that I shared today described another fused pattern, which combines map + anyMatch + Equals Predicate. When you see anyMatch + Equals Predicate, you should now immediately think “contains!�. The rest of the info on the other fused method is in the “Fusing methods for productivity� blog below.
Enjoy! �
Fusing methods for productivity
I am the creator of and committer for the Eclipse Collections OSS project, which is managed at the Eclipse Foundation. Eclipse Collections is open for contributions.
April 23, 2024
Nuanced String Joining in Java
by Donald Raab at April 23, 2024 06:03 AM
Subtle differences sometimes make a big difference
Starting with an Integer array
I opened up my IntelliJ IDE and created an Integer array. I don’t usually like boxing primitives but wanted to see what interesting things I could discover about Eclipse Collections and Java Stream without immediately jumping into primitive types.
Integer[] numbers = {1, 2, 3, 4, 5};
The first question I asked is “What can we do with this that is simple but interesting?“.” We can easily adapt this array in Java as a Stream.
Stream<Integer> stream = Stream.of(numbers);
We can also adapt it as an ArrayAdapter in Eclipse Collections.
ArrayAdapter<Integer> adapted = ArrayAdapter.adapt(numbers);
But what next? This is where our fun begins.
Let’s make a String
I wrote an article for 97 Things Every Java Programmer Should Know with the title “Learn to Kata and Kata to Learn.” In this article, I iterate through some example Java code using Collectors.joining() and String.join() to create a comma separated list of names. Then I turn the exercise into a code kata. I started with a List<String> and asserted some derived result of a joined String would equal the names in the List separated by commas.
This is a trivial example for both Collectors.joining and String.join. The example only involved a delimiter. It did not involve a prefix and a suffix. It also started off with String instances, which as we will see, is the perfect scenario for both Collectors.joining and String.join. Unfortunately, in the many classed world of object oriented programming, not everything starts out as a String.
Our problem today will start with the array of Integers values from 1 to 5 and converted them to a String starting with a “*”, separating elements with “*, *” and then finishing with a “*”.
For Loop
Joining an Integer array into a String with a for loop is a good exercise for us to start with.
@Test
public void loopArrayOfIntegerIntoAString()
{
Integer[] numbers = {1, 2, 3, 4, 5};
StringBuilder builder = new StringBuilder("*");
for (int i = 0; i < numbers.length; i++)
{
if (i > 0)
{
builder.append("*, *");
}
builder.append(numbers[i]);
}
String string = builder.append("*").toString();
Assertions.assertEquals("*1*, *2*, *3*, *4*, *5*", string);
}
We use StringBuilder here, but I started off with simple String concatenation. IntelliJ recommending applying an automated refactoring to convert the String concatentation to StringBuilder. So I did. The code is fairly simple here to understand. We iterate over the array using indexed access, so that we can check if we are not on the first (0th) element. Only the first element element will not have the “*, *” delimiter before it. A prefix of “*” and a suffix of “*” are added to the StringBuilder before and after iteration begins. The append method in StringBuilder is nice enough to call String.valueOf on each Integer value for us so we don’t have to. In the end, we assert we wind up with a String that matches this string “*1*, *2*, *3*, *4*, *5*”.
Stream.map, collect, and Collectors.joining
For the next implementation, we will use a Stream and Collectors.joining to create the String. Collectors.joining requires that elements are an instance of CharSequence (a parent interface of String). We will map each Integer to a String using String.valueOf before calling Collectors.joining.
@Test
public void streamAnArrayOfIntegerAndMapCollectorsJoining()
{
Integer[] numbers = {1, 2, 3, 4, 5};
// Collectors.joining requires elements to be CharSequence
// delimiter is first, followed by prefix and then suffix
Stream<Integer> stream = Stream.of(numbers);
String streamedJoining = stream
.map(String::valueOf)
.collect(Collectors.joining("*, *", "*", "*"));
Assertions.assertEquals("*1*, *2*, *3*, *4*, *5*", streamedJoining);
}
This code looks more concise than the for loop. However, it is rather annoying that StringBuilder append calls String.valueOf for us, and Collectors.joining does not. I also found it surprising that we see that joining takes the delimiter first, followed by the prefix and then the suffix. This does not mirror the output of the String.
String.join
For this implementation, we will used String.join. The String.join static method takes a CharSequence delimiter and either an array of CharSequence for the elements, or some kind of Iterable<CharSequence>. We can use the ArrayAdapter class from Eclipse Collections to convert the Integer array to an Iterable<CharSequence>.
@Test
public void adaptAnArrayOfIntegerAndStringJoin()
{
Integer[] numbers = {1, 2, 3, 4, 5};
Iterable<CharSequence> iterable = ArrayAdapter.adapt(numbers)
.asLazy()
.collect(String::valueOf);
// String.join only supports delimiter. Prefix and suffix are concatenated
// Requires elements to be a CharSequence[] or Iterable<CharSequence>
String stringJoin = "*" + String.join("*, *", iterable) + "*";
Assertions.assertEquals("*1*, *2*, *3*, *4*, *5*", stringJoin);
}
Here we use the ArrayAdapter, convert it to a LazyIterable (which is an Iterable) and collect String instances using String::valueOf. The most surprising thing I didn’t know about String.join is that there are no public overloads that take a prefix and suffix, like Collectors.joining has.
We can also use Stream to turn the Integer array into an Iterable<String>.
@Test
public void streamAnArrayOfIntegerAndStringJoin()
{
Integer[] numbers = {1, 2, 3, 4, 5};
Iterable<String> iterable =
Stream.of(numbers).map(String::valueOf)::iterator;
String stringJoin = "*" + String.join("*, *", iterable) + "*";
Assertions.assertEquals("*1*, *2*, *3*, *4*, *5*", stringJoin);
}
We use a method reference here of ::iterator on the Stream to convert it to an Iterable. This is a neat trick since Iterable only requires one method to be implemented, which is iterator.
ArrayAdapter.makeString
In the 97 Things article, I did not include a refactoring to use Eclipse Collections makeString. We will see how to use makeString, which is available on all RichIterable subtypes, below.
@Test
public void adaptAnArrayOfIntegerAndMakeString()
{
Integer[] numbers = {1, 2, 3, 4, 5};
ArrayAdapter<Integer> adapted = ArrayAdapter.adapt(numbers);
// makeString does not require elements to be CharSequence
// prefix is first, then delimiter and then suffix
String makeString = adapted.makeString("*", "*, *","*");
Assertions.assertEquals("*1*, *2*, *3*, *4*, *5*", makeString);
}
Similar to StringBuilder append, makeString applies the call to String.valueOf for us. The order of String parameters here is prefix, delimiter, suffix, which more closely mirrors the expected output.
ArrayIterate.makeString
The simplest solution we will see is using ArrayIterate.makeString from Eclipse Collections. Eclipse Collections has utility classes with the suffix of Iterate. There are Iterate, MapIterate, StringIterate, and ArrayIterate utility classes, that work with Iterable, Map, String, and Object array types respectively.
@Test
public void iterateAnArrayOfIntegerAndMakeString()
{
Integer[] numbers = {1, 2, 3, 4, 5};
String makeString =
ArrayIterate.makeString(numbers, "*", "*, *","*");
Assertions.assertEquals("*1*, *2*, *3*, *4*, *5*", makeString);
}
The makeString method on the utility classes behaves the same as on RichIterable subtypes. The method does not require the elements in the array to be some type of String or CharSequence already. The prefix comes first after the array parameter, followed by delimiter and then by suffix.
Looking for more nuance? Let’s get primitive.
Instead of an array of Integer, let’s switch to an array of int, and see what options we have to convert to a delimited String.
MutableIntList.makeString
We can convert an int array to a MutableIntList and use makeString on a primitive List.
@Test
public void mutableIntListMakeString()
{
int[] numbers = {1, 2, 3, 4, 5};
MutableIntList adapted = IntLists.mutable.with(numbers);
String makeString = adapted.makeString("*", "*, *", "*");
Assertions.assertEquals("*1*, *2*, *3*, *4*, *5*", makeString);
}
IntStream.of, boxed and mapToObject
We can create an IntStream using the int array with the static of method, and then box it to Integer using the method boxed. There are no primitive Collectors for primitive Streams, so boxing is our only option.
@Test
public void intStreamBoxedCollectorsJoining()
{
int[] numbers = {1, 2, 3, 4, 5};
Stream<Integer> boxed = IntStream.of(numbers).boxed();
String streamedJoining = boxed
.map(String::valueOf)
.collect(Collectors.joining("*, *", "*", "*"));
Assertions.assertEquals("*1*, *2*, *3*, *4*, *5*", streamedJoining);
}
We can also get rid of the boxing to Integer, and box straight from int to String using mapToObj with String.valueOf.
@Test
public void intStreamMapToStringCollectorsJoining()
{
int[] numbers = {1, 2, 3, 4, 5};
String string = IntStream.of(numbers)
.mapToObj(String::valueOf)
.collect(Collectors.joining("*, *", "*", "*"));
Assertions.assertEquals("*1*, *2*, *3*, *4*, *5*", string);
}
Update: Some Benchmarks
A reader commented that they would be interested in seeing some benchmarks. I was not really interested in spending time writing or running any benchmarks for these method comparisons, but I did find a set of benchmarks that already existed in the Eclipse Collections repo comparing Collectors.joining() on a Stream with makeString() in Eclipse Collections object and primitive types. So I decided to run the benchmarks while drinking some coffee today.
I set the SIZE of the collections to 100. I changed the TimeUnit to MILLISECONDS, so the measurements are in Operations per Millisecond.
I limited the tests to the following methods.
@Benchmark
public String serial_lazy_mapToStringJoining_jdk()
{
// Stream with an ArrayList<Integer> of size 100
return this.integersJDK.stream()
.map(Object::toString)
.collect(Collectors.joining(","));
}
@Benchmark
public String serial_lazy_mapToStringJoining_ec()
{
// Stream with a FastList<Integer> of size 100
return this.integersEC.stream()
.map(Object::toString)
.collect(Collectors.joining(","));
}
@Benchmark
public String serial_eager_makeString_ec()
{
// makeString with a FastList<Integer> of size 100
return this.integersEC.makeString(",");
}
@Benchmark
public String serial_eager_primitiveMakeString_ec()
{
// makeString with IntArrayList of size 100
return this.intList.makeString(",");
}
The results were obtained on my MacBook Pro M2 Max on Sonoma 14.4.1 using Azul Zulu JDK 21 and were as follows.
Benchmark Mode Cnt Score Error Units
serial_eager_makeString_ec thrpt 20 739.087 ± 17.148 ops/ms
serial_eager_primitiveMakeString_ec thrpt 20 828.930 ± 5.360 ops/ms
serial_lazy_mapToStringJoining_ec thrpt 20 433.049 ± 5.491 ops/ms
serial_lazy_mapToStringJoining_jdk thrpt 20 424.496 ± 7.619 ops/ms
![](https://cdn-images-1.medium.com/max/1024/1*SIvSA2hq3nPmg7w7MmWXjQ.png)
The bigger the numbers, the better the performance. I do not personally find these kind of microbenchmark comparisons interesting. All the code examples here are extremely fast, and would only be a bottleneck in a system generating a million calls to these methods per second, or possibly from generating Strings from very large collections. More likely, there will be some other bottleneck in the code.
I prefer makeString because it requires less code and arguably makes the code easier to read. I hope folks would prefer makeString because it takes less code and is more readable, not because makeString is faster in this benchmark run than Collectors.joining(). If anyone finds these isolated microbenchmarks useful and wants to take the time to investigate to understand why the numbers are different, you have the source. Enjoy!
Summary
In this blog we saw how to use several approaches to convert the elements of an Integer array to a delimited String with a prefix and a suffix. The following are the methods we explored.
✅ for loop
✅ Stream.map, collect, and Collectors.joining
✅ String.join
✅ ArrayAdapter.makeString
✅ ArrayIterate.makeString
We then explored converting the Integer array to an int array, and looked at how we can convert that to a delimited String.
✅ MutableIntList.makeString
✅ IntStream.of, boxed and mapToObj
There are nuances to each of these methods. The ArrayIterate approach wound up being the most concise for this particular use case.
Thank you for reading this blog and I hope you find the solutions I shared to this problem informative.
Enjoy!
I am the creator of and committer for the Eclipse Collections OSS project, which is managed at the Eclipse Foundation. Eclipse Collections is open for contributions.
Nuanced String Joining in Java was originally published in Javarevisited on Medium, where people are continuing the conversation by highlighting and responding to this story.
April 22, 2024
Call for Papers: eSAAM 2024
by Shanda Giacomoni at April 22, 2024 01:05 PM
Submit your papers for Eclipse SAAM on Data Spaces, a conference that will bring together practitioners and researchers working on innovative software and systems solutions for next-generation mobility. This year the conference is co-located with Open Community Experience and will focus on Security and Privacy, Artificial Intelligence, Architecture, Modelling and related challenges.
April 19, 2024
Haiku Kata using String transform, Text Blocks, and Switch Expressions
by Donald Raab at April 19, 2024 03:44 PM
I solved the Haiku Kata again using more features added since Java 12
Finding String transform
I found a method on the Java String class I hadn’t seen before. I discovered it while running the String class through my Java class kaleidoscope. There is a method that was added in Java 12 named transform.
![](https://cdn-images-1.medium.com/max/1024/1*ztDipb6ELiPGlJqx7e5dSQ.png)
The transform method makes it possible to pass a Function to a String and have any type returned. In Java, the more popular name for this method is map on Stream and Optional.
I couldn’t understand why this method was added to the String class. This is the only method on String that takes a Functional Interface like Function.
What is the purpose of this method on String?
Instead of scratching my head wondering, I decided to see what I could do with this method.
Haiku Kata
I created a kata for a set of eleven Haiku I wrote during a self-enforced writing detox period I went through in September 2021. I turned my haiku into a Java kata and blogged about it here. José Paumard turned my Haiku Kata into an amazing YouTube tutorial in JEP Café #9.
https://medium.com/media/d954992e8ffb899b6ebe8ff504c2facc/hrefJosé’s JEP Café #9 is currently one of the Top 10 most popular videos on the Java YouTube channel based on views. Congrats José!
Paul King also implemented the Haiku Kata in Groovy last year.
The Haiku Kata was intended to be a way for me to experiment with Java’s Text Block feature. Text Blocks were added as a standard feature in Java 15, and were in preview in Java 13 and 14.
In the Haiku Kata, I adapt a String stored as a Text Block into a CharAdapter class from Eclipse Collections. The code I write to do this looks like this.
CharAdapter chars = Strings.asChars("Hello!");
The equivalent using the Java chars method looks like this.
IntStream chars = "Hello!".chars();
With the new transform method on the String class, it is possible to flip this code.
CharAdapter chars = "Hello!".transform(Strings::asChars);
There is something subtle that happens with this inversion of behavior, other than requiring a few more characters. To see the effect, it helps to have bigger String instances than “Hello!”. This is why I went back to the Haiku Kata to try the transform method.
Distinct Letters
One of the first tests to implement in the Haiku Kata is finding the distinct letters in the Tex Block. Using the String transform method, it is possible to inline all of the code to look as follows.
@Test
public void distinctLettersEclipseCollections()
{
String distinctLetters = """
Breaking Through Pavement Wakin' with Bacon Homeward Found
---------------- -------- ----------------- --------------
The wall disappears Beautiful pavement! Wakin' with Bacon House is where I am
As soon as you break through the Imperfect path before me On a Saturday morning Home is where I want to be
Intimidation Thank you for the ride Life’s little pleasures Both may be the same
Winter Slip and Slide Simple Nothings With Deepest Regrets
--------------------- --------------- --------------------
Run up the ladder A simple flower With deepest regrets
Swoosh down the slide in the snow Petals shine vibrant and pure That which you have yet to write
Winter slip and slide Stares into the void At death, won't be wrote
Caffeinated Coding Rituals Finding Solace Curious Cat Eleven
-------------------------- -------------- ----------- ------
I arrange my desk, Floating marshmallows I see something move This is how many
refactor some ugly code, Cocoa brewed hot underneath What it is, I am not sure Haiku I write before I
and drink my coffee. Comfort in a cup Should I pounce or not? Write a new tech blog.
"""
.transform(Strings::asChars)
.select(Character::isAlphabetic)
.collectChar(Character::toLowerCase)
.distinct()
.toString();
Assertions.assertEquals("breakingthoupvmwcdflsy", distinctLetters);
}
The transform method works better here than the original form which would require wrapping the entire text block in a method call to Strings.asChars().
This is what it would have looked like without the transform method.
@Test
public void distinctLettersEclipseCollectionsWithoutTransform()
{
String distinctLetters = Strings.asChars("""
Breaking Through Pavement Wakin' with Bacon Homeward Found
---------------- -------- ----------------- --------------
The wall disappears Beautiful pavement! Wakin' with Bacon House is where I am
As soon as you break through the Imperfect path before me On a Saturday morning Home is where I want to be
Intimidation Thank you for the ride Life’s little pleasures Both may be the same
Winter Slip and Slide Simple Nothings With Deepest Regrets
--------------------- --------------- --------------------
Run up the ladder A simple flower With deepest regrets
Swoosh down the slide in the snow Petals shine vibrant and pure That which you have yet to write
Winter slip and slide Stares into the void At death, won't be wrote
Caffeinated Coding Rituals Finding Solace Curious Cat Eleven
-------------------------- -------------- ----------- ------
I arrange my desk, Floating marshmallows I see something move This is how many
refactor some ugly code, Cocoa brewed hot underneath What it is, I am not sure Haiku I write before I
and drink my coffee. Comfort in a cup Should I pounce or not? Write a new tech blog.
""")
.select(Character::isAlphabetic)
.collectChar(Character::toLowerCase)
.distinct()
.toString();
Assertions.assertEquals("breakingthoupvmwcdflsy", distinctLetters);
}
It is harder to determine what type the select method is being applied to as you have to scan up to the top of the text block to see the String.asChars( opening.
Top Three Letters
The test to find the top three letters in the haiku can be rewritten using a single fluent line of code, by using the Switch Expressions feature of Java to make the test Assertions part of a call to forEachWithindex.
@Test
public void topLettersEclipseCollections()
{
"""
Breaking Through Pavement Wakin' with Bacon Homeward Found
---------------- -------- ----------------- --------------
The wall disappears Beautiful pavement! Wakin' with Bacon House is where I am
As soon as you break through the Imperfect path before me On a Saturday morning Home is where I want to be
Intimidation Thank you for the ride Life’s little pleasures Both may be the same
Winter Slip and Slide Simple Nothings With Deepest Regrets
--------------------- --------------- --------------------
Run up the ladder A simple flower With deepest regrets
Swoosh down the slide in the snow Petals shine vibrant and pure That which you have yet to write
Winter slip and slide Stares into the void At death, won't be wrote
Caffeinated Coding Rituals Finding Solace Curious Cat Eleven
-------------------------- -------------- ----------- ------
I arrange my desk, Floating marshmallows I see something move This is how many
refactor some ugly code, Cocoa brewed hot underneath What it is, I am not sure Haiku I write before I
and drink my coffee. Comfort in a cup Should I pounce or not? Write a new tech blog.
"""
.transform(Strings::asChars)
.select(Character::isAlphabetic)
.collectChar(Character::toLowerCase)
.toBag()
.topOccurrences(3)
.forEachWithIndex((each, index) -> Assertions.assertEquals(switch (index)
{
case 0 -> PrimitiveTuples.pair('e', 94);
case 1 -> PrimitiveTuples.pair('t', 65);
case 2 -> PrimitiveTuples.pair('i', 62);
default -> null;
}, index < 3 ? each : null));
}
The method forEachWithIndex is one of the lesser known methods available in Eclipse Collections. The equivalent Assertion code before required calling Assertions.assertEquals three separate times with an indexed lookup into the resulting ListIterable returned from topOccurrences.
Duplicates and Uniques
There wasn’t much to change in the duplicates and uniques code, other than inlining Text Block in the test and using the String transform method.
@Test
public void duplicatesAndUniqueEclipseCollections()
{
MutableCharBag chars = """
Breaking Through Pavement Wakin' with Bacon Homeward Found
---------------- -------- ----------------- --------------
The wall disappears Beautiful pavement! Wakin' with Bacon House is where I am
As soon as you break through the Imperfect path before me On a Saturday morning Home is where I want to be
Intimidation Thank you for the ride Life’s little pleasures Both may be the same
Winter Slip and Slide Simple Nothings With Deepest Regrets
--------------------- --------------- --------------------
Run up the ladder A simple flower With deepest regrets
Swoosh down the slide in the snow Petals shine vibrant and pure That which you have yet to write
Winter slip and slide Stares into the void At death, won't be wrote
Caffeinated Coding Rituals Finding Solace Curious Cat Eleven
-------------------------- -------------- ----------- ------
I arrange my desk, Floating marshmallows I see something move This is how many
refactor some ugly code, Cocoa brewed hot underneath What it is, I am not sure Haiku I write before I
and drink my coffee. Comfort in a cup Should I pounce or not? Write a new tech blog.
"""
.transform(Strings::asChars)
.select(Character::isAlphabetic)
.collectChar(Character::toLowerCase)
.toBag();
CharBag duplicates = chars.selectDuplicates();
CharSet unique = chars.selectUnique();
Assertions.assertEquals(chars, duplicates);
Assertions.assertEquals(CharSets.immutable.empty(), unique);
}
Final Thoughts
I can’t tell yet if the String transform method has interesting uses that I haven’t thought of yet, but I was happy to see how it worked with the the Haiku Kata. In the original version of the kata, I stored the text block into a field called haiku so as to keep the huge text block out of the methods, taking away from the method calls. The transform method created a nice separation and progression between the inlined String Text Block and the transformation code that found the distinct, top three, duplicate and unique characters.
Thanks for reading, and I hope you enjoyed learning about my recent discovery of the String transform method.
I am the creator of and committer for the Eclipse Collections OSS project, which is managed at the Eclipse Foundation. Eclipse Collections is open for contributions.
Haiku Kata using String transform, Text Blocks, and Switch Expressions was originally published in Javarevisited on Medium, where people are continuing the conversation by highlighting and responding to this story.
April 18, 2024
The Eclipse Foundation Unveils Open Community Experience (OCX), Europe’s Premier Event for Open Source Innovation
by Jacob Harris at April 18, 2024 11:00 AM
BRUSSELS – 18 April 2024 – The Eclipse Foundation, one of the world’s largest open source foundations, is proud to announce the launch of Open Community Experience (OCX), a transformative open source developer conference set to take place 22-24 October 2024 in Mainz, Germany. This inaugural event will be a catalyst for open collaboration and innovation, covering a diverse range of community-curated open source topics, including automotive & mobility, embedded IoT & edge, cloud native Java, languages and runtimes, supply chain security, dataspaces, and open source software development best practices.
“As our communities have continued to grow and thrive, it became clear that we needed to create a new event that matched the momentum behind our growing ecosystem, as well as the diversity of its interests and collaborations,” said Mike Milinkovich, executive director of the Eclipse Foundation. “OCX has been built to serve as the premier event in Europe for developers and technology leaders worldwide engaged in open source ecosystems to meet, share ideas and experiences, and learn from each other.”
Set in the historic city of Mainz, Germany, near Frankfurt, OCX will offer an array of tracks covering Eclipse projects and a wide range of topics relevant to open source developers and practitioners. In addition to the main conference tracks, OCX will also host three multi-day, collocated events, each dedicated to specific communities: Open Community for Automotive, Open Community for Java, and EclipseCon.
The planned lineup includes:
- OCX Main Tracks
- Embedded, IoT & Edge
- Languages & Runtimes
- OSS Supply Chain Security
- Open Collaboration Best Practices
- Open Community for Automotive: dedicated to automotive software, software defined vehicles, and mobility.
- Open Community for Java: focusing on topics related to Jakarta EE, Adoptium, MicroProfile, open source enterprise Java, and more.
- EclipseCon: the centre of gravity for all topics related to the Eclipse IDE platform and next-generation cloud-based development tools.
In addition to the collocated three-day events, the program will feature specialised sessions and one day gatherings like the Eclipse Security, Artificial Intelligence, Architecture, and Modelling Conference (eSAAM) on 22 October 2024, which will spotlight innovative software and solutions for data spaces.
OCX offers the ideal opportunity to engage with developers, executives, and evangelists shaping today’s most advanced open technologies. Whether you aim to showcase your own solutions, expand your organisation’s role in the developer ecosystem, or connect with potential partners for new opportunities, OCX is Europe's premier venue for developer innovation. We are now actively seeking contributions from sponsors, members, potential speakers, and more. Join us in shaping the future of open source collaboration at OCX!
OCX is made possible with the generous support of our sponsors, and we extend our sincere gratitude to each of them. A special acknowledgement goes to Huawei, our first Diamond-level sponsor, whose support sets a high standard for excellence. We also appreciate the early sponsorship commitment from EclipseSource, Lunatech, Obeo, Scanoss, and Typefox. Your contributions make OCX a reality and greatly enhance the experience for all attendees
We encourage all companies in the Eclipse ecosystem, particularly our Strategic members, to consider sponsoring our flagship conference. This is a unique opportunity to build your brand and directly engage a highly qualified developer audience focused explicitly on the open source technologies that drive your business. Sponsor packages include multiple event passes, making it easy for your developers to join the many conversations to be had at this unique confluence of forward-thinking technologists. Explore sponsorship opportunities by reaching out to sponsors@OCXconf.org.
For more details on OCX and how you can sponsor and participate, visit the OCX website. If you would like to submit a talk for consideration, the Call for Proposals is now open, with an early bird deadline of 31 May 2024.
About the Eclipse Foundation
The Eclipse Foundation provides our global community of individuals and organisations with a business-friendly environment for open source software collaboration and innovation. We host the Eclipse IDE, Adoptium, Software Defined Vehicle, Jakarta EE, and over 415 open source projects, including runtimes, tools, specifications, and frameworks for cloud and edge applications, IoT, AI, automotive, systems engineering, open processor designs, and many others. Headquartered in Brussels, Belgium, the Eclipse Foundation is an international non-profit association supported by over 360 members. Visit us at this year’s Open Community Experience (OCX) conference on 22-24 October 2024 in Mainz, Germany. To learn more, follow us on social media @EclipseFdn, LinkedIn, or visit eclipse.org.
Third-party trademarks mentioned are the property of their respective owners.
###
Media contacts:
Schwartz Public Relations for the Eclipse Foundation, AISBL (Germany)
Gloria Huppert/Julia Rauch
Sendlinger Straße 42A
80331 Munich
EclipseFoundation@schwartzpr.de
+49 (89) 211 871 -70/-43
Nichols Communications for the Eclipse Foundation, AISBL
Jay Nichols
+1 408-772-1551
514 Media Ltd for the Eclipse Foundation, AISBL (France, Italy, Spain)
Benoit Simoneau
M: +44 (0) 7891 920 370
April 17, 2024
OCX Call for Proposals Now Open!
by Shanda Giacomoni at April 17, 2024 04:03 PM
Do you have insights, experiences, or innovations to share? We're currently accepting submissions for our new Open Community Experience (OCX) conference and it's collocated events. Submit your proposal now and be part of shaping the OCX 2024 agenda.
April 12, 2024
Enhancing Modeling Tools with AI: A Leap Towards Smarter Diagrams with Eclipse GLSP
by Jonas, Maximilian & Philip at April 12, 2024 12:00 AM
The integration of Artificial Intelligence (AI) with IDEs, as exemplified by tools like Github Copilot, Codeium, Tabine, ChatGPT and more, has opened new horizons in software development. It is …
The post Enhancing Modeling Tools with AI: A Leap Towards Smarter Diagrams with Eclipse GLSP appeared first on EclipseSource.
April 11, 2024
OCX 2024: Celebrating Community, Code and Collaboration
by Clark Roundy at April 11, 2024 06:25 PM
TL;DR - Don't miss the opportunity to participate in Open Community Experience 2024, a new conference for our vibrant community of communities.
At the Eclipse Foundation, our ethos is anchored in three pivotal Cs: Community, Code, and Collaboration. These principles are so integral to our mission that when we re-envisioned our flagship event for 2024, we aimed to include these themes. As a code-first community, we initially introduced our revamped event as the Open Code Experience (OCX). However, after careful reflection and, in full disclosure, due to some potential concerns related to trademark considerations, we embraced a name that truly resonates with our core mission: the Open Community Experience.
Communities are at the core of the Eclipse Foundation. OCX 2024 will showcase a diverse range of excellent content across multiple tracks from the Eclipse ecosystem. In addition to the main conference tracks, OCX will also host three multi-day, collocated events, each dedicated to specific communities: Open Community for Automotive, Open Community for Java, and EclipseCon.
Our program committees are currently hard at work building an outstanding program, but here's a glimpse of what to expect:
- Main OCX Tracks: Content covering embedded systems, IoT and edge computing, programming languages and runtimes, security, trusted data sharing, and open source best practices.
- Open Community for Automotive: Focused on innovations in automotive software, software-defined vehicles, and mobility domains.
- Open Community for Java: A deep dive into the open source enterprise Java ecosystem, featuring content related to Jakarta EE, Adoptium, MicroProfile, and much more.
- EclipseCon: Reinvented as the nexus for all talks related to the Eclipse IDE platform and the evolving landscape of development tools.
In addition to the collocated multi-day events, the program will feature specialised sessions and one day gatherings like the Eclipse Security, Artificial Intelligence, Architecture, and Modelling Conference (eSAAM), which will spotlight innovative software and solutions for data spaces.
OCX is made possible with the generous support of our sponsors, and we extend our sincere gratitude to each of them. A special acknowledgement goes to Huawei, our first Diamond-level sponsor, whose support sets a high standard for excellence. We also appreciate the early sponsorship commitments from EclipseSource, Lunatech, Obeo, Scanoss, and Typefox. Your contributions make OCX a reality and greatly enhance the experience for all attendees.
We encourage all companies in the Eclipse ecosystem, particularly our Strategic members, to consider sponsoring our flagship conference. This is a unique opportunity to build your brand and directly engage a highly qualified developer audience focused explicitly on the open source technologies that drive your business. Sponsor packages include multiple event passes, making it easy for your developers to join the many conversations to be had at this unique confluence of forward-thinking technologists. Explore sponsorship opportunities by reaching out to sponsors@OCXconf.org.
OCX isn't just an event — it's a celebration of community-driven collaboration and open source innovation. We invite you to join us on this exciting journey. For more details on OCX and how you can sponsor and participate, visit the OCX website. And, be sure to mark your calendars for the Call for Proposals opening on April 15.
Stay tuned for more exciting news and announcements in the coming weeks!
April 09, 2024
Eclipse Theia 1.48 Release: News and Noteworthy
by Jonas, Maximilian & Philip at April 09, 2024 12:00 AM
We are happy to announce the Eclipse Theia 1.48 release! The release contains 53 merged pull requests and we welcome two new contributors. In this article we will highlight some selected improvements …
The post Eclipse Theia 1.48 Release: News and Noteworthy appeared first on EclipseSource.
April 06, 2024
Looking at a Java Class and its Methods Through a Kaleidoscope
by Donald Raab at April 06, 2024 06:44 PM
Exploring the Java Stream methods from multiple perspectives
Six Views of a Java Class
I have been exploring different ways of understanding the methods of large Java classes. I don’t mean large in terms of lines of code, but large in terms of number of methods. Feature-rich interfaces, sometimes referred to as humane interfaces, are not incredibly humane when you need to find a method, if you don’t know the name, or discover patterns and look for symmetry between types. Thankfully, we have computers to help us process large amounts of data very quickly. Class and Method declarations are an easily accessible treasure trove of information about libraries and applications that Java developers have at their fingertips. Unfortunately, beyond good old Javadoc we don’t have many ways to make them talk.
I’ve created some basic documentation tools for increasing my own understanding of the feature-rich API of Eclipse Collections. Of course, I use Eclipse Collections to help me understand Eclipse Collections. The tools I am creating allow me to understand any Java Class and its Method instances, not just Eclipse Collections classes. One might consider the tools I have been experimenting with as a kind of Javadoc++. I am writing this blog in the hopes it might confirm or deny the usefulness of some of these class/method views.
I’m also hoping this blog will bring more attention and interest to a user-defined method grouping feature that is missing in Java, that I learned from Smalltalk, and is known as Method Categories. Imagine being able to optionally tag each Method in a Java Class with something like methodCategory=”filtering” or methodCategory=”transforming” and then having JavaDoc, IDEs, and developers able to query this information through the Method interface. I digress. Back to the views and groupings that I was able to create without any new Java features.
I have created five AsciiDoc generated views of a class and its methods to help me understand how the methods on the class are organized and if any interesting patterns exist. These views can help me understand class scope, naming patterns and any symmetry/asymmetry that might exist.
The six views of a Java class we will see in this blog are as follows:
- Javadoc
- Methods by First Letter
- Methods by Prefix
- Methods by Suffix
- Methods by Return Type
- Methods by Functional Interface Parameter Types
For views two through six, I used Eclipse Collections to group and count methods by different attributes based on the Class and Method types in Java.
There is no user-defined grouping mechanism for Java methods today, which would be the equivalent of method categories in Smalltalk. I used the available metadata about a Method to build groupings of methods to create these additional views of methods using generated AsciiDoc. I hosted the generated AsciiDoc for the Java Stream class in gists. I linked to the gists below and used GitHub’s ability to render AsciiDoc to have decent looking tables displayed inline.
Enjoy the following views of the Java Stream class and its methods!
Six Views of Java Stream
We will explore the six views of a Java class using Java Stream as an example.
1. Javadoc
The first view of Stream we can find online is the Javadoc for the class.
The Javadoc view shows us all the documentation about the class, and organizes a method summary with all methods listed in alphabetical order. While this may be suitable for some purposes, it does not help us find patterns in the methods, because there is only a flat view without any particular grouping. We can filter methods by static methods, instance methods, abstract methods, and default methods.
We can use the useful search widget in the top right corner to find things. There is also an interesting “Use” tab that can show us the places in the JDK where Java Stream is used.
Uses of Interface java.util.stream.Stream (Java SE 21 & JDK 21)
2. Stream Methods by First Letter
This is the simplest view of methods on a class. I use Eclipse Collections to group all of the methods of the Stream class by their first letter, and sort them by the most frequent first letter to the least frequent.
In each letter, the methods are sorted alphabetically. The benefit of this view is the method compression. In the Javadoc view for Stream, you have to scroll to see all of the methods. With this view, there is no scrolling on either my 27 inch monitor or laptop screen.
https://medium.com/media/49b7a53df8af7eb8c79e3bd6df9420da/href3. Stream Methods by Prefix
This view is slightly more interesting than grouping by first letter. Here we group the methods by any prefix they might have like “map” or “for”. The prefix is determined by the split between the initial lowercase letters in the method and the first uppercase letter. Methods with no prefix, or having all lowercase letters, show up in a category of “No Prefix”. This category shows up first because the table is sorted by the most frequent prefix to the least frequent prefix. Prefix does grouping/screen space compression and also serves as a rough approximation of categories for a majority of methods.
https://medium.com/media/7d4b7898ae0bfafd1acff19efa0199ec/href4. Stream Methods by Suffix
This view is an interesting variation on the grouping by prefix. Here we group the methods by any suffix they might have like “int” or “match”. The suffix is determined by the split between the last uppercase letter and the remaining lowercase letters in the method. Methods with no suffix, or having all lowercase letters, show up in a category of “No Suffix”. This category shows up first because the table is sorted by the most frequent suffix to the least frequent suffix.
https://medium.com/media/47cbdbd4061946f918b7585c32da8c80/href5. Stream Methods by Return Type
In this view, which has methods grouped by their return types, we get to see a bit more information about each method. We can see the methods with their parameter types. This necessarily takes up a bit more screen real estate, but the extra information is potentially useful. The table is sorted by most frequent return type to least frequent return type. As we can see, Stream is the most frequent return type from Stream, which means there are a decent number of lazy methods on the Stream interface. There are also four BaseStream methods and nine primitive stream (IntStream, LongStream, DoubleStream) methods which are also lazy.
https://medium.com/media/61700f8d2181d268db2a848bc067e5b1/href6. Stream Methods by Functional Interface Parameter Types
This was the most complicated of the views to produce. In this view, we can see the methods, with their number of parameters as an emoji, grouped by each of the parameter types the methods take. The methods are filtered to only include parameter types that are Functional Interfaces (e.g. Predicate, Function, Consumer). This view tells us which methods are lambda ready, and which Functional Interface has the most methods with it as a parameter type. The parameter number was included here, because as we can see on the BinaryOperator row in the table, there are three overloaded versions of reduce.
This view can quickly answer questions like “Where can I use a Predicate with a Stream?” or “Where can I use a Function with a Stream?”
https://medium.com/media/1b5873c26da2b9dc28168c48a44f861c/hrefComparing Stream and RichIterable Lambda Enabled Methods
The sixth view of the Stream interface methods allowed me to compare how lambda ready Stream is compared to the RichIterable interface from Eclipse Collections, based on the number of methods that accept the four most well known Functional Interfaces as parameters.
![](https://cdn-images-1.medium.com/max/1024/1*CjxufxMVuAR73dN3JTYkfQ.png)
Consumer is quoted in the above chart as the equivalent type in Eclipse Collections is named Procedure.
If you feel like there are some useful methods missing in Stream, you might be able to find them in RichIterable. The detailed view of RichIterable Methods by Functional Interface Parameter Types can be seen below.
https://medium.com/media/2d7fa8c9d57e26186324a3f382e60fd8/hrefFinal Thoughts
Sometimes it’s helpful to build tools to help us augment our understanding of the Java classes and methods we use. Java gives us the capability to query Classes and Methods for a lot of useful information in code. Looking for everything in files can necessitate a lot of scrolling and testing of our memory. Information chunking is extremely helpful for humans. Grouping and Filtering are great options for aiding information chunking.
This is the first time I have used AsciiDoc in a gist included in a Medium blog. I was pleasantly surprised by the automatic rendering of the AsciiDoc tables by GitHub. Now that I know this is possible, I may use AsciiDoc tables in gists instead of screen captures for tables in the future.
I hope you found this blog and the five AsciiDoc generated Class/Method views of the Stream class in Java useful. Please share this blog with others who you think may benefit from learning more about the method naming and organization on the Java Stream class!
Enjoy!
I am the creator of and committer for the Eclipse Collections OSS project, which is managed at the Eclipse Foundation. Eclipse Collections is open for contributions.
Looking at a Java Class and its Methods Through a Kaleidoscope was originally published in Javarevisited on Medium, where people are continuing the conversation by highlighting and responding to this story.
April 04, 2024
The Eclipse Foundation to Highlight Open Innovation at embedded world 2024
by Jacob Harris at April 04, 2024 11:00 AM
BRUSSELS – 4 April 2024 – The Eclipse Foundation, one of the world’s largest open source foundations, is set to unveil its latest open source innovations at this year’s embedded world Exhibition & Conference, taking place in Nuremberg from 9-11 April 2024. The foundation will be presenting talks on multiple embedded topics, while also highlighting new open source technologies, including a safety-certified real-time operating system (RTOS), industrial grade RISC-V CPU IP, and Software-Defined Vehicle (SDV) innovations.
“Embedded computing, the bedrock of today’s digital economy, thrives on open source technologies,” said Mike Milinkovich, executive director of the Eclipse Foundation. “The Eclipse Foundation is experiencing remarkable growth across various aspects of embedded innovation, spanning IoT, edge computing, and our Software Defined Vehicle initiatives. We’re particularly excited to showcase the first release of Eclipse ThreadX at this year’s Embedded World.”
The First Release of Eclipse ThreadX
Eclipse ThreadX, formerly Azure RTOS, is the world's first open source, safety-certified real-time operating system (RTOS). ThreadX is a new addition to the world of open source, having recently become a project at the Eclipse Foundation after its transition from Microsoft. embedded world 2024 serves as the launchpad for the debut release of ThreadX under the stewardship of the Eclipse Foundation. Eclipse ThreadX v6.4.1 is available under the permissive MIT licence. You can download it and its subcomponents from GitHub.
Innovation for Software-Defined Vehicles
The Eclipse SDV team will showcase groundbreaking business use cases with SDV Blueprints, spotlighting advancements in insurance, fleet management, and software orchestration. These initiatives represent a collaborative effort across more than 20 automotive open source projects, highlighting a collective effort to push the boundaries of software-defined vehicles.
Industrial-Grade, Open Source RISC-V CPU Technology
The OpenHW Group will be demonstrating its latest cores based on RISC-V open source technology. The CVA6, CVE4, and CVE2 cores exemplify the pinnacle of open source innovation and adoption in the embedded industry.
Cutting-Edge Research and New Open Source Projects
The Eclipse Research team will unveil four new projects that are advancing the future of technology:
- CODECO, a cognitive, cross-layer, and highly adaptive Edge-Cloud management framework
- TRISTAN, an industrialisation of the European RISC-V ecosystem that is capable of competing with existing commercial alternatives
- TRANSACT, a universal, distributed solution architecture for the transformation of security-critical cyber-physical systems
- NEPHELE, a reliable and secure end-to-end orchestration of hyper-distributed applications on a programmable infrastructure.
Advancing European Technology Leadership with Eclipse Aidge
With the backing of CEA List, the Eclipse Aidge project stands out as a testament to European and French technological leadership. It embodies the successful transition from academic research to real-world applications, showcasing the symbiotic relationship between academia and embedded industry. Connect with the CEA List team to learn more about Eclipse Aidge.
Get to Know Our Community
Discover the diverse Eclipse Foundation ecosystem catering to the IoT, edge, and embedded industries. Representatives from key Eclipse communities such as Eclipse IoT, Sparkplug, and Oniro will all be available to engage with you.
Must-Attend Technical Talks
Eclipse Foundation experts will have a strong presence at this year’s embedded world, including two specific presentations that anyone interested in open source technologies will not want to miss:
- Frédéric Desbiens: Open Source Software and Lifecycle Standards – Yes: It Can Be Done (Tuesday, April 9, 11:30 AM - 12:00 PM, NCC Ost, Session 6.1)
- Frédéric Desbiens: The State of Open Source Real-Time Operating Systems (Wednesday, April 10, 11:00 AM - 11:30 AM, NCC Ost, Session 3.4)
Join Us at Booth 4-554, Hall 4:
Discover the transformative power of open source innovation by visiting the Eclipse Foundation at booth 4-554, Hall 4. Engage with our vibrant communities, explore industry-leading projects, and discover how open source initiatives are reshaping technology. We look forward to seeing you there!
About the Eclipse Foundation
The Eclipse Foundation provides our global community of individuals and organisations with a business-friendly environment for open source software collaboration and innovation. We host the Eclipse IDE, Adoptium, Software Defined Vehicle, Jakarta EE, and over 415 open source projects, including runtimes, tools, specifications, and frameworks for cloud and edge applications, IoT, AI, automotive, systems engineering, open processor designs, and many others. Headquartered in Brussels, Belgium, the Eclipse Foundation is an international non-profit association supported by over 360 members. Visit us at this year’s Open Code Experience (OCX) conference on 22-24 October 2024 in Mainz, Germany. To learn more, follow us on social media @EclipseFdn, LinkedIn, or visit eclipse.org.
Third-party trademarks mentioned are the property of their respective owners.
###
Media contacts:
Schwartz Public Relations for the Eclipse Foundation, AISBL (Germany)
Gloria Huppert/Julia Rauch
Sendlinger Straße 42A
80331 Munich
EclipseFoundation@schwartzpr.de
+49 (89) 211 871 -70/-43
Nichols Communications for the Eclipse Foundation, AISBL
Jay Nichols
+1 408-772-1551
514 Media Ltd for the Eclipse Foundation, AISBL (France, Italy, Spain)
Benoit Simoneau
M: +44 (0) 7891 920 370
Eclipse Foundation Security Advisory: HTTP CONTINUATION frames issue
by Marta Rybczynska at April 04, 2024 04:24 AM
The Eclipse Foundation Security Team has been made aware of the vulnerability VU#421644 affecting multiple HTTP/2 implementations, that could cause an out-of-memory crash.
April 03, 2024
Showcasing Open Innovation at embedded world 2024: An Eclipse Foundation Preview
by Clark Roundy at April 03, 2024 11:33 PM
With embedded world 2024 just around the corner, we're thrilled to offer a sneak peek into the groundbreaking projects and innovations that are shaping the future, all thanks to the collaborative efforts of the Eclipse Foundation and our vibrant community.
Join us in Nuremberg April 9th to 11th at booth 4-554, Hall 4, as we unveil a diverse spectrum of open source projects and technologies spanning the entire embedded ecosystem. At the Eclipse Foundation booth, you'll have the opportunity to explore the world of open source collaboration and witness firsthand its transformative power.
Here are a few things to expect and explore when you visit our booth:
Software Defined Vehicle Innovation
The Eclipse SDV team will showcase groundbreaking business use cases with SDV Blueprints, spotlighting advancements in insurance, fleet management, and software orchestration. These initiatives represent a collaborative effort across more than 20 automotive open source projects, highlighting a collective effort to push the boundaries of software-defined vehicles.
The World’s First Open Source, Safety-Certified RTOS
Eclipse ThreadX, formerly Azure RTOS, is the world's first open source, safety-certified embedded real-time operating system. ThreadX is a new addition to the world of open source, having recently become a project at the Eclipse Foundation after its transition from Microsoft. Embedded world 2024 serves as the launchpad for the debut release of ThreadX under the stewardship of the Eclipse Foundation. Eclipse ThreadX v6.4.1 is now available under the permissive MIT licence. You can download it and its subcomponents from GitHub. Stop by our booth to engage with one of our experts and learn more about how you can harness the potential of open source in your next safety-critical real-time project.
Industrial-Grade, Open Source RISC-V CPU Technology
With a mission to deliver industrial-grade, fully open source RISC-V CPU IP Cores to the tech community, the OpenHW Group's CVA6, CVE4, and CVE2 cores exemplify the pinnacle of open source innovation and adoption in the industry. Chat with the OpenHW team to learn more about their projects.
Advancing European Technology Leadership with Eclipse Aidge
With the backing of CEA List, the Eclipse Aidge project stands out as a testament to European and French technological leadership. It embodies the successful transition from academic research to real-world applications, showcasing the symbiotic relationship between academia and embedded industry. Connect with the CEA List team to learn more about Eclipse Aidge.
Cutting-Edge Research and New Open Source Projects
The Eclipse Research team will present 4 new projects that are advancing the future of technology: CODECO, a cognitive, cross-layer and highly adaptive Edge-Cloud management framework; TRISTAN, an industrialisation of the European RISC-V ecosystem that is capable of competing with existing commercial alternatives; TRANSACT, a universal, distributed solution architecture for the transformation of security-critical cyber-physical systems; and NEPHELE, a reliable and secure end-to-end orchestration of hyper-distributed applications on a programmable infrastructure.
Get to Know Our Community
Discover the diverse Eclipse Foundation ecosystem catering to the IoT, edge and embedded industries. Representatives from key Eclipse communities such as Eclipse IoT, Sparkplug, and Oniro will all be available to engage with you.
Must-Attend Technical Talks
Embedded world features talks covering myriad topics, but here are some sessions you definitely won’t want to miss:
- Frédéric Desbiens: Open Source Software and Lifecycle Standards – Yes: It Can Be Done (Tuesday, April 9, 11:30 AM - 12:00 PM, NCC Ost, Session 6.1)
- Frédéric Desbiens: The State of Open Source Real-Time Operating Systems (Wednesday, April 10, 11:00 AM - 11:30 AM, NCC Ost, Session 3.4)
Join Us at embedded world 2024
Embedded world 2024 offers a glimpse into the future of embedded systems. Visit the Eclipse Foundation at booth 4-554, Hall 4 To connect with our passionate communities, explore industry-leading projects and discover how open source is reshaping technology. We look forward to seeing you there!
Date: 9 - 11 April 2024
Location: Nuremberg, Germany
Visit Us: Booth 4-554, Hall 4
Eclipse Theia IDE: A Look at Leaps in Performance
by John Kellerman at April 03, 2024 02:53 PM
![XKCD: Compiling by Randal Monroe](https://blogs.eclipse.org/sites/default/files/2024-04/compiling.png)
Developers hate waiting. In the ever-evolving landscape of Integrated Development Environments (IDEs), the quest for swifter, more efficient tools remains a constant pursuit. Enter Eclipse Theia IDE. This is more than a rebrand of Theia Blueprint. It is a statement that this IDE is ready for prime time and to provide a great user experience. It is a statement that the feature set, stability and performance have all improved to the point where the product provides a compelling user experience. We will explore a bit of the performance improvements with Theia IDE startup time and compare it historically. This should lead to a more streamlined development journey.
Objectively speaking, Eclipse Theia IDE delivers a noticeable boost in performance over the “Theia Blueprints” releases 3 months ago, particularly evident during the startup phase. To get to this point, smart engineering was used. The Theia developers started by measuring execution time in a repeatable way. This phase is called instrumentation. After that, they observed the results and improved the performance dominators. This showed them where to look and where to optimize. After that, they identify an issue, fix it and repeat the process to continually make things faster.
The Theia developers set up a site to observe performance changes. The tests were run on github runners, which are quite fast, but more importantly, are quite stable in practical terms. Two runs on the infrastructure yielded reproducible changes.
The following chart shows the total “Startup time.” It does not show a complete picture though as it does not show when users can begin to interact with the UI. You can see there were significant speedups in November, where the performance has more than doubled. The time from initialization to a responsive UI has improved by about the same factor too! There were a few observed speedups on Jan 21st. This is due to the “implement headless plug-ins” patch which defers plug-in loading. These were done by Tobias Ortmayr, Philip Langer, Jonas Helming, Stefan Dirix, Thomas Maeder and more.
![Test Results Graph](https://blogs.eclipse.org/sites/default/files/2024-04/graph.png)
The Theia developers used Eclipse Trace Compass to compare the execution times. If you’d like, you can reproduce the findings yourself. In the theia-e2e-test-suite GitHub repo, run the get_trace.py script to reproduce the experiment.
![Eclipse Trace Compass Flame Chart](https://blogs.eclipse.org/sites/default/files/2024-04/graph2.png)
The view above is the flame chart. It shows the call stack over time. Trace Compass has the ability to synchronize two runs and compare them. With this data layout, it becomes clear that startplugins was a major dominator before, and was reduced. However, every item on the UI thread (front end) seems to have accelerated aggressively. This is great news as the UI thread is resource limited, it could require a UI thread whereas the back-end can eventually multi-threaded more easily.
We must however acknowledge the unknown. The response to first click is measured here with 20% unknown (see above the pink boxes). The unknown is probably due to the Theia plug-in being downloaded to the browser. However, it needs to be confirmed and a trace point on that transaction would need to be added
![Trace Compass Flart Chart: Unknown](https://blogs.eclipse.org/sites/default/files/2024-04/graph3.png)
If the full transaction, i.e. the full initialization and not just interactivity, is considered, almost 80% of the time is unknown. With the data we have, it is not clear what is happening. One possibility is this is when plug-ins are lazy-loaded. It is bounded by the backend operation, and so this could be seen as a "known unknown." While this may initially seem daunting, it presents an opportunity for further exploration and refinement. For example, by instrumenting the plug-in API, the initialization time of plug-ins would be known and a misbehaving plug-in on the critical path of start-up could be identified.
Having a proper, more complete test bench and suite is an opportunity for more visibility in the long run. The partially instrumented code is a good first step, meaning that we need to instrument more, to fill in the gaps. When the code instrumentation is complete for a given test execution flow, more test flows can be then added. This then presents additional opportunities to update the instrumentation.
Will Rogers is attributed to saying “You never get a second chance to make a first impression.” The startup time is the first thing anyone sees when opening a new product, and the Theia community has optimized it, showing their concern with the user experience. This shows the general attitude and the work towards justifying the rebrand from Blueprint to IDE. Its strides in startup performance are the first step on a journey of ongoing enhancement and refinement. As the team continues down this path, the community is optimistic and anticipating what lies ahead. (spoiler alerts: backendless, remote and multi-player!)
With Eclipse Theia IDE arriving on the scene, developers have another viable contender that offers rich features, a vibrant community and a tight experience.
Matthew Khouzam,
Director, Eclipse Foundation
Product Owner/Developer, Ericsson AB
John Kellerman
Program Manager Cloud DevTools and Open VSX
Eclipse Foundation
April 02, 2024
The Open Source Community is Building Cybersecurity Processes for CRA Compliance
by Jacob Harris at April 02, 2024 02:40 PM
Apache Software Foundation, Blender Foundation, OpenSSL Software Foundation, PHP Foundation, Python Software Foundation, Rust Foundation, and Eclipse Foundation are jointly announcing our intention to collaborate on the establishment of common specifications for secure software development based on existing open source best practices.
The Open Source Community is Building Cybersecurity Processes for CRA Compliance
by Mike Milinkovich at April 02, 2024 07:00 AM
tl;dr – Apache Software Foundation, Blender Foundation, OpenSSL Software Foundation, PHP Foundation, Python Software Foundation, Rust Foundation, and Eclipse Foundation are jointly announcing our intention to collaborate on the establishment of common specifications for secure software development based on existing open source best practices.
In an effort to meet the real challenges of cybersecurity in the open source ecosystem, and to demonstrate full cooperation with, and to support the implementation of, the European Union’s Cyber Resilience Act (CRA), Apache Software Foundation, Blender Foundation, OpenSSL Software Foundation, PHP Foundation, Python Software Foundation, Rust Foundation, and Eclipse Foundation are announcing an initiative to establish common specifications for secure software development based on open source best practices.
This collaborative effort will be hosted at the Brussels-based Eclipse Foundation AISBL under the auspices of the Eclipse Foundation Specification Process and a new working group. As Europe’s largest open source foundation, which also supports a robust open specification process, the Eclipse Foundation is a natural home for this effort. Other code-hosting open source foundations, SMEs, industry players, and researchers are invited to join in as well. The starting point for this highly technical standardisation effort will be today’s existing security policies and procedures of the respective open source foundations, and similar documents describing best practices. The governance of the working group will follow the Eclipse Foundation’s usual member-led model but will be augmented by explicit representation from the open source community to ensure diversity and balance in decision-making. The deliverables will consist of one or more process specifications made available under a liberal specification copyright licence and a royalty-free patent licence.
The reasons for this collaboration extend beyond compliance. In an era where software, particularly open source software, plays an increasingly vital role in modern society, the need for reliability, safety, and security has steadily increased. New regulations, exemplified by the impending CRA, underscore the urgency for secure by design and robust supply chain security standards well before the new regulation comes into force in 2027.
While open source communities and foundations generally adhere to and have historically established industry best practices around security, their approaches often lack alignment and comprehensive documentation. The open source community and the broader software industry now share a common challenge: legislation has introduced an urgent need for cybersecurity process standards.
The CRA will lead to numerous standards requests from the Commission to the European Standards Organisations. And these are only the European requirements – additional demands from the US and other regions can be anticipated.
The CRA also creates a new type of economic actor – the “Open Source Software Steward”. It is in this context that we, as open source foundations, want to respond to the challenge of establishing common specifications for secure software development.
This challenge is compounded by the following:
- Today’s global software infrastructure is over 80% open source. The software stack that underpins any product with digital elements is typically built using open source software. As a result, it is fair to say that when we discuss the “software supply chain,” we are primarily, but not exclusively, referring to open source.
- Traditional standards organisations have had limited interactions with open source communities and the broader software/IT industry. To make matters more complicated, their governance models currently do not provide opportunities for open source communities to engage.
- Open source communities have a limited history of dealing with traditional standards organisations. To make matters more complicated, their resource constraints make it difficult for them to engage.
- Standards setting is typically a long process, and time is of the essence.
So while these new cybersecurity standards must be developed with the requirements of open source development processes and communities in mind, there is no clear path on how to do so in the time available. It is also important to note that it is similarly necessary that these standards be developed in a manner that also includes the requirements of proprietary software development, large enterprises, vertical industries, and small and medium enterprises.
Despite these challenges, a foundation for progress exists. The leading open source communities and foundations have for years developed and practised secure software development processes. These are processes that have often defined or set industry best practices around things such as coordinated disclosure, peer review, and release processes. These processes have been documented by each of these communities, albeit sometimes using different terminology and approaches. We hypothesise that the cybersecurity process technical documentation that already exists amongst the open source communities can provide a useful starting point for developing the cybersecurity processes required for regulatory compliance.
We hope that our specifications could inform the formal standardisation processes of at least one of the European Standards Organisations. Given the tight time horizon for implementation of the CRA, we believe that this immediate start will provide a constructive environment to host the technical discussions necessary for the stewards, contributors, and adopters of open source to meet the requirements set forth in these new regulations.
We invite you to join our collaborative effort to create specifications for secure open source development: Contribute your ideas and participate in the magic that unfolds when open source foundations, SMEs, industry leaders, and researchers combine forces to tackle big challenges. To stay updated on this initiative, sign up for our mailing list.
March 19, 2024
Visualizing Eclipse Collections after Twenty Years of Development
by Donald Raab at March 19, 2024 07:37 PM
It’s hard to see the forest when you keep walking among the trees.
![](https://cdn-images-1.medium.com/max/1024/1*TLko6FOsWlRYYXI2ZvhFbA.jpeg)
This year is the 20th year that I have been working on Eclipse Collections. To kick off the official 20th anniversary celebration in a technical blog, I wanted to create a fresh visualization of Eclipse Collections features to get new developers acquainted with this amazing library.
In a code base with many packages, many types, and over one million lines of code (including test code), it can be easy to get lost browsing while looking through files. There is an organized package structure to Eclipse Collections, but if you are new to the library, it may not be obvious where to get started. I’m leaving this mind map here, with some useful links to help folks find the things they might be looking for.
This blog may be the “Just getting started” guide some folks are looking for as they begin their journey of discovery. Eclipse Collections contains everything I ever wanted in a collections library for Java. I hope Eclipse Collections will be the same for many of you. My intention in writing this blog is for it to be a good reference for using the library in your development adventures. I plan to refer to it myself on my own continuing adventures over the next 5… 10… 15… maybe 20 years.
Good luck and enjoy your journey!
Interfaces
If you want to find the interfaces, you need to look at the eclipse-collections-api module. In this module you will find most of the parent interfaces, like RichIterable, PrimitiveIterable, and ParallelIterable. Multimap and PartitionIterable are located in two different packages. Eclipse Collections had a design goal of cleanly separating interface from implementation. We want developers to refer only to interfaces whenever possible. This module contains primarily interfaces. The one exception to this are collection factory classes, which are loaded with implementations dynamically.
In order to understand the symmetry of the triad of interfaces, which include an Iterable, Mutable, and Immutable version for each type (e.g. ListIterable, MutableList, ImmutableList), I recommend reading the following blog.
Rich, Lazy, Mutable, and Immutable Interfaces in Eclipse Collections
There is only one LazyIterable interface. LazyIterable is not a parent interface, as it extends RichIterable. LazyIterable substitutes co-variant overrides for any methods that should be lazy and return a LazyIterable. Any collection type, whether iterable, mutable or immutable can create a lazy view of itself by calling asLazy(), which will return a LazyIterable.
Data Structures
The data structures for Eclipse Collections are split between interfaces and implementation. The interfaces are located at the module and links I shared above. The implementations are located in the eclipse-collections module. The types you are probably most interested are the implementations of List, Set, Map, and Bag. The Mutable implementations of these types in Eclipse Collections are named FastList, UnifiedSet, UnifiedMap and HashBag. Most of the time you will never see these names in code, assuming you are using the interfaces MutableList, MutableSet, MutableMap, and MutableBag and create the collections using the Lists, Sets, Maps, and Bags factories.
Container Types
There are Object and primitive containers in Eclipse Collections. For Map types, there are Object/Object, primitive/primitive, Object/primitive, and primitive/Object combinations. There are also some thread-safe container types in Eclipse Collections including both concurrent and MultiReader containers.
The best way to learn about the specialized Data Structures and Container Types in Eclipse Collections is to check out the following blog series.
Blog Series: The missing Java data structures no one ever told you about
Algorithms
Eclipse Collections supports eager and lazy behaviors, as well as serial and parallel evaluation. The best way to understand the difference between eager and lazy behaviors is to read the following blog. You can also learn how the library evolved support from eager, to fused, to lazy over time.
The above blog only covers serial examples. If you would like to read more about the parallel capabilities in Eclipse Collections, the following blog is a great place to start.
The unparalleled design of Eclipse Collections
Java is missing a feature that I remember fondly from my days as a Smalltalk developer. The missing feature is a code organization tool known as Method Categories. Method categories allow you to group methods together in a class. The following are the categories I would use in Eclipse Collections types if a method categorization feature was available in Java.
✅ Enumerating
✅ Filtering
✅ Transforming
✅ Finding
✅ Testing
✅ Grouping
✅ Aggregating
✅ Converting
✅ Math
The following blog covers some of the features in the categories above. There are over 100 methods on the RichIterable parent interface, and even more in subtypes. Most of the methods fit in one of these categories.
Getting Started with Eclipse Collections — Part 4
Factories
Eclipse Collections includes factories for Mutable, Immutable, MultiReader and other more specialized types. The factory classes in Eclipse Collections are named by taking a type name (e.g., List) and pluralizing it (e.g. Lists). The following blogs will teach you everything you ever wanted to know about the collection factories in Eclipse Collections.
- As a matter of Factory — Part 1 (Mutable)
- As a matter of Factory — Part 2 (Immutable)
- As a matter of Factory — Part 3 (Method Chaining)
Twenty Years! Woo hoo!
In 2004, I didn’t think I would ever contribute anything to open source. I certainly didn’t think I would create something that would be open sourced from Goldman Sachs and used and contributed to by so many developers and projects. Here I am in 2024, celebrating 20 years of using and working on this amazing library. Crazy!
I think all that is left is to tell you how to download the library in your own projects. Of course, there is a blog for that.
Getting Started with Eclipse Collections — Part 1
Thank you for reading this blog, and for spending your valuable time learning some things about Eclipse Collections. I hope the library will be as useful and inspiring to you as it has been to me. If you find it useful and would like to contribute, we always welcome new contributors. If you don’t have a code contribution, but would like to advocate for and help others discover cool features in the library, then write a blog or an article. I keep a running list of articles about Eclipse Collections updated on the GitHub wiki linked below.
Enjoy!
I am the creator of and committer for the Eclipse Collections OSS project, which is managed at the Eclipse Foundation. Eclipse Collections is open for contributions.
Jakarta EE Developer Survey 2024
by Jacob Harris at March 19, 2024 01:25 PM
The 2024 Jakarta EE Developer Survey is now open! Through this annual survey, we want to gather valuable insights into the needs, priorities, and requirements of the enterprise Java developer community.
March 13, 2024
WTP 3.33 Released!
March 13, 2024 02:00 PM
March 12, 2024
Reminder: Eclipse Theia Community Call March 14th, 2024
by John Kellerman at March 12, 2024 03:52 PM
The Eclipse Theia community is a dynamic and expanding ecosystem, reflecting the dedicated efforts and enthusiasm of its members. The Theia Community Call is an open forum intended to provide updates on Theia, foster discussion within the ecosystem, and engage the community of Theia adopters, contributors, and users. This call presents an valuable opportunity to stay informed about the latest in Theia, contribute to its ecosystem, and partake in discussions with fellow community members.
Why Attend?
The Theia Community Call serves as an important venue for:
- Gaining comprehensive updates on Theia and its surrounding ecosystem.
- Participating in discussions about the project's progress, challenges, and opportunities.
- Offering suggestions and agenda items, thereby contributing to Theia's future direction.
Your involvement and feedback play a vital role in Theia's ongoing development. Whether you are deeply involved in the project or have a budding interest, your participation is greatly welcomed and appreciated.
Meeting Details
- Date: March 14th, 2024
- Time: 4pm Central European Time (CET)
- Location: Zoom Meeting
- Meeting ID: 820 4658 7932
- Passcode: 117021
Agenda Highlights
- Community Update by Jonas: An in-depth update on the most recent developments and releases within the Theia community.
How to Contribute
We encourage the community to actively contribute to the agenda. If you have topics, questions, or discussions in mind that you believe would benefit the community, please propose your ideas by initiating a [discussion](https://github.com/eclipse-theia/theia/discussions) and tagging @JonasHelming. Your insights and contributions are essential for a diverse and enriching conversation.
Navigating the IoT & Edge Landscape: Insights from the 2023 Commercial Adoption Survey Report
by Clark Roundy at March 12, 2024 01:42 PM
We are excited to introduce the much-anticipated fifth edition of the Eclipse Foundation’s annual IoT & Edge Commercial Adoption Survey Report. The latest findings shed light on some of the shifts within the industry that unfolded over the past year, and how certain trends have persisted. Let’s take a look at a few of the key takeaways and explore what they mean for the future of IoT and edge computing:
A Noteworthy Rise in IoT Adoption
The numbers speak for themselves – in 2023 there was a remarkable 11% increase in IoT adoption, with 64% of respondents now deploying IoT solutions. This surge signals a growing recognition of the value and potential that IoT technologies offer across various industries. Moreover, an additional 23% are gearing up to embrace IoT, with plans to deploy within the next 12-24 months.
Steady Adoption, Anticipated Acceleration in Edge Computing
While IoT adoption demonstrated healthy growth, the adoption rate of edge computing remained steady year-over-year at 33%. Nevertheless, it would seem that an adoption surge is on the horizon, with 30% planning deployments within the next 24 months. Meanwhile, an additional 27%, are evaluating the potential use of edge computing platforms, while only 10% remain on the sidelines. This all points to organisations taking a cautious but optimistic approach, with an anticipated acceleration of edge technology adoption for enhanced data processing and analysis closer to the source. Machine learning at the edge is a possible driver here.
A Trend Towards Larger Financial Commitments
Confidence in IoT and edge technologies is on the rise, reflected in a notable shift towards higher investments. In 2023, 17% reported spending between $1-10 million, more than doubling the percentage from 2022, and projections show this growing to 23% in 2024. Furthermore, 5% anticipate spending over $10 million, indicating a trend towards substantial financial commitments in these domains.
Deployments are Scaling Up
The scale of IoT and edge deployments is also evolving, with 10% of deployments now consisting of 50,000 or more devices. This shift towards larger deployments is accompanied by an almost equal mix between greenfield and brownfield implementations, indicating diverse approaches to integrating new and existing technologies.
Organisations Recognize the Strategic Value of IoT & Edge Tech
A notable development in 2023 is the increased influence of C-suite executives in driving decisions related to IoT and edge investments. Nearly half of participating organisations report that their investment choices are predominantly driven by top-level executives, a substantial rise from 38% in 2022. This trend underscores the strategic importance of IoT and edge technologies in shaping business directions and outcomes.
The Rising Tide of Open Source
Open source technologies have taken centre stage in the deployment of IoT and edge solutions, with a whopping 75% of organisations actively incorporating open source into their plans. This overwhelming embrace reflects the critical role open source plays in fostering innovation, flexibility, and collaboration in the development of IoT and edge solutions.
As organisations increasingly recognise the value of these technologies, the trends toward larger deployments, higher investments, and the strategic involvement of the C-suite are likely to continue. Moreover, the embrace of open source technologies signifies continual viability of open, collaborative, and innovative approaches to technology deployment. To learn more about open source in IoT and edge computing, explore our industry collaborations like Eclipse IoT, Sparkplug, and the Edge Native special interest group (SIG).
While these are some of the high level takeaways from this year’s survey, I encourage you to dive into the report yourself. These insights aren't just reflections of our past, but serve as a guide for the future of IoT and edge computing. Let’s keep the conversation going, collaborate often, and collectively continue to shape the path forward.
The Eclipse Foundation Unveils 2023 IoT and Edge Commercial Adoption Survey Insights
by Jacob Harris at March 12, 2024 10:45 AM
BRUSSELS – 12 March 2024 – The Eclipse Foundation, one of the world’s largest open source foundations, today announced the availability of its 2023 IoT and Edge Commercial Adoption Survey Report, a comprehensive analysis derived from responses of over 1067 professionals in the IoT and edge computing domain. Conducted online from 4 April to 5 July 2023, the survey offers valuable insights into the evolving IoT and edge computing ecosystems by identifying the requirements, priorities, and challenges faced by organisations that deploy and use commercial solutions, including those based on open source technologies.
“Consistent with our previous surveys, the continuous growth and adoption of IoT and edge computing remains evident. The data reflects a notable increase in the number of managed devices and larger investments, indicative of a scale-up in deployments,” said Mike Milinkovich, executive director of the Eclipse Foundation. “Particularly notable is that the C-suite significantly influences decision-making for IoT and edge investments. This underscores the strategic value that businesses place on solutions based on open technologies in real-world deployments. Open source components are recognised as vital enablers of success.”
Survey participants represent a broad range of industries and job functions. Six of the key takeaways from the survey data include:
- IoT Adoption Surged in 2023: 64% of respondents are now deploying IoT solutions, up from 53% in 2022. An additional 23% plan to deploy within 12-24 months. Less than 5% have no IoT deployment plan.
- Edge Computing Adoption Holds Steady, Acceleration Anticipated: Adoption of edge computing solutions remains at 33% (same as 2022), with an additional 30% indicating plans to deploy within the next 24 months. 27% are still evaluating edge platforms, while only 10% have no plans to deploy edge solutions.
- Rising Investments Signal Scale-Up in Production Deployments: 17% of respondents spent between $1-10M in 2023 (more than double that of 2022), growing to 23% in 2024. 5% anticipate spending over $10M. This trend indicates a transition from proof-of-concept to ROI-focused deployments.
- Growing Number of IoT & Edge Assets per Deployment: Deployments of fewer than 1K managed assets will remain steady or decline, while larger deployments are on the rise, with an impressive 10% of deployments consisting of 50K or more devices. Regarding asset implementation, the mix between greenfield and brownfield is almost equal.
- IoT is Increasingly Strategic with the C-Suite Driving Investment Decisions: 49% of organisations reveal that the C-suite predominantly drives decisions. This marks a significant increase from the 38% reported in 2022, indicating a growing influence of top-level executives in shaping investment choices within the realm of IoT and edge technologies.
- 75% of Organisations Surveyed Embrace Open Source in IoT and Edge: 75% of organisations are actively incorporating open source into their deployment plans. The widespread use of IoT and edge solutions based on open source technologies highlights how open source has become key in shaping today's technology landscape.
The report also delves into industry-specific insights on IoT and edge adoption, highlights the primary concerns and challenges encountered by commercial adopters, and provides actionable recommendations for navigating the evolving landscape. To find out more, download the 2023 IoT & Edge Commercial Adoption Survey Report.
The IoT and Edge Commercial Adoption Survey is sponsored by the Eclipse IoT and Sparkplug Working Groups. It serves as a valuable complement to the annual IoT Developer Survey, a vital source of strategic insights from the development front lines. The Eclipse IoT community represents one of the largest IoT-focused open source collaborations in the world, with 45 members and over 50 projects. Eclipse IoT projects have been broadly adopted by leading organisations across a variety of verticals to deliver commercial IoT and edge-based solutions and services.
To learn more about how to get involved with the Eclipse IoT, Sparkplug, or other Eclipse Foundation industry collaborations, visit the Eclipse Foundation membership page. Members benefit from a broad range of services, including exclusive access to detailed industry research findings, marketing assistance, and expert open source governance.
For further IoT & edge related information, please reach us at:
Moreover, mark your calendars for the inaugural Open Code Experience (OCX) by the Eclipse Foundation, dedicated to open source software development. Join us 22-24 October 2024 in Mainz, Germany.
About the Eclipse Foundation
The Eclipse Foundation provides our global community of individuals and organisations with a business-friendly environment for open source software collaboration and innovation. We host the Eclipse IDE, Adoptium, Software Defined Vehicle, Jakarta EE, and over 415 open source projects, including runtimes, tools, specifications, and frameworks for cloud and edge applications, IoT, AI, automotive, systems engineering, open processor designs, and many others. Headquartered in Brussels, Belgium, the Eclipse Foundation is an international non-profit association supported by over 360 members. Visit us at this year’s Open Code Experience (OCX) conference on 22-24 October 2024 in Mainz, Germany. To learn more, follow us on social media @EclipseFdn, LinkedIn, or visit eclipse.org.
Third-party trademarks mentioned are the property of their respective owners.
###
Media contacts:
Schwartz Public Relations for the Eclipse Foundation, AISBL (Germany)
Stephanie Brüls / Susanne Pawlik
Sendlinger Straße 42A
80331 Munich
EclipseFoundation@schwartzpr.de
+49 (89) 211 871 – 64 / -35
Nichols Communications for the Eclipse Foundation, AISBL
Jay Nichols
+1 408-772-1551
514 Media Ltd for the Eclipse Foundation, AISBL (France, Italy, Spain)
Benoit Simoneau
M: +44 (0) 7891 920 370
March 07, 2024
Eclipse Theia 1.47 Release: News and Noteworthy
by Jonas, Maximilian & Philip at March 07, 2024 12:00 AM
We are happy to announce the Eclipse Theia 1.47 release! The release contains 64 merged pull requests and we welcome four new contributors. In this article we will highlight some selected improvements …
The post Eclipse Theia 1.47 Release: News and Noteworthy appeared first on EclipseSource.
March 06, 2024
2024 Eclipse Foundation Board Election Results
by Gesine Freund at March 06, 2024 02:00 PM
2024 Eclipse Foundation Board Election Results
The Eclipse Foundation would like to thank everyone who participated in this year’s election process and is pleased to announce the results of the 2024 Eclipse Foundation Contributing Member and Committer Member elections for representatives to the foundation’s board. These positions are a vitally important part of the Eclipse Foundation's governance.
Hendrik Ebbers, Johannes Matheis are returning, and Angelo Corsaro will be joining as the Contributing Member representatives. Ed Merks, Matthew Khouzam, and Shelley Lambert will all be returning as the Committer representatives. Congratulations! We're looking forward to working with them on the Board, effective April 1, 2024.
We thank George Adams, Torkild Ulvøy Resheim, Thomas Mäder, and Carlo Piana for running in this year’s election.
We also thank Gunnar Wagenknecht for his many years of service to the Eclipse Foundation Board.
March 05, 2024
Eclipse Cloud DevTools Digest - January and February, 2024
by John Kellerman at March 05, 2024 05:50 PM
Eclipse Cloud DevTools Contributor Award for 2023 goes to EclipseSource and TypeFox
The Eclipse Cloud DevTools Contributor Award for the year 2023 was to two remarkable companies, EclipseSource and TypeFox, in acknowledgment of their enormous, continuous, strategic, and sustainable contributions to the Eclipse Cloud DevTools ecosystem.
Adopter Story: Code RealTime
In an earlier article, I wrote about Code RealTime, an innovative tool for creating stateful, event-driven real time applications in C++, created by HCL and IBM and using the strengths of the Eclipse Cloud DevTools open source ecosystem, including Eclipse Theia and Eclipse GLSP.
Languim
![Langium](https://blogs.eclipse.org/sites/default/files/styles/large/public/2024-03/langium.png?itok=jVLYLdfj)
Markus Rudolph of TypeFox provided a nice, instructive article on atting a React webview using Langium to a VS Code extension, resplendent with code examples.
Unveiling the Power of Open VSX
![open-vsx.org](https://blogs.eclipse.org/sites/default/files/styles/large/public/2023-05/open-vsx_0.png?itok=hovEH9pW)
In this article we discuss the success we've seen in the extensions hosted at Open VSX, an open source registry for VS Code extensions, providing a decentralized and community-driven alternative to the Visual Studio Code Marketplace.
Cloud DevTools Articles from EclipseSource
Jonas, Maximilian, and Philip of EclipseSource were busy in January and February with a series of informative articles about building and running cloud based IDEs. The article on AI integration for tools and IDEs is an especially worthy read.
- Why Every Tool and IDE Project Should Care About AI Integration
- The Eclipse Theia Project Update 2023
- Real-time Collaboration on Diagrams with Eclipse GLSP
- Building Custom C/C++ Tools: CDT Cloud and Eclipse Theia in Action
- Accessibility in Diagram Editors with Eclipse GLSP
- Running Eclipse Theia without a backend
- Hosting IDEs and tools online - lessons learned
- CDT Cloud Blueprint: Tracing with TraceCompass Cloud
- The Choice of an IDE and Tool Platform: Eclipse Theia vs. Code OSS
GLSP 2.0!
![GLSP 2.0](https://eclipsesource.com/blogs/2024/01/31/eclipse-glsp-2-elevating-web-based-diagram-editors/images/helper-lines.gif)
Jonas, Maximilian & Philip announced GLSP 2.0, a major release. GLSP (Graphical Language Server Platform) is a framework for web-based diagram editors. Enhancements in 2.0 include improved JSON model support, helper lines for better element alignment, reconnectable server connections, ghost element rendering, front-end only support, among many other things
JKube 1.16 is Available
The JKube team announced the availability of 1.16. Enhancements included, among other things, a Helm Lint feature, support for Kube Recommended labels and updated base images.
The Eclipse Theia Community Release 2024-02
Jonas, Maximilian & Philip also, in this article, tell us about their latest Theia Community Release. 2024-02 includes a beta release of Theia IDE, portable mode support, and number of other enhancements.
Other Recent Releases
Cloud Tool Time Webinars
We are now scheduling Cloud Tool Time webinars for 2023. Be sure to Sign up now to get on the calendar and let us help tell your story. You can see past sessions on our Youtube channel.
Eclipse Cloud DevTools Projects
![Eclipse Cloud DevTools](https://blogs.eclipse.org/sites/default/files/2023-07/Cloud%20DevTools.png)
Explore the Eclipse Cloud DevTools ecosystem! Check out our projects page to find out more about open source innovation for cloud IDEs, extension marketplaces, frameworks and more.
Getting Listed on the Cloud DevTools Blog
If you are working with, or on, anything in the Cloud DevTools space, learn how to get your writings posted in our blog section.
Eclipse Cloud DevTools Contributor Award: Marc Dumais for Simplifying License Management
by John Kellerman at March 05, 2024 05:48 PM
The Eclipse Cloud Developer Tools (ECDT) community is happy to announce Marc Dumais as the recipient of the Contributor Award for the first quarter of 2024. This is in recognition of Marc's outstanding contributions that have significantly simplified third-party license checks across ECDT projects, contributing to enhanced project integrity and compliance.
Marc significantly simplified the approach to third-party license (3PP) checks. Traditionally, these checks have been a cumbersome and manual necessity, often slowing down project development. Marc created a modular, more configurable wrapper to dash-licenses, now available as the npm package @eclipse-dash/nodejs-wrapper. This tool, developed under the Eclipse Foundation's technology.dash project, makes license compliance checks more accessible and streamlined for projects within and beyond the ECDT ecosystem. For those interested in the technical intricacies of this contribution, the integration details and its application can be explored in depth here.
This contribution by Marc transcends the code; it exemplifies the spirit of collaboration and innovation that the ECDT community holds dear. By not only addressing a need within a project he was directly involved in, but also championing the solution for wider adoption, Marc has significantly eased the burden of license compliance for numerous projects within our community.
Marc Dumais is no stranger to the ECDT ecosystem. His long-standing commitment and versatile contributions across several projects, including Eclipse Theia, TraceCompass Cloud and CDT Cloud, have been instrumental in the shaping and evolution of the ecosystem.
We extend our warmest congratulations to Marc Dumais for this well-deserved recognition!
This Eclipse Cloud DevTools contributor award is sponsored by EclipseSource, providing consulting and implementation services for web-based tools, Eclipse GLSP, Eclipse Theia, and VS Code.
Langium 3.0 is Released!
March 05, 2024 12:00 AM
March 04, 2024
Join Us: Reminder for the Eclipse Theia Community Call! March 14th
by Jonas, Maximilian & Philip at March 04, 2024 12:00 AM
As the date approaches, we want to extend another warm invitation to the Eclipse Theia Community Call scheduled for March 14th, 2024, 4pm CET. It’s a great opportunity to dive deep into the world of …
The post Join Us: Reminder for the Eclipse Theia Community Call! March 14th appeared first on EclipseSource.
March 02, 2024
Visualizing My Java Champion Journey
by Donald Raab at March 02, 2024 04:34 AM
Mind mapping memories and metrics from the before and after times.
![](https://cdn-images-1.medium.com/max/1024/1*n4_3sw-AbpQa0opjT7oQIQ.png)
The Journey Continues
Last year I captured a blog with a mind map including the things I believe had contributed to me being selected as a Java Champion in 2018. This week I captured a mind map of everything I have done in similar categories since 2018. There was some missing time in the conference talks due to the pandemic, but I made up some lost ground last year with four conference talks. I spoke at Devnexus 2023, QCon New York 2023, Devoxx Greece 2023, Devoxx Belgium 2023. I’m not going to write too much text in this blog. I will just leave the before and after Java Champion mind maps for comparison, along with a photo from my first talk as a Java Champion from Oracle CodeOne 2018.
Before Java Champion
![](https://cdn-images-1.medium.com/max/1024/1*dlziDJI2YYWCVMIlGUAGdQ.png)
After Java Champion
![](https://cdn-images-1.medium.com/max/1024/1*byfH1ArI1XqKfEfutnT2eA.png)
Mapping the Memories
One benefit I have seen out of this activity is quantifying the resulting impact on the communities and initiatives I have been involved with over time. I will try to capture an update every few years so I can have snapshots of how my journey is evolving.
It was very nostalgic for me, going back through old photos and recalling things that can be easily forgotten. I am including a photo below from Oracle CodeOne 2018, which was the first conference I spoke at where I was able to add Java Champion to my speaker bio. Some of the benefits of speaking at and attending technical conferences are the amazing people you get to meet, and the global network you can grow if you invest some time and energy in building connections. It helps to find good places to meet for coffee before, during and after a conference.
![](https://cdn-images-1.medium.com/max/1024/1*1e4qNVBjZ7XhpQjhD9xDcg.png)
Thank you for reading, and best of luck on your journeys!
I am the creator of and committer for the Eclipse Collections OSS project, which is managed at the Eclipse Foundation. Eclipse Collections is open for contributions.
February 27, 2024
Access Ditto Things from an Asset Administration Shell
February 27, 2024 12:00 AM
Integrating digital representations of devices into an IT infrastructure is a recurring task in different domains and application areas. To address this challenge in Industry 4.0 scenarios along the supply chain, the community specified the Asset Administration Shell within the Industrial Digital Twin Association (IDTA) to handle all kinds of information of a physical asset over its lifecycle.
Eclipse Ditto provides a backend for handling such device data as Things and takes care of a number of general tasks that are otherwise easy to be done wrong, such as handling device connectivity over different protocols or state management. Therefore, it is promising to use the benefits of Eclipse Ditto for populating an AAS infrastructure when the devices already communicate with an existing instance of Eclipse Ditto.
In this post we want to share our solution and learnings from setting up an AAS infrastructure based on Eclipse Basyx and Eclipse Ditto as a source for device state.
Figure 1: User-device interaction via BaSyx and Ditto
Background
We start with some background on the AAS and Eclipse Basyx. If you are allready familiar with both, it is safe to skip this section.
Asset Administration Shell
The Asset Administration Shell (AAS) is a standardization effort of the Industrial Digital Twin Association (IDTA) that originated from the Platform Industry 4.0 (I4.0) (AAS Spec Part I; AAS Spec Part II).
An AAS is a digital representation of a physical asset and consists of one or more submodels. Each submodel contains a structured set of submodel elements. Submodels, as well as their submodel elements, can either be a type or an instance. The AAS metamodel defines the possible elements for modeling an AAS like Asset, AssetAdminstrationShell (AAS), Submodel (SM), SubmodelElementCollection (SMEC), Property, and SubmodelElement (SME). You can find further details here and here.
A user who wants to interact with an AAS over HTTP follows the sequence of service calls depicted in Figure 2. The flow starts by requesting an AAS ID from the AAS discovery interface based on a (local) specific asset ID or a global asset ID. An example of such an asset ID is a serial number written on the device. With the AAS ID, the user retrieves the endpoint for the AAS through the AAS registry interface. The user then requests the SM ID from that AAS endpoint and uses this SM ID to get the SM endpoint from the SM Registry. From that SM endpoint, the user can request the SME, which contains the required value.
Figure 2: Sequence of data flow through AAS infrastructure
If you want to dig deeper into the specifics of the AAS, consult the AAS Reading Guide, which helps the interested reader to navigate through the available material.
Eclipse BaSyx
Eclipse BaSyx is an open-source project hosted by the Eclipse Foundation providing components to deploy an Industry 4.0 middleware. Apart from other features, Eclipse BaSyx provides several easy-to-use off-the-shelf components to realize an AAS infrastructure:
You can pull them from Docker Hub or follow the instructions to build them yourself.
In this post, we mainly work with the AAS Server Component and the Registry Component.
Architectural Considerations
Making Eclipse Ditto Things available in an AAS infrastructure, in our case from the Eclipse Basyx project, boils down to making Thing data available as Submodels of an AAS accessible via the AAS Interface.
We see three approaches to achieve this:
- BaSyx AAS SM server pulls the current state from Eclipse Ditto via a wrapper around Eclipse Ditto. This approach requires the creation of a custom AAS infrastructure around Eclipse Ditto without the chance of reusing existing components of the Eclipse Basyx project. The Eclipse Ditto project followed a comparable approach to support Web of Things (WoT) definitions, which is another specification to integrate IoT devices from different contexts and align their utilized data model. Ditto now allows the generation of new Things based on a WoT Thing Description.
- BaSyx AAS SM server pulls the current state from Eclipse Ditto via a bridge component, which Eclipse Basyx already provides. To integrate the bridge, the BaSyx SM-server component has a delegation feature, where the user can configure an SME with an endpoint to which the server delegates incoming requests. The configured endpoint can reference the bridge that then retrieves the actual data from Ditto and applies transformation logic.
- Eclipse Ditto pushes the latest updates to a BaSyx SM server. For this approach, we configure Eclipse Ditto to notify the BaSyx SM server about any change to the relevant Things. During the creation of the notification message, Ditto applies a payload mapping to transform the data into the AAS format. The BaSyx SM server then stores the received submodel element and responds directly to the requests by the users.
Figure 3: Push approach sequence
We follow the push approach here because it treats the AAS infrastructure as a blackbox and almost all configuration happens within Eclipse Ditto.
Mapping of Data Models
Eclipse Ditto and Eclipse Basyx work with different data structures and conceptual elements to represent device and asset data. Since we want to convert between these data models, we need to come up with a mapping between them.
Eclipse Ditto | Asset Administration Shell |
---|---|
Namespace | Asset Administration Shell |
Thing | — |
Features | Submodel |
Property | Submodel Element |
Attribute | Submodel Element |
Table 1: Concept mapping from Eclipse Ditto to the AAS
We map a Ditto Namespace
to a single AAS. An AAS holds multiple SMs, and not all of these SMs necessarily have counterparts in Ditto. We thus treat a Thing
as an opaque concept and do not define an explicit mapping for a Thing
but map each feature
to one SM.
property
and Attribute
are mapped to SMEs.
By that, it is possible to have more than one Thing organized in one AAS. This can especially be useful if an AAS organizes complex equipment with different sensors and actuators, which belong together but are organized in multiple Things.
Integration Steps
With the more theoretical details completed, we can now turn to the actual implementation and describe what is required to integrate Eclipse Ditto into an AAS infrastructure of Eclipse BaSyx.
Prerequisites
- Running instance of Eclipse Ditto
- Running instance of Eclipse BaSyx AAS Server
- Running instance of Eclipse BaSyx AAS Registry
Those three instances must be available and a network connection must exist between them.
In the code snippets below, we use placeholders for the URLs of Ditto as well as BaSyx.
So, you need to replace <ditto-instance-url>
, <basyx-server-instance-url>
, <basyx-registry-instance-url>
with the proper URLs in your environment.
For our setup, we used version 3.0.1 for Eclipse Ditto and version 1.4.0 for Eclipse BaSyx.
Please note that the Ditto demo instance, does not work for the described setup and requests because it does not allow to directly invoke the /devops
endpoints through which we later configure connections.
Payload Mappers from Ditto to BaSyx
Let us assume a device with a sensor named machine:sensor
that is capable of measuring temperature values.
This device may send sensor data to an Eclipse Ditto instance as a Ditto Protocol message Ditto Protocol message:
{
"topic": "machine/sensor/things/twin/commands/modify",
"headers": {},
"path": "/features/temperature/properties/value",
"value": 46
}
Listing 1: Ditto Protocol message for the Thing machine:senor
If the device uses another message format, you can find more details on how to map it to a Ditto Protocol message.
After an update to a Thing, we want Ditto to map the information to an AAS-conforming representation and forward this via an outbound connection to an AAS server. The task in Eclipse Ditto is to define payload mappers for these transformations in accordance with the mapping from Mapping of Data Models. Ditto allows the usage of JavaScript to create the mappers. We thus configure connections in Ditto to the BaSyx components, where we filter for the relevant changes to a Thing and then trigger the respective mapper.
We need to implement the following mappers:
- Creation of an AAS triggered by creation of new
namespaces
- Creation of a SM triggered by creation of
feature
- Creation and update of an SME triggered by creation and modification of a
property
Map from Thing Creation to AAS Creation
The next snippet performs a mapping from a Thing to an AAS. It gets executed every time a Thing is created.
function mapFromDittoProtocolMsg(
namespace,
name,
group,
channel,
criterion,
action,
path,
dittoHeaders,
value,
status,
extra
) {
let headers = dittoHeaders;
let textPayload = JSON.stringify({
conceptDictionary: [],
identification: {
idType: 'Custom',
id: namespace
},
idShort: namespace,
dataSpecification: [],
modelType: {
name: 'AssetAdministrationShell'
},
asset: {
identification: {
idType: 'Custom',
id: namespace + '-asset'
},
idShort: namespace + '-asset',
kind: 'Instance',
dataSpecification: [],
modelType: {
name: 'Asset'
},
embeddedDataSpecifications: []
},
embeddedDataSpecifications: [],
views: [],
submodels: []
});
let bytePayload = null;
let contentType = 'application/json';
return Ditto.buildExternalMsg(
headers, // The external headers Object containing header values
textPayload, // The external mapped String
bytePayload, // The external mapped byte[]
contentType // The returned Content-Type
);
}
Listing 2: Payload mapping that creates a new AAS if a new Thing appears
As we map the Thing namespace to an AAS we only use the namespace
, which is the first part of the ID of a Thing.
For example machine
in our machine:sensor
example Thing (Listing 1).
More precisely, the mapping creates a representation of an AAS with the ID namespace
and returns a new message with this text as payload. The Ditto connectivity service then runs the mapping and pushes the new message to the BaSyx AAS server to create the described AAS.
For example, whenever a Thing with the ID machine:sensor
is created, an AAS with the ID machine
will be created.
Map from Feature creation to Submodel creation
The next mapper creates an AAS submodel and will be executed every time a new feature is created for a Thing.
function mapFromDittoProtocolMsg(
namespace,
name,
group,
channel,
criterion,
action,
path,
dittoHeaders,
value,
status,
extra
) {
let feature_id = path.split('/').slice(2);
let headers = dittoHeaders;
let textPayload = JSON.stringify(
{
parent: {
keys: [
{
idType: 'Custom',
type: 'AssetAdministrationShell',
value: namespace,
local: true
}
]
},
identification: {
idType: 'Custom',
id: name+'_'+feature_id
},
idShort: name+'_'+feature_id,
kind: 'Instance',
dataSpecification: [],
modelType: {
name: 'Submodel'
},
embeddedDataSpecifications: [],
submodelElements: []
}
);
let bytePayload = null;
let contentType = 'application/json';
return Ditto.buildExternalMsg(
headers, // The external headers Object containing header values
textPayload, // The external mapped String
bytePayload, // The external mapped byte[]
contentType // The returned Content-Type
);
}
Listing 3: Payload mapping that creates a new AAS submodel if a new Feature appears
Besides namespace
, this mapper uses the parameters name
and path
from the Ditto Protocol message.
The name
represents the second part of the Thing-ID, e.g., sensor
from our machine:sensor
example Thing (Listing 1).
The path
describes the part of the Thing whose change triggered the processed Ditto Protocol message.
It may include the feature ID of the Thing or the whole path of the affected property of the Thing,
but it could be only /
after the creation of a Thing. In our example message above,
the path
is /features/temperature/properties/value
.
The mapping function extracts the ID of the feature from the parameter path
and uses this together with the name
of the Thing to build the ID of the corresponding AAS submodel. For example, whenever the feature temperature
of a Thing called machine:sensor
is created, an AAS submodel with the ID sensor_temperature
in the AAS machine
will be created.
Similarly to the AAS creation mapping, the listed function returns a new message with a custom text payload. Below, we will create a connection so that this payload gets pushed to the BaSyx AAS server to trigger the creation of an AAS submodel there.
Map from Property Update to Submodel Update
The next mapper creates an AAS submodel element. we use it in the connection for every modification of a property in a Thing.
function mapFromDittoProtocolMsg(
namespace,
name,
group,
channel,
criterion,
action,
path,
dittoHeaders,
value,
status,
extra
) {
let property_id = path.split('/').slice(3).join('_');
let feature_id = path.split('/').slice(2,3);
let headers = dittoHeaders;
let dataType = typeof value;
dataType = mapDataType(dataType)
function mapDataType(dataType) {
switch (dataType) {
case 'undefined':
return 'Undefined';
case 'boolean':
return 'boolean';
case 'number':
return 'int';
case 'string':
return 'string';
case 'symbol':
return 'Symbol';
case 'bigint':
return 'BigInt';
case 'object':
return 'string';
case 'function':
return 'Function';
default:
return 'Unknown';
}
}
let textPayload = JSON.stringify(
{
parent: {
keys: [
{
idType: 'Custom',
type: 'Submodel',
value: name+'_'+feature_id,
local: true
}
]
},
idShort: property_id,
kind: 'Instance',
valueType: dataType,
modelType: {
name: 'Property'
},
value: value
}
);
let bytePayload = null;
let contentType = 'application/json';
return Ditto.buildExternalMsg(
headers, // The external headers Object containing header values
textPayload, // The external mapped String
bytePayload, // The external mapped byte[]
contentType // The returned Content-Type
);
}
Listing 4: Payload mapping that modifies an AAS submodel element if a property is changed
The mapper extracts the feature_id
and the property_id
from the path
, which is only possible if the parameter path
includes the property_id
. So, in the configuration of the connection, we have to ensure that this mapper only runs for the right messages.
Moreover, we can access the value
of the modified property
, which will be set as value
in the submodel element from the textPayload
output.
For example, if a message updates the path
: /features/temperature/properties/value
in the Thing machine:sensor
, the submodel element with the ID properties_value
in the submodel sensor_temperature
will be updated with the new temperature as value
.
We update a submodel element instead of the whole submodel if an existing Thing changes because the mapper only has access to the changed property of the Thing and no information about the other properties. Therefore, submodel elements, which may already be part of the submodel due to previous updates, would implicitly be dropped. With our approach, we preserve the existing properties and only modify the updated properties.
Create a Connection to the BaSyx AAS Server
To apply the introduced mappers, we configure a new Ditto connection to a BaSyx AAS server. The listings below show the respective HTTP calls using curl to configure this connection.
The JavaScript mappers from above are part of piggybackCommand.connection.mappingDefinitions
in mappingforShell
, mappingforSubmodel
and mappingforSubmodelElement
.
In the example, we use the placeholder <ditto-instance-url>
for the used Ditto instance. You need to adjust to the valid URL of your environment.
We assume you have access rights to the Ditto Devops Commands credentials in the used instance (username: devops
, password: `foobar is the default).
You can change the password by setting the environment variable DEVOPS_PASSWORD in the gateway service.
Alternatively, an already existing password can be obtained and stored as an environment variable using the following command:
export DEVOPS_PWD=$(kubectl --namespace ditto get secret my-ditto-gateway-secret -o jsonpath="{.data.devops-password}" | base64 --decode)
Please be aware that this command assumes Ditto has been deployed within a namespace ditto
.
Finally, you adjust the parameter piggybackCommand.connection.uri
with the URL of the running BaSyx server to which Ditto should have network connectivity.
As HTTP requires us to replace certain characters for proper processing, we encode the payload by escaping certain characters and removing the line breaks.
We replaced newlines with \n
and '
with '"'
.
curl -X POST -u devops:foobar -H 'Content-Type: application/json' --data-binary '{
"targetActorSelection": "/system/sharding/connection",
"headers": {
"aggregate": false
},
"piggybackCommand": {
"type": "connectivity.commands:createConnection",
"connection": {
"id": "basyxserver-http-connection",
"connectionType": "http-push",
"connectionStatus": "open",
"uri": "<basyx-server-instance-url>:4001",
"failoverEnabled": true,
"mappingDefinitions": {
"mappingforShell": {
"mappingEngine": "JavaScript",
"options": {
"outgoingScript": "function mapFromDittoProtocolMsg(namespace, name, group, channel, criterion, action, path, dittoHeaders, value, status, extra) {\n let headers = dittoHeaders;\n let textPayload = JSON.stringify({\n conceptDictionary: [],\n identification: {\n idType: '"'Custom'"',\n id: namespace\n },\n idShort: namespace,\n dataSpecification: [],\n modelType: {\n name: '"'AssetAdministrationShell'"'\n },\n asset: {\n identification: {\n idType: '"'Custom'"',\n id: namespace + '"'-asset'"'\n },\n idShort: namespace + '"'-asset'"',\n kind: '"'Instance'"',\n dataSpecification: [],\n modelType: {\n name: '"'Asset'"'\n },\n embeddedDataSpecifications: []\n },\n embeddedDataSpecifications: [],\n views: [],\n submodels: []\n });\n let bytePayload = null;\n let contentType = '"'application/json'"';\n return Ditto.buildExternalMsg(headers, textPayload, bytePayload, contentType);}"
}
},
"mappingforSubmodel": {
"mappingEngine": "JavaScript",
"options": {
"outgoingScript": "function mapFromDittoProtocolMsg(namespace, name, group, channel, criterion, action, path, dittoHeaders, value, status, extra) {\n \n let feature_id = path.split('"'/'"').slice(2);\n let headers = dittoHeaders;\n let textPayload = JSON.stringify(\n {\n parent: {\n keys: [\n {\n idType: '"'Custom'"',\n type: '"'AssetAdministrationShell'"',\n value: namespace,\n local: true\n }\n ]\n },\n identification: {\n idType: '"'Custom'"',\n id: name+'"'_'"'+feature_id\n },\n idShort: name+'"'_'"'+feature_id,\n kind: '"'Instance'"',\n dataSpecification: [],\n modelType: {\n name: '"'Submodel'"'\n },\n embeddedDataSpecifications: [],\n submodelElements: []\n }\n\n );\n let bytePayload = null;\n let contentType = '"'application/json'"';\n return Ditto.buildExternalMsg(headers, textPayload, bytePayload, contentType);}"
}
},
"mappingforSubmodelElement": {
"mappingEngine": "JavaScript",
"options": {
"outgoingScript": "function mapFromDittoProtocolMsg(namespace, name, group, channel, criterion, action, path, dittoHeaders, value, status, extra) {\n let property_id = path.split('"'/'"').slice(3).join('"'_'"');\n let feature_id = path.split('"'/'"').slice(2,3);\n let headers = dittoHeaders;\n let dataType = typeof value;\n dataType = mapDataType(dataType)\n\n function mapDataType(dataType) {\n switch (dataType) {\n case '"'undefined'"':\n return '"'Undefined'"';\n case '"'boolean'"':\n return '"'boolean'"';\n case '"'number'"':\n return '"'int'"';\n case '"'string'"':\n return '"'string'"';\n case '"'symbol'"':\n return '"'Symbol'"';\n case '"'bigint'"':\n return '"'BigInt'"';\n case '"'object'"':\n return '"'string'"';\n case '"'function'"':\n return '"'Function'"';\n default:\n return '"'Unknown'"';\n }\n }\n let textPayload = JSON.stringify(\n {\n parent: {\n keys: [\n {\n idType: '"'Custom'"',\n type: '"'Submodel'"',\n value: name+'"'_'"'+feature_id,\n local: true\n }\n ]\n },\n idShort: property_id,\n kind: '"'Instance'"',\n valueType: dataType,\n modelType: {\n name: '"'Property'"'\n },\n value: value\n }\n );\n let bytePayload = null;\n let contentType = '"'application/json'"';\n return Ditto.buildExternalMsg(headers, textPayload, bytePayload, contentType);}"
}
}
},
"sources": [],
"targets": [
{
"address": "PUT:/aasServer/shells/{{ thing:namespace }}",
"headerMapping": {
"content-type": "{{ header:content-type }}"
},
"authorizationContext": ["nginx:ditto"],
"topics": [
"_/_/things/twin/events?filter=and(in(topic:action,'"'created'"'),eq(resource:path,'"'/'"'))"
],
"payloadMapping": [
"mappingforShell"
]
},
{
"address": "PUT:/aasServer/shells/{{ thing:namespace }}/aas/submodels/{{ thing:name }}_{{ resource:path | fn:substring-after('"'/features/'"') }}",
"headerMapping": {
"content-type": "{{ header:content-type }}"
},
"authorizationContext": ["nginx:ditto"],
"topics": [
"_/_/things/twin/events?filter=and(in(topic:action,'"'created'"'),not(eq(resource:path,'"'/features'"')),like(resource:path,'"'/features*'"'),not(like(resource:path,'"'*properties*'"')))"
],
"payloadMapping": [
"mappingforSubmodel"
]
},
{
"address": "PUT:/aasServer/shells/{{ thing:namespace }}/aas/submodels/{{ thing:name }}_{{ resource:path | fn:substring-after('"'/features/'"') | fn:substring-before('"'/properties'"') }}/submodel/submodelElements/properties_{{ resource:path | fn:substring-after('"'/properties/'"') | fn:replace('"'/'"','"'_'"') }}",
"headerMapping": {
"content-type": "{{ header:content-type }}"
},
"authorizationContext": ["nginx:ditto"],
"topics": [
"_/_/things/twin/events?filter=and(in(topic:action,'"'modified'"'),not(eq(resource:path,'"'/features'"')),like(resource:path,'"'/features*'"'),like(resource:path,'"'*properties*'"'),not(like(resource:path,'"'*properties'"')))"
],
"payloadMapping": [
"mappingforSubmodelElement"
]
}
]
}
}
}' <ditto-instance-url>/devops/piggyback/connectivity
Listing 5: Request to add a new Connection
to a Ditto instance
When Ditto established the connection and our payload mappings work, it returns a successful HTTP response and otherwise an error message.
Without any further means, the payload mappings defined in piggybackCommand.mappingDefinition
and set in piggybackCommand.targets
would get executed for all changes to a Thing.
To prevent this, we use filtering with RQL expressions to make sure that our payload mappings are only executed for the correct messages.
For example, the filter:
_/_/things/twin/events?filter=and(in(topic:action,'"'created'"'),eq(resource:path,'"'/'"'))
before mappingforShell
in piggybackCommands.targets[0].topics[0]
makes sure that it only triggers for messages, which create a Thing.
Another filter for mappingForSubmodel
in pigybackCommands.targets[1].topics[0]
makes sure, that the parameter path
contains a feature
and not a property
:
"_/_/things/twin/events?filter=and(in(topic:action,'"'created'"'),not(eq(resource:path,'"'/features'"')),like(resource:path,'"'/features*'"'),not(like(resource:path,'"'*properties*'"')))"
Setup Connection to an BaSyx AAS Registry
Within an AAS environment it is required that AAS are discoverable via an AAS registry. We make an AAS discoverable by adding an entry for that AAS into the AAS registry for a new Thing. In our setup we achieve this through the definition of a new connection between Eclipse Ditto and the BaSyx AAS Registry with a respective payload mapping.
function mapFromDittoProtocolMsg(
namespace,
name,
group,
channel,
criterion,
action,
path,
dittoHeaders,
value,
status,
extra
) {
let headers = dittoHeaders;
let textPayload = JSON.stringify({
endpoints: [
{
address: '<basyx-server-instance-url>:4001/aasServer/shells/' + namespace + '/aas',
type: 'http'
}
],
modelType: {
name: 'AssetAdministrationShellDescriptor'
},
identification: {
idType: 'Custom',
id: namespace
},
idShort: namespace,
asset: {
identification: {
idType: 'Custom',
id: namespace + '-asset'
},
idShort: namespace + '-asset',
kind: 'Instance',
dataSpecification: [],
modelType: {
name: 'Asset'
},
embeddedDataSpecifications: []
},
submodels: []
});
let bytePayload = null;
let contentType = 'application/json';
return Ditto.buildExternalMsg(
headers, // The external headers Object containing header values
textPayload, // The external mapped String
bytePayload, // The external mapped byte[]
contentType // The returned Content-Type
);
}
Listing 6: Snippet to add a new AAS Registry entry for an AAS
As introduced in Mapping of Data Models, we map a namespace
in Ditto to an AAS.
The new entry in the BaSyx Registry has to contain the endpoint of the BaSyx AAS server, which hosts the new AAS. You find this in the script-payload in the variable endpoints.address
. So you need to adapt this value in the following HTTP request to the address of the BaSyx ASS server that you are using and that was configured in the connection between Ditto and the BaSyx AAS Server.
With this mapping, it is now possible to configure a new connection from Ditto to a BaSyx AAS registry through the following HTTP request:
curl -X POST -u devops:foobar -H 'Content-Type: application/json' --data-binary '{
"targetActorSelection": "/system/sharding/connection",
"headers": {
"aggregate": false
},
"piggybackCommand": {
"type": "connectivity.commands:createConnection",
"connection": {
"id": "basyxregistry-http-connection",
"connectionType": "http-push",
"connectionStatus": "open",
"uri": "<basyx-registry-instance-url>:4000",
"failoverEnabled": true,
"mappingDefinitions": {
"mappingforShell": {
"mappingEngine": "JavaScript",
"options": {
"outgoingScript": "function mapFromDittoProtocolMsg(namespace, name, group, channel, criterion, action, path, dittoHeaders, value, status, extra) {\n let headers = dittoHeaders;\n let textPayload = JSON.stringify({\n endpoints: [\n {\n address: '"'<basyx-server-instance-url>:4001/aasServer/shells/'"' + namespace + '"'/aas'"',\n type: '"'http'"'\n }\n ],\n modelType: {\n name: '"'AssetAdministrationShellDescriptor'"'\n },\n identification: {\n idType: '"'Custom'"',\n id: namespace\n},\n idShort: namespace,\n asset: {\n identification: {\n idType: '"'Custom'"',\n id: namespace + '"'-asset'"'\n },\n idShort: namespace + '"'-asset'"',\n kind: '"'Instance'"',\n dataSpecification: [],\n modelType: {\n name: '"'Asset'"'\n },\n embeddedDataSpecifications: []\n },\n submodels: []\n });\n let bytePayload = null;\n let contentType = '"'application/json'"';\n return Ditto.buildExternalMsg(headers, textPayload, bytePayload, contentType);}"
}
}
},
"sources": [],
"targets": [
{
"address": "PUT:/registry/api/v1/registry/{{ thing:namespace }}",
"headerMapping": {
"content-type": "{{ header:content-type }}"
},
"authorizationContext": ["nginx:ditto"],
"topics": [
"_/_/things/twin/events?filter=and(in(topic:action,'"'created'"'),eq(resource:path,'"'/'"'))"
],
"payloadMapping": [
"mappingforShell"
]
}
]
}
}
}' <ditto-instance-url>/devops/piggyback/connectivity
Listing 7: Request to add a new Connection
to a Ditto instance
We list the JavaScript mapper in piggybackCommand.connection.mappingDefinitions.mappingForShell.options.outgoingScript
and reference it as mappingForShell
in piggybackCommand.connection.targets[0].payloadMapping
.
The address of the BaSyx AAS registry is configured in the parameter piggybackCommand.connection.uri
.
As filter, to make sure that our mapper function only triggers after the creation of new Thing, we use:
"_/_/things/twin/events?filter=and(in(topic:action,'"'created'"'),eq(resource:path,'"'/'"'))"
Since the registry uses the AAS server endpoint as a base to also get access to all submodels and submodel elements from the same AAS, it is enough to register the AAS endpoint.
Test the Connection
We now configured all required connections in Ditto and can test our setup. All configured mappers trigger through changes to a Thing, so we begin by creating a Thing.
We again refer to the used Ditto instance through the placeholder <ditto-instance-url>
,
which you need to adapt to the URL of your Ditto instance.
Creating a Thing in Eclipse Ditto
Setup a common policy
To define authorization information to be used by the Things,
we first create a policy with the policy-id machine:my-policy
.
POLICY_ID=machine:my-policy
curl -i -X PUT -u ditto:ditto -H 'Content-Type: application/json' --data '{
"entries": {
"DEFAULT": {
"subjects": {
"{{ request:subjectId }}": {
"type": "Ditto user authenticated via nginx"
}
},
"resources": {
"thing:/": {
"grant": ["READ", "WRITE"],
"revoke": []
},
"policy:/": {
"grant": ["READ", "WRITE"],
"revoke": []
},
"message:/": {
"grant": ["READ", "WRITE"],
"revoke": []
}
}
}
}
}' <ditto-instance-url>/api/2/policies/$POLICY_ID
Listing 8: Demo Policy Definition
You will get a 201 Created
response, if the policy creation concluded successfuly. In the subsequent steps, we use the policy-id machine:my-policy
to refer to the created policy.
Create a Thing
The next step is to create an actual Thing.
We use the namespace and name machine:my-policy
and policy-id machine:my-policy
here:
NAMESPACE=machine
NAME=sensor
DEVICE_ID=$NAMESPACE:$NAME
curl -i -X PUT -u ditto:ditto -H 'Content-Type: application/json' --data '{
"policyId": "'$POLICY_ID'"
}' <ditto-instance-url>/api/2/things/$DEVICE_ID
Listing 9: Request to add the Demo Policy to a Ditto instance ($POLICY_ID
refers to Listing 8)
Again, a successful creation returns a 201 Created
response.
We earlier configured two connections to trigger a mapper on the create event of a Thing. This should push a new AAS to the AAS server and a reference to that AAS in the AAS registry.
You can check whether the execution of the scripts was successful by requesting the shell at the AAS server:
curl -X GET <basyx-server-instance-url>:4001/aasServer/shells
which should return the following result
[{"modelType":{"name":"AssetAdministrationShell"},"idShort":"machine","identification":{"idType":"Custom","id":"machine"},"dataSpecification":[],"embeddedDataSpecifications":[],"submodels":[{"keys":[{"type":"AssetAdministrationShell","local":true,"value":"machine","idType":"Custom"},{"type":"Submodel","local":true,"value":"sensor_temperature","idType":"Custom"}]}],"asset":{"keys":[{"type":"Asset","local":true,"value":"machine-asset","idType":"Custom"}],"identification":{"idType":"Custom","id":"machine-asset"},"idShort":"machine-asset","kind":"Instance","dataSpecification":[],"modelType":{"name":"Asset"},"embeddedDataSpecifications":[]},"views":[],"conceptDictionary":[]}]
In addition, the request to the AAS registry:
curl -X GET <basyx-registry-instance-url>:4000/registry/api/v1/registry
should return:
[{"modelType":{"name":"AssetAdministrationShellDescriptor"},"endpoints":[{"address":"<basyx-server-instance-url>:4001/aasServer/shells/machine/aas","type":"http"}],"identification":{"idType":"Custom","id":"machine"},"idShort":"machine","asset":{"identification":{"idType":"Custom","id":"machine-asset"},"idShort":"machine-asset","kind":"Instance","dataSpecification":[],"modelType":{"name":"Asset"},"embeddedDataSpecifications":[]},"submodels":[]}]
At this point, the newly created Thing has no features, properties, or attributes yet. So let us populate that Thing.
Create a feature for the Thing
Next, we create a feature for the Thing to contain a property with the data of a temperature sensor.
FEATURE_ID=temperature
curl -X PUT -u ditto:ditto -H 'Content-Type: application/json' --data-binary '{
"properties": {
"value": null
}
}' <ditto-instance-url>/api/2/things/$DEVICE_ID/features/$FEATURE_ID
Listing 10: Request to add a feature to the demo Thing (variables refer to previous Listings)
The feature creation triggers the mapper (mappingforSubmodel
) to create a corresponding Submodel in the previously created AAS.
To check if this was successful, we request the expected submodel:
curl -X GET <basyx-server-instance-url>:4001/aasServer/shells/$NAMESPACE/aas/submodels/${NAME}_${FEATURE_ID}/submodel
which should result in the following response:
{"parent":{"keys":[{"idType":"Custom","type":"AssetAdministrationShell","value":"machine","local":true}]},"identification":{"idType":"Custom","id":"sensor_temperature"},"idShort":"sensor_temperature","kind":"Instance","dataSpecification":[],"modelType":{"name":"Submodel"},"embeddedDataSpecifications":[],"submodelElements":[]}
Updating a Thing
After we have successfully created a Thing, we can check if the update of a property works as well by executing:
curl -i -X PUT -u ditto:ditto -H "content-type: application/json" --data-binary '46' <ditto-instance-url>/api/2/things/$DEVICE_ID/features/$FEATURE_ID/properties/value
Again, we check if our change was successful:
curl -u ditto:ditto -w '\n' <ditto-instance-url>/api/2/things/$DEVICE_ID
and expect:
{"thingId":"machine:sensor","policyId":"machine:my-policy","features":{"temperature":{"properties":{"value":46}}}}
If the property creation was successful, then the mapping mappingforSubmodelElement
should trigger.
To verify that the Submodel was updated, call:
curl -X GET <basyx-server-instance-url>:4001/aasServer/shells/$NAMESPACE/aas/submodels/${NAME}_${FEATURE_ID}/submodel/submodelElements/properties_value
This should lead to the response:
{"parent":{"keys":[{"idType":"Custom","type":"Submodel","value":"sensor_temperature","local":true}]},"idShort":"properties_value","kind":"Instance","valueType":"int","modelType":{"name":"Property"},"value":46}
Here, we see that we are able to access the sensor data of the device through the AAS Submodel API via Eclipse BaSyx.
As an alternative to plain Json responses, you can use one of the UI-tools provided by the AAS community, like the AAS Web UI.
![AAS Dashboard](https://eclipse.dev/ditto/images/blog/2024-02-15-integrating-ditto-ass-basyx/AASDashboard.png)
Figure 4: BaSyx AAS Web UI
Summary
In this post, we present our approach for making Ditto Things available in an AAS. We defined a mapping concept between Things and AAS. To apply the mapping concept, we created connections with mappers from Ditto to a BaSyx AAS server and a BaSyx AAS registry. Afterwards, we tested the connections with an example Thing and data from a sensor.
Our example of integrating Ditto Things into an AAS environment shows, how the capbilities of Ditto, such as custom mappers, filters etc, render it a useful tool to integrate device states into various environments. We discussed the integration into AAS but believe a similar approach could be applied in other domains as well.
Milena Jäntgen, Sven Erik Jeroschewski and Max Grzanna contributed to this post.
February 26, 2024
Why Every Tool and IDE Project Should Care About AI Integration
by Jonas, Maximilian & Philip at February 26, 2024 12:00 AM
For creators of custom tools and Integrated Development Environments (IDEs), AI integration is not just a fleeting trend or an additional feature to consider. It is a paradigm shift, capable of …
The post Why Every Tool and IDE Project Should Care About AI Integration appeared first on EclipseSource.
February 21, 2024
Real-time Collaboration on Diagrams with Eclipse GLSP
by Jonas, Maximilian & Philip at February 21, 2024 12:00 AM
In our globalized era, seamless collaboration is more important than ever, especially in complex fields like modeling and diagram editing. With this in mind, we’re thrilled to introduce a new …
The post Real-time Collaboration on Diagrams with Eclipse GLSP appeared first on EclipseSource.
February 18, 2024
Code RealTime: Harnessing the Power of the Eclipse Cloud DevTools Ecosystem
by John Kellerman at February 18, 2024 06:53 PM
This adopter story delves into Code RealTime, an innovative tool for creating stateful, event-driven real time applications in C++, created by HCL and IBM. By leveraging the strengths of the Eclipse Cloud DevTools open source ecosystem, including Eclipse Theia and Eclipse GLSP, Code RealTime offers a unique blend of advanced programming capabilities, intuitive graphical interfaces, and a seamless development experience. This story not only highlights the tool's innovative features, but also the integral role played by the Eclipse Cloud DevTools ecosystem in its creation, demonstrating a successful collaboration of cutting-edge technologies.
Code RealTime uses the Art language to enable developing stateful, event-driven applications on top of C++. Art stands out for its high-level concepts such as state machines, capsules, events and ports, making complex application development more intuitive and efficient. In Code RealTime, these concepts can be efficiently used in a textual form with all modern code editor features such as auto-completion, live validation, and more. However, Art also seamlessly integrates a graphical visualization, which is updated as the user types. The ability to visualize these elements through graphical diagrams provides a more comprehensive understanding of the application architecture, significantly enhancing the user experience. Finally, the tool's real-time semantic validation and auto-generation of optimized C++ code streamline the development process, ensuring high performance and reliability. Code RealTime is developed in a collaboration between HCL and IBM.
The Code RealTime tooling is implemented entirely on a modern, web-based and open source technology stack. It is available as an installable extension for desktop IDEs, including Eclipse Theia and also as an online version, conveniently provided as a Docker container, exclusively based on Eclipse Theia. The ability to build comprehensive tools such as Code RealTime on Eclipse Theia and provide them as offline and online versions underscores Theia's versatility and strength in supporting the development of complex developer tools.
The two main components within Code RealTime are the textual and graphical editors supporting the Art language. The textual language support for Art is based on the Language Server Protocol (LSP), which is conveniently integrated in Eclipse Theia. The corresponding Language Server was created using Eclipse Xtext.
The graphical elements of Code RealTime are based on the Graphical Language Server Platform (Eclipse GLSP), the leading open source framework for building custom diagram editors based on web technologies at the Eclipse Foundation. Code RealTime makes full use of the flexibility of GLSP in various aspects. The diagrams are directly connected to the underlying textual representation; they will update live while the user is typing in Art. And, conversely, if changes are made in the diagrams, the corresponding Art files will also update. Furthermore, GLSP enables Code Realtime to seamlessly integrate the diagrams into the IDE extension, including consistent styling. This video shows the tool in action with a focus on the perfect synergy between textual editing and the GLSP-based diagrams:
To seamlessly integrate its feature set into the existing workbench provided by Theia, Code RealTime makes heavy use of the VS Code extension API. Theia, as a framework, is fully compatible with this API, allowing tools such as Code RealTime to also be used in other IDEs, including VS Code.
The ready-to-be-used online version (provided as a Docker container) shows Theia’s flexibility in terms of deployment. Based on the same code, Code RealTime can be used as a desktop application, installed into existing IDE installations and hosted online in the cloud, where users simply follow a URL to start their C++ projects with Art. The online option is exclusively available based on Eclipse Theia.
Code RealTime demonstrates the potential of combining different Eclipse open source technologies to create a cohesive and efficient development environment. Moreover, the interaction between the Code RealTime development team and the open source community is a shining example of collaborative innovation. Far from simply utilizing open source libraries, the team actively participates in the ecosystem. They regularly attend project meetings, such as for Eclipse Theia, and contribute high quality bug reports. They also present their experience in open forums such as TheiaCon. This active engagement not only enhances the tool but also aids in the industrial hardening of the open source technologies they use. Their feedback is invaluable, driving improvements and showcasing the potential of open source technology. As such, Code RealTime stands as a beacon of successful open source collaboration and adoption, highlighting the reciprocal benefits between adopters and the broader community. This dynamic interaction exemplifies how collaborative efforts can lead to robust and innovative technological solutions.
For more detailed information about Code RealTime and its integration with Eclipse technologies, visit the Code RealTime website.
“Theia's superior customizability is especially beneficial for advanced users who seek to tailor their IDE with specific extensions and functionalities. Additionally, Theia's ease in facilitating web-based access positions it as a more adaptable alternative to other IDEs. This flexibility is crucial for "Code RealTime," as it allows for seamless integration and deployment in various environments, including cloud-based platforms.”
Mattias Mohlin, Senior Software Architect and development lead of Code RealTime
February 14, 2024
Rock-solid Diagram Editors: End-to-end Testing with Eclipse GLSP
by Jonas, Maximilian & Philip at February 14, 2024 12:00 AM
Industrial-grade diagram editors are intricate, filled with advanced functionalities and complex logic. It’s clear then that automated testing isn’t just beneficial—it’s essential for maintaining a …
The post Rock-solid Diagram Editors: End-to-end Testing with Eclipse GLSP appeared first on EclipseSource.
February 12, 2024
Building Custom C/C++ Tools: CDT Cloud and Eclipse Theia in Action
by Jonas, Maximilian & Philip at February 12, 2024 12:00 AM
Are you looking for the best way to create a custom C/C++ development tool that perfectly matches your specific requirements, hardware, or tool-chains? Check out our recent session at TheiaCon! We’ve …
The post Building Custom C/C++ Tools: CDT Cloud and Eclipse Theia in Action appeared first on EclipseSource.
February 09, 2024
Eclipse JKube 1.16 is now available!
February 09, 2024 04:00 PM
On behalf of the Eclipse JKube
team and everyone who has contributed, I'm happy to announce that Eclipse JKube 1.16.2
has been
released and is now available from
Maven Central �.
Thanks to all of you who have contributed with issue reports, pull requests, feedback, and spreading the word with blogs, videos, comments, and so on. We really appreciate your help, keep it up!
What's new?
Without further ado, let's have a look at the most significant updates:
- New Buildpacks based build strategy
- New Helm Lint feature
- Support for Kubernetes Recommended Labels
- Updated base images:
- Better support for Java 21
- Jolokia updated to 2.0.0
- Red Hat UBI based on UBI 9
- � Many other bug-fixes and minor improvements
New Buildpacks based build strategy
Users can now leverage Cloud Native Buildpacks to build their container images.
In addition to the existing docker
, jib
, and s2i
build strategies, JKube now supports the buildpacks
strategy.
To enable the buildpacks
strategy, you just need to set the jkube.build.strategy
property to buildpacks
:
<prooperties>
<jkube.build.strategy>buildpacks</jkube.build.strategy>
</properties>
Or in case you're using Gradle:
jkube.build.strategy=buildpacks
There is no need to have a Pack CLI binary installed in your system, JKube takes care of downloading and wrapping the Pack CLI for you.
Currently, JKube reads your .pack/config.toml
file to select the builder image.
In case there is no .pack/config.toml
file, JKube will use the standard paketobuildpacks/builder:base
builder image.
New Helm Lint feature
Eclipse JKube provides now a new feature to lint the Helm charts it generates just by running a simple Maven or Gradle command.
Once you've generated the Kubernetes resources and the Helm charts, you can now examine the generated Helm charts for possible issues.
In case of Maven:
mvn k8s:resource k8s:helm k8s:helm-lint
Or if you're using Gradle:
gradle k8sResource k8sHelm k8sHelmLint
Using this release
If your project is based on Maven, you just need to add the Kubernetes Maven plugin or the OpenShift Maven plugin to your plugin dependencies:
<plugin>
<groupId>org.eclipse.jkube</groupId>
<artifactId>kubernetes-maven-plugin</artifactId>
<version>1.16.2</version>
</plugin>
If your project is based on Gradle, you just need to add the Kubernetes Gradle plugin or the OpenShift Gradle plugin to your plugin dependencies:
plugins {
id 'org.eclipse.jkube.kubernetes' version '1.16.2'
}
How can you help?
If you're interested in helping out and are a first-time contributor, check out the "first-timers-only" tag in the issue repository. We've tagged extremely easy issues so that you can get started contributing to Open Source and the Eclipse organization.
If you are a more experienced developer or have already contributed to JKube, check the "help wanted" tag.
We're also excited to read articles and posts mentioning our project and sharing the user experience. Feedback is the only way to improve.
Project Page | GitHub | Issues | Gitter | Mailing list | Stack Overflow
![The logo of Eclipse JKube](https://blog.marcnuri.com/static/af6673438e09cd98812665335c800cbf/e5189/JKube-blog-banner.jpg)
Eclipse Theia 1.46 Release: News and Noteworthy
by Jonas, Maximilian & Philip at February 09, 2024 12:00 AM
We are happy to announce the Eclipse Theia 1.46 release! The release contains 69 merged pull requests and we welcome four new contributors. In this article we will highlight some selected improvements …
The post Eclipse Theia 1.46 Release: News and Noteworthy appeared first on EclipseSource.
February 08, 2024
The Eclipse Theia Community Release 2024-02
by Jonas, Maximilian & Philip at February 08, 2024 12:00 AM
We are happy to announce the fifth Eclipse Theia community release “2024-02”, version 1.45.x! New to Eclipse Theia? It is the next-generation platform for building IDEs and tools for the web or …
The post The Eclipse Theia Community Release 2024-02 appeared first on EclipseSource.
February 07, 2024
Bridging the Gap
by Donald Raab at February 07, 2024 07:12 PM
Taking a road trip and checking off some bucket list items on my todo list
![](https://cdn-images-1.medium.com/max/1024/1*BVk-14GJ17dOIKboBZi8OA.png)
Empty Nesters with Time Off
My wife and I decided that on January 16th, the same day both of our kids had returned to university, that we would drive down the east coast with the ultimate goal of spending some time with my aunt. For various reasons and pandemics, I hadn’t seen my aunt in at least five years. It had honestly been so long, that neither my aunt or myself could remember exactly when we had last seen each other in person. No matter, I had set my mind on visiting and spending some quality time with my aunt for a few days, so that’s what we did.
This trip was unlike any other I have ever taken in my life. The trip had a beginning (New Jersey), a goal (visit with my aunt), a final destination (New Jersey), but not much in the way of advance planning for particular destinations along the way. Only the first two bullets below were scheduled stays before we started the trip. Once we reached Palm Coast, Florida, we decided how long we would stay, and what we would do next. We used our previously banked (thanks pandemic!) Marriott timeshare points for overnight stays anywhere we could. This determined most of the places we decided to stay.
Plan is nothing. Planning is everything.
Our plans and destinations changed on a daily basis. By the end of the trip, my wife and I saw many new places, sights, sunrises and sunsets. We also ate a lot of great food and drank a lot of yummy coffee. I’m honestly at a loss for how much we were able to see and do. The trip felt like it was months long, but was seventeen days and sixteen nights with nine overnight destinations. We spent 50–60 hours driving in our SUV. I estimate we drove at least 3,500 miles during the trip. I am now taking some much needed time off from driving.
Major Stops along our trip:
✅ Williamsburg, VA (overnight)
✅ Myrtle Beach, SC (two nights)
✅ Palm Coast, FL (three nights)
✅ Orlando, FL (two nights)
✅ Pompano Beach, FL (🛑 How You Brewin? Coffee House for ☕�)
✅ Singer Island, FL (two nights)
✅ Pompano Beach, FL (🛑 How You Brewin? Coffee House for ☕�)
✅ Miami, FL (checked in but didnt’ stay)
✅ Key Largo, FL (two nights)
✅ Bahia Honda State Park, Bahia Honda Key (🛑 for ��)
✅ Pompano Beach, FL (🛑 How You Brewin? Coffee House for ☕�)
✅ Palm Coast, FL (overnight)
✅ Hilton Head Island, SC (two nights)
✅ Williamsburg, VA (overnight)
✅ Washington, DC (🛑 for lunch)
Every day of this trip was a beautiful day. We literally had only 10 minutes of rain the entire time. I feel like I understand the motto of my cousin Chris a lot better after taking this trip. We enjoyed every beautiful day! Thank you for the best life advice, Chris!
The rest of this blog will be organized by the stops we took with some select pictures. We took hundreds of pictures, so it was a challenge to filter them. I hope you enjoy the ones I selected, and find inspiration to go on your own road trip adventures. We sometimes forget how many wonderful things there are to do and see in this beautiful country we live in. Enjoy it!
Williamsburg, VA
We love visiting Williamsburg, Virginia. It is a nice place to stop on a long road trip to the Southern East Coast and has some great alternatives for food and entertainment. When the kids were younger, we used to visit Busch Gardens and Water Country USA. On this trip we spent one night on the way down, and one night on the way back. We ate at the same restaurant both times this trip —Mellow Mushroom Pizza Restaurant.
It was cold in Williamsburg, and we got there after dark I so didn’t take any pictures this trip.
Myrtle Beach, SC
The first destination on our trip that neither my wife nor I had been to before was Myrtle Beach, South Carolina.
Day 1
This is a picture I took from the Marriott Vacation Club resort we stayed at after we checked in.
![](https://cdn-images-1.medium.com/max/1024/1*UxCF1rlj2OCS3eYNosG3Jg.png)
The temperature was in low to mid 50’s (Fahrenheit) when we arrived. Some folks were going in the hot tub, but no one was brave enough it seems to go in the pools, even though they were heated.
I went for a walk on the beach and caught a decent sunset.
![](https://cdn-images-1.medium.com/max/1024/1*z2LEPHYl2OQTTCJtic1L1Q.png)
I love taking pictures of sunsets and this trip was full of some great ones.
![](https://cdn-images-1.medium.com/max/1024/1*CkS7XxiVXL-ppN4bNiJUww.png)
Day 2
I’m not a morning person. I’ve always been a night owl. I made an exception during this trip. In addition to my usual sunsets, I wanted to take advantage of our ocean based stays and capture some hopefully amazing sunrises. I was not disappointed.
I woke up a half hour before sunrise in Myrtle Beach and started taking photos.
![](https://cdn-images-1.medium.com/max/1024/1*b-8jhFHGgPgR-xKAQlFgDg.png)
As the sun began to rise over the clouds after 7:15am, I caught this picture in all its splendor. The gray clouds on the horizon were challenging my ability to determine how to balance the photo.
![](https://cdn-images-1.medium.com/max/1024/1*Fq3psECegaEOfYUTKJumbQ.png)
The sun had risen fully by the next picture, and was beginning to reflect strongly on the ocean.
![](https://cdn-images-1.medium.com/max/1024/1*gUp7IT2k33AVULrHxj--Ng.png)
I zoomed in with 2x for this wonderful shot of the sun, which by this point was drowning out the dark gray clouds behind it so I could finally find my balance with the the ocean line. I went back in to get a bit more sleep before breakfast.
![](https://cdn-images-1.medium.com/max/1024/1*07xZd09udG98Vtuu6neZzw.png)
I am not fully functional until I have had at least one cup of coffee. The coffee at Blueberry’s Grill in Myrtle Beach was very good. I enjoyed the breakfast as well. I also quite liked the mug, so I took this picture.
![](https://cdn-images-1.medium.com/max/1024/1*cvSYCqEZ5bLjxjOjvXGXiA.png)
We caught nice sunset dinner at a restaurant called Chestnut Hill in Myrtle Beach. We had a delicious dinner two nights in a row there as well. I find when you are on a short trip somewhere, there is no need to experiment with multiple restaurants. If you find some place good, then go back and try different things on the menu.
![](https://cdn-images-1.medium.com/max/1024/1*k0IjO3lDcy5BAXuM9jQ7QA.png)
Day 3
Two days in a row, I woke up early for the sunrise. The sun did not disappoint. Every sunrise and sunset is different. I recommend enjoying as many as you possibly can. We had to check out of the room by 10am, so I had to get up anyway and pack the car. This picture was worth getting up a little bit earlier.
![](https://cdn-images-1.medium.com/max/1024/1*gp0y1VUb5lPuxqtKUpGrew.png)
Palm Coast, FL
The day we arrived at Palm Coast, FL, we took a quick drive with my aunt to visit Flagler Beach. For three days we pretty much ate breakfast and dinner at Metro Diner, which was just awesome.
Day 1
We had hoped to go eat at the Flagler Tea Company, but it was closed until a few days after we visited. I took this picture of the waves and surf at the pier at Flagler Beach.
![](https://cdn-images-1.medium.com/max/1024/1*KtNabB2vUUImJR29QMRqnQ.png)
Day 2
We took a drive to Washington Oaks Gardens State Park. It was cold and windy the day we went there, but it was totally clear blue sky.
![](https://cdn-images-1.medium.com/max/1024/1*3NW8FzUiqWJhC5f-lW5iGQ.png)
I took this picture of the gazebo in the water in the middle of the park. I really love the colors that come out in this picture. I half expected fairies, elves, and gnomes to jump out and say hello.
![](https://cdn-images-1.medium.com/max/1024/1*IfMfNub-rxLlvJEO18xGgw.png)
We went the ocean side of the park, but the winds were so strong, they were blowing sand everywhere. I got this decent picture of the waves being blown in by the wind.
![](https://cdn-images-1.medium.com/max/1024/1*eC4Wx9nD4T5zLTv_XWsyXA.png)
Orlando, FL
I wasn’t originally planning to go to Orlando on this trip. I was hoping to stick mostly to the coastline. We decided while in Palm Coast to book a couple nights to help us move further south on our trip through Florida.
Day 1
We took a ride in a boat car next to The Boathouse in Disney Springs. This was the car we drove in the water with. I kept wondering about the seal on the doors and if we would take on any water. We stayed dry.
![](https://cdn-images-1.medium.com/max/1024/1*OK-RpKNzzwDpsBBk5fGk4Q.png)
Day 2
We decided if we were going to stay in Orlando, we were going to spend a day at Epcot. So we did. I took this one of many pictures of Spaceship Earth.
![](https://cdn-images-1.medium.com/max/1024/1*oDpfvZl542GVuJ46CgHv0Q.png)
We travelled around the countries of the world at Epcot, and I tried to buy a shot glass at each country, but was only able to find four of them. My favorite one was from Norway.
![](https://cdn-images-1.medium.com/max/1024/1*P6FBbkgjnn6nDarWWtPMmg.png)
I got a decent picture of a sunset over the lake in Epcot.
![](https://cdn-images-1.medium.com/max/1024/1*kXc26mQrRt6mbCHhkFtqRg.png)
Finally, we went for dinner at a nice restaurant called Space 220. After dinner I took a bunch of pictures of Spaceship Earth at the entrance, as it was lighting up in all different colors.
![](https://cdn-images-1.medium.com/max/1024/1*CIdf3nozHejb7WHgW4eLaA.png)
Pompano Beach, FL
We didn’t stay at Pompano Beach, but was stopped there three separate days for coffee at How You Brewin? Coffee Company. The first day we dropped by on our way from Orlando to Singer Island. Pompano Beach is about an hour south of Singer Island, but was worth the detour to visit my favorite coffee house originally from Long Beach Island, NJ.
![](https://cdn-images-1.medium.com/max/1024/1*WwLCDgtD8uzGly_twnfRRg.png)
We walked out on the pier at Pompano Beach, which was quite nice. I liked how colorful the lifeguard stations were on the beach.
![](https://cdn-images-1.medium.com/max/1024/1*k5uLzHk24EVNyrZym6p2DQ.png)
Singer Island, FL
We stayed at Marriott’s Ocean Pointe location on Singer Island. We were staying on the South Eastern corner of the island right next to an inlet that let ships and boats come in and out from the Atlantic.
Day 1
We got to the resort after sunset, and I took this picture of the pool at our building.
![](https://cdn-images-1.medium.com/max/1024/1*sfrYkTmbJMe-ms4FntBvmA.png)
Day 2
Since I had committed to morning ritual of sunrises on this trip, I walked to the beach by the main building to catch the sunrise. It was about a 10 minute walk from our building to the main building.
![](https://cdn-images-1.medium.com/max/1024/1*tupQFtXrH59KPtXuIpU1AA.png)
I was a bit confused and excited to see this large ship off the beach, as it kept coming closer and closer.
![](https://cdn-images-1.medium.com/max/1024/1*4UzyMtnAt7pnEKYN4_Z6bw.png)
At one point I thought the boat was going to land on the beach. It turns out there is an inlet next to where we stayed that both large ships and boats come in and out of to get to and from the Atlantic.
![](https://cdn-images-1.medium.com/max/1024/1*42-iK-wTEY7NXUxp0V82Hw.png)
We went to a manatee viewing spot on the mainland, but didn’t see any manatees. Between the mainland and Singer Island, there was an island called Peanut Island. We got some beautiful sunset pictures from Singer Island overlooking Peanut Island.
![](https://cdn-images-1.medium.com/max/1024/1*n-WoonYVJqr-sMAVTNFdww.png)
The colors of the sunset were a bit surreal. They seemed to change colors and hues every few minutes.
![](https://cdn-images-1.medium.com/max/1024/1*M-LSC7nDLEOXCj-jYgYE8A.png)
Day 3
Another day, another sunrise. There are certainly perks to getting up early. I’m glad I took pictures so I can enjoy them as I return to being a night owl.
![](https://cdn-images-1.medium.com/max/1024/1*qIY-AAqI0pyjmkmyHOrvkg.png)
The following is a photo I took of a ship coming in the inlet we were next to on Singer island.
![](https://cdn-images-1.medium.com/max/1024/1*Vra9t6MkJGVfU9xfg7o2mg.png)
Pompano Beach, FL
When we left Singer Island, we stopped first at Pompano Beach to pick up some yummy coffee from How You Brewin? coffee shop.
Miami, FL
We had planned to stay two nights at Marriott’s Villas at Doral, but once we checked in at noon, we found out we would have to wait until 4pm to get our room. We decided quickly we would take a drive down to check out Key Largo, which was about an hour away, so we would not waste any time. This was the one photo I took of the pool at the Marriott we booked, but never wound up staying at.
![](https://cdn-images-1.medium.com/max/1024/1*8g_prBDwM1jKGPxxa-QEvg.png)
Key Largo, FL
Once we were on the road driving to Key Largo, we decided that we would see if we could find an available hotel to stay at. After being booked in an overbooked Courtyard by Marriott, we were referred to the Reefhouse Resort and Marina. We really enjoyed staying here, and it was a great launching point for two drives down through the Florida Keys.
Day 1
On our first drive on US 1 through the Florida Keys, we stopped at Marathon Key and the Sunset Park at Key Colony Beach.
![](https://cdn-images-1.medium.com/max/1024/1*-ncRSmlyU89tGGVRy44n2A.png)
From Marathon, we turned around on US 1 and stopped along the way at Long Key State Park for a few minutes and few photos.
![](https://cdn-images-1.medium.com/max/1024/1*B4N9jyo1CAHGJiHPscC9ug.png)
We got back to the Reefhouse Resort and Marina just after sunset, but I was able to catch some great after sunset photos overlooking the Blackwater Sound.
![](https://cdn-images-1.medium.com/max/1024/1*CEBlHt6Yj0RnF-1BUKXVFA.png)
Day 2
We had to wake up at 6am to see the sunrise at Harry Harris Park on Key Largo. We had looked up what the best place to see a sunrise on Key Largo was, and this park was what we found. We drove there at 7:00am and found a line of cars with boats waiting for the gates to open. Unfortunately, the park opened for cars at 7:30am, which was about 15 minutes after sunrise. We decided I would enter the park on foot, and my wife would wait for me in the car. I took pictures of the sunrise for us. The sunrise here was nice, but not the best sunrise ever.
![](https://cdn-images-1.medium.com/max/1024/1*XLgTXtlBHXSinqnpXD3Mng.png)
After the sunrise, we were hungry, so we found a great little restaurant named Harriette’s for breakfast. The breakfast was delicious, and I had the biggest biscuit I have ever seen on a plate along with a crab filled omelette. I also had a delicious Key Lime muffin. I would definitely go here again. Both the food and service were great.
![](https://cdn-images-1.medium.com/max/1024/1*O-eHGA1M96xdLkPJ6ehw8w.png)
After breakfast, we decided to explore and see if we could find a decent beach or two in Key Largo. We drove to the north of Key Largo, only to find the road ended with a gate to a private club. We then went to a Botanical Garden in Key Largo for a nice walk. Then we drove around a bit looking at the map on our GPS for places we might be able to see a beach. Unfortunately, there weren’t any that we could find. We went back to the hotel we were staying at and asked the very nice concierge where the nicest beaches we could go to within a reasonable distance were. One of the beaches was at Mile Marker 37, which was past the Seven Mile Bridge. The beach was at Bahia Honda State Park. We were at Mile Marker 103.8 in Key Largo. After driving 66.8 miles, we would cross the Seven Mile Bridge and arrive at Bahia Honda State Park.
![](https://cdn-images-1.medium.com/max/1024/1*mZHDPXZyebL2lrOEH4UfMA.png)
I always wanted to drive over this bridge. Now I have. Twice. I thought it was going to be a bit harrowing to drive over such a long bridge over water, but I found the drive kind of relaxing and fun.
![](https://cdn-images-1.medium.com/max/1024/1*qv_Lqlc3IzVh1eKpgEA4mQ.png)
The wide shoulder on the bridge made the drive mostly stress free. The dotted line for cars to pass made it somewhat less so, but I guess some folks just can’t wait to get where they are going. When we arrived at Bahia Honda State Park, we paid the entrance fee and found some parking near a Beach Shop near the marina. We bought some towels and some water shoes, as I planned to go walking out in the amazing looking water.
![](https://cdn-images-1.medium.com/max/1024/1*Z3Bjbq548G3bxDe-QZp17A.png)
Here’s a selfie of me walking in the water with my new water shoes.
![](https://cdn-images-1.medium.com/max/1024/1*DS5L-74ffGdNTnKNHFTK0w.png)
The views at several beaches that are part of Bahia Honda State Park were just stunning. I hope you enjoy a few of them here.
![](https://cdn-images-1.medium.com/max/1024/1*BVk-14GJ17dOIKboBZi8OA.png)
This is a picture of the bridge we did not drive across. It was a bridge too far for our one day driving on the Florida Keys. Next time!
![](https://cdn-images-1.medium.com/max/1024/1*nbSwnTgwD8lOnC4BwcquKQ.png)
When we were done hanging out at Bahia Honda State Park, we headed back across the Seven Mile Bridge and the rest of the keys to Key Largo and the Reefhouse Resort and Marina to enjoy the sunset.
![](https://cdn-images-1.medium.com/max/1024/1*Yr-Vccp7wiInYCTWmq-9gA.png)
The sunset on Blackwater Sound was cool and somewhat eerie.
![](https://cdn-images-1.medium.com/max/1024/1*7p86pe6casdKTbzytIDe5g.png)
Day 3
We would check out of the Reefhouse on Key Largo at 10am and head back up the east coast of Florida to Palm Coast to visit again with my aunt. But first, we would stop again in Pompano Beach for my favorite coffee at my favorite coffee house.
![](https://cdn-images-1.medium.com/max/1024/1*561dco8nCogKkMVGLsnh1A.png)
Palm Coast, FL
We only stayed one night at Palm Coast, but I got to have a couple of Sierra Nevadas at our hotel bar while watching San Francisco win against Detroit.
![](https://cdn-images-1.medium.com/max/1024/1*OYxwbbkunc6kDWoLN3kpEQ.png)
Hilton Head Island, SC
My wife and I had never been to Hilton Head Island, South Caroline, so we booked two nights at a Marriott Grand Ocean resort there. Sunsets and sunrises were great here. So was the food.
Day 1
We arrived after a 3–4 hour trip from Palm Coast, Florida. This was the view of the ocean from our room.
![](https://cdn-images-1.medium.com/max/1024/1*y4ENSZM6aVC1LlFyzCAP4Q.png)
The beach at Hilton Head Island seemed to be at a really low tide when we took a walk.
![](https://cdn-images-1.medium.com/max/1024/1*OfGfsoXfwySdneIDjtaQ_g.png)
We drove to Harbor Town on Hilton Head Island and got some nice after sunset photos. The following picture is of the lighthouse in Harbor Town.
![](https://cdn-images-1.medium.com/max/1024/1*C2S760EPXReTpIQUVMgXsQ.png)
Day 2
As it would turn out, the sunrises from our room would get kind of obstructed by the trees. No worries. I walked down to the beach to get some unobstructed pictures.
![](https://cdn-images-1.medium.com/max/1024/1*jzfRm69YueSKT8TXw3nz9A.png)
I always enjoy when wildlife or boats decide to get involved in my sunrise and sunset shots. A seagull was nice enough to grace this shot.
![](https://cdn-images-1.medium.com/max/1024/1*2TUqjBqfR_p68iwOun_ZZw.png)
My wife has Celiac, so finding safe and good food is always a challenge. On this trip, we found the G-Free Spot! The breakfast sandwiches and bakery items are great here. I had a BEC on an everything bagel that they prepared non-gluten free in a separate kitchen. The coffee was great too.
![](https://cdn-images-1.medium.com/max/1024/1*izh7Q39kBzw8YR4qGE370g.png)
We got a recommendation to visit the Pinckney Island National Wildlife Refuge. I wish we had more time to spend there, but I would go back. We were lucky and got to see an alligator in Ibis Pond while we were visiting.
![](https://cdn-images-1.medium.com/max/1024/1*kRFQYUX_MDL-Ga-c8gPfZg.png)
I had to zoom on my camera to get this shot, but hopefully you can spot the alligator without too much strain.
![](https://cdn-images-1.medium.com/max/1024/1*ZPsgOheKJe1hl6QkjxHsKA.png)
We returned to Harbor Town for the sunset and dinner, and we were so very happy with both. This picture had a really cool cloud interaction. It almost looked like a left over tornado getting sizzled out by the sun.
![](https://cdn-images-1.medium.com/max/1024/1*34Sb4Jf9DCWDlSBiqu6t3g.png)
I like when I am able to line up the sun with something that makes a fun picture. Here the sun is turning on the light which was off.
![](https://cdn-images-1.medium.com/max/1024/1*njuwSAgZCZzqmkMUU_blEw.png)
My two favorite sunsets on this trip was this one and the one we experienced on Singer Island.
![](https://cdn-images-1.medium.com/max/1024/1*fVA81Elmj-ynOeIf44AKFw.png)
I am always excited to wait and see what the sun will do with the clouds as it goes down. This sunset did not disappoint.
![](https://cdn-images-1.medium.com/max/1024/1*MHTqf6T4wrnPmCnO_txhcQ.png)
The after sunset effects are always a treat when they work out well.
![](https://cdn-images-1.medium.com/max/1024/1*fW39G7knaLD13jxKDP1MCw.png)
I guess I was enjoying the sunset so much, along with a terrific dinner at the Quarterdeck restaurant, that I didn’t notice that I drank three IPAs with my dinner.
![](https://cdn-images-1.medium.com/max/1024/1*s47JRZ6Q_Bnl-DVf5kf_cg.png)
My wife drove us back to our hotel. After all of my driving the previous 15 days, I was happy to have the break.
No More Pictures, but Plenty of Memories
We checked out of our hotel at 10am as per the usual, and had our longest drive from Hilton Head Island, SC to Williamsburg, VA. It took us about 8 hours and I had to refill the gas tank once along the way. When we arrived in Williamsburg, we booked a reservation again at Mellow Mushroom and had a great dinner. The following morning, we checked out again, and decided to break our final drive home to New Jersey in half by stopping by Washington D.C. to have lunch with my wife’s uncle and aunt. After a nice lunch, we finished the drive back to New Jersey.
There were many other amazing things we did on this trip, like driving up the A1A in Florida from Palm Coast to St. Augustine. We also drove up the A1A from Pompano Beach through Boca Raton up to Palm Beach when we were headed to Singer Island. We also drove the A1A down to Ft. Lauderdale from Pompano Beach on our way to Miami. Our goal was to see as many places and things as we could while we were driving. This trip was about the journey, not the destination. We enjoyed every single minute of the drive, and there were a shit ton of minutes for us to enjoy.
I always wanted to take a slow walk road trip with my wife down the east coast. We’ve now done it, and I feel like we’ve bridged a gap in our lives. We are both ready to try some trips from east to west. I once drove from San Diego to New Orleans with my brother over the course of a week. We took one path that I enjoyed but would not take again. I would like instead to drive along the famed Route 66. The trick is that you need more time to enjoy the journey. One week is not enough. Three weeks lets you take your time and see more stuff.
Thanks for reading and I hope you enjoyed the selection of pictures I used to tell my January 2024 road trip story!
I am the creator of and committer for the Eclipse Collections OSS project, which is managed at the Eclipse Foundation. Eclipse Collections is open for contributions.
Accessibility in Diagram Editors with Eclipse GLSP
by Jonas, Maximilian & Philip at February 07, 2024 12:00 AM
In an exciting collaboration with Dr. Dominik Bork and master student Aylin Sarioglu at the Business Informatics Group at Vienna University, we’ve achieved a new pivotal capability in GLSP 2.0: an …
The post Accessibility in Diagram Editors with Eclipse GLSP appeared first on EclipseSource.
February 04, 2024
LiClipse 11: newer PyDev and on to new Eclipse base (4.30)
by Fabio Zadrozny (noreply@blogger.com) at February 04, 2024 11:39 AM
LiClipse 11 is now out and includes the newer version of PyDev, which has a whole new debugging mode using sys.monitoring (which translates to a much faster debugging experience overall -- see: https://pydev.blogspot.com/2024/02/pydev-debugger-and-sysmonitoring-pep.html for more details).
Also, it is now based on Eclipse 4.30 -- this time it was actually quite tricky as there are some internal changes to Eclipse itself which had to be changed in a bunch of places (the @Inject is now from jakarta instead of javax and the orbit aggregation site changed).
One pretty important note I haven't commented before is that now LiClipse is signed on Mac OS too (not just Windows).
Unfortunately Eclipse suffers a bit from that because after signing it's expected that nothing inside the .app will change. This means that quite some work was done so that .pyc files are not created inside the app anymore and nothing changes there -- unfortunately at this points additional plugins on top of LiClipse can not be installed when using Mac OS (I'm still researching on alternative approaches here).
On a separate note, it's been quite a while since I haven't posted about LiClipse itself... I guess this boils down to the fact that most of the work ends up happening on PyDev or LiClipseText directly -- but rest assured that work is indeed happening here 😉!
by Fabio Zadrozny (noreply@blogger.com) at February 04, 2024 11:39 AM
January 31, 2024
Eclipse GLSP 2: Elevating Web-based Diagram Editors
by Jonas, Maximilian & Philip at January 31, 2024 12:00 AM
We are excited to announce the recent release of Eclipse GLSP 2! This new major release marks a significant advancement in the domain of web-based diagram editors offering an impressive array of new …
The post Eclipse GLSP 2: Elevating Web-based Diagram Editors appeared first on EclipseSource.
January 30, 2024
Eclipse and OpenAtom: Pioneering Open Source Innovation
by Mike Milinkovich at January 30, 2024 12:55 PM
We’re thrilled to share that the Eclipse Foundation has signed a collaboration agreement with the OpenAtom Foundation, China’s first open source foundation. Together, we will be driving the development of Oniro, an open source project that builds upon the versatile OpenHarmony operating system. Our aim is to create a modular and globally compatible operating system platform and ecosystem, catering to a wide spectrum of smart devices.
Oniro is more than an open source project. To our knowledge, this marks the first instance of two open source foundations engaging in such detailed technical collaboration – a significant step towards cultivating a global ecosystem for open intelligent devices. The collaborative approach not only ensures a competitive landscape, but also opens doors for participation by organisations worldwide, affirming the far-reaching impact of open source on technical innovation.
OpenHarmony: A Robust Platform
OpenHarmony shines in its versatility, offering robust support for a wide array of smart devices that not only showcases scalability, but also highlights its adaptability. Designed for scalable management of distributed systems, OpenHarmony stands out as a flexible platform capable of accommodating IoT solutions of varying scale.
In recent years, OpenHarmony has made some noteworthy advancements. It’s been certified in over 200 devices and now supports more than 40 development boards. With a vibrant community of over 6,200 contributors and over 16 million lines of code, it has fostered 42 distributions and played a pivotal role in launching over 200 devices.
Oniro: Tailoring OpenHarmony for Western Markets
The goal of the Oniro Project is to elevate the OpenHarmony platform by developing a suite of Western market-focused modifications and add-ons, while preserving compatibility with the core platform. This dynamic collaboration encompasses advancements in application frameworks, system-level components, software development tools, and a toolchain ensuring adherence to regulatory compliance, intellectual property compliance, and licensing.
As per Statista’s 2023 forecast, the worldwide count of connected devices is anticipated to nearly double by 2030, reaching an impressive 29.42 billion IoT devices. Oniro is well positioned to actively participate in this expansive growth with strong execution of the 3 fundamental principles on which this project is built: seamless interoperability, modularization, and a visually appealing user interface. These principles not only embody the core mission of Oniro, but also position it as the go-to option for a broad range of applications, including consumer electronics, home appliances, industrial IoT devices, smart home devices, and multimedia devices.
Join the Innovation Journey
As OpenHarmony and Oniro join forces, exciting times are ahead. We invite you to be part of this journey, contribute your ideas, and participate in the magic that unfolds when open source organisations collaborate. Stay tuned for more updates as we collectively build a future where innovation knows no bounds!
January 29, 2024
Running Eclipse Theia without a backend
by Jonas, Maximilian & Philip at January 29, 2024 12:00 AM
When hosting cloud-based tools and IDEs, backend efficiency and cost-effectiveness are a key consideration. We are excited to present an ongoing development in the Eclipse Theia project that not only …
The post Running Eclipse Theia without a backend appeared first on EclipseSource.
January 26, 2024
Announcing Eclipse Ditto Release 3.5.0
January 26, 2024 12:00 AM
The Eclipse Ditto team wished you a happy new year and is excited to announce availability of Ditto 3.5.0.
In 3.5.0 a lot of UI improvements are contained and several smaller but very useful features were added.
Thanks a lot to the contributors who contributed to this release, this is really appreciated.
Adoption
Companies are willing to show their adoption of Eclipse Ditto publicly: https://iot.eclipse.org/adopters/?#iot.ditto
When you use Eclipse Ditto it would be great to support the project by putting your logo there.
Changelog
The main improvements and additions of Ditto 3.5.0 are:
Eclipse Ditto 3.5.0 focuses on the following areas:
- Search in the history of a single thing using an RQL filter
- Configure per namespace the fields to index in Ditto’s search index
- Configure defined search count queries to be exposed as Prometheus metrics by Ditto periodically
- Providing new placeholder functionality to the time placeholder, being able to add and subtract to/from the current time and to truncate the time to a given unit
- Enhance WoT (Web of Things) JSON skeleton creation to be able to fail with an exception on invalid WoT models
- Provide negative numbers when querying for the historical events of an entity (thing, policy, connection) in order to e.g. get “latest 10” events
- UI enhancements:
- Show policy imports in Ditto explorer UI
- Enhance UI Operations functionality to be able to perform devops/piggyback commands
- Allow editors in UI to toggle full screen mode
- Display attributes in UI inside a JSON editor in order to correctly display structured JSON payloads
- Enhance “Incoming Thing Updates” section by displaying “Action” and “Path” in the table and adding a dropdown to select the amount of details to show per event
- Add client side filter option for filtering Incoming Thing Updates and Connection logs
The following non-functional work is also included:
- Configured docker-compose to by default retain only the last 50m of log messages per Ditto service
- Migrated SLF4J to version 2.x and logback to version 1.4.x
- Benchmark tool improvements and fixes
- Improve cluster stability when running in Kubernetes, e.g. on updates or k8s node-shutdowns
The following notable fixes are included:
- Fix enriching Thing creation events with the inlined
_policy
- Fixed that Ditto’s own calculated “health” was not exposed to the
/alive
endpoint scraped by Kubernetes to check for aliveness of single services - Fixed that no cache was used when updating the search index when an “imported” policy was modified
Please have a look at the 3.5.0 release notes for a more detailed information on the release.
Artifacts
The new Java artifacts have been published at the Eclipse Maven repository as well as Maven central.
The Ditto JavaScript client release was published on npmjs.com:
The Docker images have been pushed to Docker Hub:
- eclipse/ditto-policies
- eclipse/ditto-things
- eclipse/ditto-things-search
- eclipse/ditto-gateway
- eclipse/ditto-connectivity
The Ditto Helm chart has been published to Docker Hub:
–
The Eclipse Ditto team
January 22, 2024
Unveiling the Power of Open VSX: An Open Hub for Top VS Code Extensions
by John Kellerman at January 22, 2024 07:12 PM
Open VSX is an open source registry for VS Code extensions, providing a decentralized and community-driven alternative to the Visual Studio Code Marketplace. Created to foster collaboration and innovation, Open VSX offers developers a space to share, discover, and contribute to a growing repository of extensions. Open VSX offers a curated selection of extensions that caters to various programming languages and development workflows. It's not about quantity; it's about quality and relevance to the community's needs.
![open-vsx.org](https://blogs.eclipse.org/sites/default/files/styles/large/public/2024-01/Screenshot%202024-01-24%20at%208.23.17%E2%80%AFPM.png?itok=TWbfpddT)
Open VSX boasts a collection that includes all of the most popular (top 100) VS Code extensions available on the Visual Studio Code Marketplace under open source licenses. These extensions cover a wide range of functionalities, from code formatting and linting to language support, debugging, and version control. For example, you can find extensions for editing and debugging Python and Jupyter notebooks, editing and debugging Java, and Gitlens, a powerful tool for improved collaboration and productivity with Git.
What sets Open VSX apart is its commitment to openness and inclusivity. Anyone can contribute to the platform and its extensions can be used in any compatible IDE, making it a true reflection of the diverse needs and preferences of the developer community.
Open VSX stands as a testament to the collaborative spirit of the developer community. It's not just a registry; it's a thriving ecosystem where developers come together to elevate their coding experience.
If you'd like to become part of the Open VSX community, consider publishing an extension; contributing to one of the projects that comprise the deployment, eclipse/openvsx, EclipseFdn/open-vsx.org, and open-vsx/publish-extensions; subscribe to our mailing list; or join us as part of the Open VSX Working Group.
Eclipse Cloud DevTools Contributor Award 2023 goes to EclipseSource and TypeFox
by John Kellerman at January 22, 2024 02:45 PM
The Eclipse Cloud DevTools Contributor Award for the year 2023 is being jointly awarded to two remarkable companies, EclipseSource and TypeFox, in acknowledgment of their enormous, continuous, strategic, and sustainable contributions to the Eclipse Cloud DevTools ecosystem.
Throughout 2023, EclipseSource and TypeFox have demonstrated exceptional commitment and expertise in various projects within the ecosystem, including Eclipse Theia, CDT Cloud, Eclipse GLSP, Eclipse Sprotty, EMF Cloud, and Eclipse Langium. Their leadership role is evident as they provide project leads and several committers to these open source projects. Their excellence was already recognized in monthly awards in January, July, October, and December, showcasing their consistent and impactful contributions.
Their involvement in the Eclipse Cloud DevTools ecosystem is not just technical; both companies have been pivotal in strategic initiatives, which significantly supported the growth of the community and nurtured the adoption of its open-source technologies sustainably. As active participants and leading architects in the Eclipse Cloud DevTools working group, they have shown foresight in shaping the future of cloud development tools.
TypeFox and EclipseSource play a unique and vital role in the ecosystem. As service providers specializing in building tools and IDEs, they provide an essential resource for companies aiming to develop their own tool offerings. Their investment in the maintenance and evolution of projects in the ecosystem is therefore not only a testament to their dedication but also strategically vital for their operations.
In addition to their extensive contributions, EclipseSource and TypeFox provide a unique model of sponsored open source development. By contracting a service provider for sponsored development, adopters can directly engage experts who contribute to open source projects on their behalf, enabling a highly tailored and impactful approach to advancing open source initiatives that are of strategic importance for the adopter. This allows other companies to leverage the expertise of EclipseSource and TypeFox for specific fixes, feature developments, and general project maintenance, enabling a broader group of organizations to contribute to and strengthen the open-source ecosystem. The approach also allows for resource pooling, where multiple companies can collectively sponsor a full-time expert committer, thereby enhancing the efficiency and impact of contributions. The model of sponsored development has proven to be highly successful in the Eclipse Cloud DevTools Ecosystem, leading to increased and more sustainable contributions, thereby significantly enriching the ecosystem.
Project websites contain information about which companies provide support and sponsored development.
Service providers like EclipseSource and TypeFox are cornerstone elements of a thriving open-source ecosystem. They offer important support for custom projects and play a crucial role in fostering sponsored development for open-source components. We congratulate and thank both EclipseSource and TypeFox for being the recipients of the Eclipse Cloud DevTools Contributor Award for the year 2023. Your consistent dedication and impactful contributions have significantly advanced the Eclipse Cloud DevTools landscape, and we are profoundly grateful for your commitment and excellence.
This Eclipse Cloud DevTools contributor award is sponsored by the Eclipse Cloud DevTools Working Group. The working group provides a vendor-neutral ecosystem of open source projects focused on defining, implementing and promoting best-in-class web and cloud-based development tools. It is hosted at the Eclipse Foundation, current members of the group include AMD, Arm, EclipseSource, Ericsson, Obeo, RedHat, Renesas, STMicroelectronics and TypeFox.
Hosting IDEs and tools online - lessons learned
by Jonas, Maximilian & Philip at January 22, 2024 12:00 AM
The transition to cloud-based tools and IDEs is reshaping the landscape of software development. However, the details of hosting tools and IDEs online present unique challenges. If you’re considering …
The post Hosting IDEs and tools online - lessons learned appeared first on EclipseSource.
January 18, 2024
CDT Cloud Blueprint: Tracing with TraceCompass Cloud
by Jonas, Maximilian & Philip at January 18, 2024 12:00 AM
In the world of C/C++ development, especially when doing performance tuning, tracing plays a pivotal role. CDT Cloud Blueprint, the web-based C/C++ development environment, provides advanced Tracing …
The post CDT Cloud Blueprint: Tracing with TraceCompass Cloud appeared first on EclipseSource.
January 17, 2024
Eclipse Cloud DevTools Digest - November and December 2023
by John Kellerman at January 17, 2024 07:57 PM
Theia Announces Full Compatibility with VS Code Extension API
![Theia IDE](https://theia-ide.org/static/theia-screenshot-6feea3c00c8e1ee681e38a48d927f51b.png)
In his blog, Mike Milinkovich announced a significant achievement in the development of Theia: to wit, full compatibility with the Visual Studio Code (VS Code) extension API. This is a major milestone in the evolution of Theia toward a universally adaptable development environment.
Contributor Awards to Tobias Ortmayr and Dominik Bork
The Cloud Dev Tools Working Group presented Contributor of the Month awards to Tobias Ortmayr for his continued work improving the performance of Theia and to Dominik Bork bringing academia, industry and open source closer together.
On Building Cloud Native Modeling Tools
Jonas, Maximilian & Philip, in this article, wrote about a talk they gave at EclipseCon 2023 on building cloud native modeling tools using modern web-based open source technologies like EMF Cloud, Langium and GLSP.
On Building Diagrams with GLSP
![](https://eclipse.dev/glsp/images/diagramanimated_compact.gif)
In another article, Jonas, Maximilian & Philip also write about another talk they gave at EclipseCon 2023 about building diagramming tools using GLSP that are more testable, collaborative, and accessible (through improved keyboard navigation and metadata annotations).
Theia Releases 1.44 and 1.45
Theia released 1.44 and 1.45 adding support for a "portable mode" keeping user data with the Theia application, language icons, improvements for secondary windows, search history, and saving untitled files.
Theia Community Release 2023-11
Theia also released their Community Release 2023-11 based on Theia 1.43. Community releases are provided once a quarter with a dedicated release branch that allows contributors to further harden and even hotfix a community release. To learn more about the advantages of the Theia community release, visit the Theia release page.
Other Recent Releases
Cloud Tool Time Webinars
We are now scheduling Cloud Tool Time webinars for 2023. Be sure to Sign up now to get on the calendar and let us help tell your story. You can see past sessions on our Youtube channel.
Eclipse Cloud DevTools Projects
![Eclipse Cloud DevTools](https://blogs.eclipse.org/sites/default/files/2023-07/Cloud%20DevTools.png)
Explore the Eclipse Cloud DevTools ecosystem! Check out our projects page to find out more about open source innovation for cloud IDEs, extension marketplaces, frameworks and more.
Getting Listed on the Cloud DevTools Blog
If you are working with, or on, anything in the Cloud DevTools space, learn how to get your writings posted in our blog section.
What if Java had no for?
by Donald Raab at January 17, 2024 03:10 AM
These loops look like objects to me!
Where for art thou?
This blog is intended to make you think about and discover alternatives to modeling for loops in an object-oriented (OO) programming language. It is convenient to have a versatile and performant eager for statement built in the Java language. It is also convenient to have lazy versions of numeric range based for loops in the form of IntStream and LongStream.
In my previous blog, I introduced a new lazy abstraction for an int range based for loop, without giving much of an explanation. This is the quote in the previous blog where I introduced the concept.
In the active Boolean version of the the code, I use an IntInterval from Eclipse Collections to represent an OO version of the for loop.
I will explain what an IntInterval from Eclipse Collections is later in the blog.
The following are the topics I will cover in this blog.
In this blog, I explain some of the versatility of for statements in Java with examples. I explain how some of the language (lambdas) and library (Streams) work including in Java 8 release have improved the level of abstraction of looping constructs for Java developers. Java does not go as far as Smalltalk does on the OO abstraction level for looping constructs. I show and explain how Smalltalk makes some things amazingly simple in its pure object-oriented approach to looping. Finally, I explain some features that Eclipse Collections provides that enables additional levels of abstraction for Java developers to enhance their productivity.
This blog does not include anything about parallelism.
1. For Loops in Java
Three parts of the for
Looping is part of control flow in a programming language. For loops are used to do things until a condition is met, or infinitely if no condition is specified. There is a for statement in Java that is well structured and extremely useful for executing a block of code a number of times. The example I used in the previous blog was to output a String parameter a specified number of times.
public static void main(String[] args)
{
int numberOfTimes = Integer.parseInt(args[0]);
for (int i = 0; i < numberOfTimes; i++)
{
System.out.println(args[1]);
}
}
The code will throw an exception if less than two arguments are passed in. This code will output the String at args[1] the number of times specifed at args[0]. The String at args[0] is converted to an int and stored in the variable numberOfTimes.
The structure of a for loop in Java includes three statements inside of parentheses after the for keyword, each separated by a semi-colon. The statements are as follows.
- Initialization— executed once to initialize one or more variables
- Continue Condition — a boolean expression that when true will continue to loop and when false will cause the loop to exit
- Advancement Expression— an expression that may cause a change in the result of the Continue Condition, like incrementing or decrementing a counter or calling next on an Iterator.
For example — Summing numbers 1 to 10
A very simple example of a for loop in Java is summing the numbers from 1 to 10. The following test is an example of this.
@Test
public void sumNumbersFromOneToTen()
{
int sum = 0;
for (
int i = 1; // Intialization
i <= 10; // Continue Condition
i++) // Advancement Expression
{
sum += i;
}
Assertions.assertEquals(55, sum);
}
For example — Summing numbers 10 to 1
This code could also be written as summing the numbers from 10 to 1. The following test is an example of this.
@Test
public void sumNumbersFromTenToOne()
{
int sum = 0;
for (
int i = 10; // Intialization
i > 0; // Continue Condition
i--) // Advancement Expression
{
sum += i;
}
Assertions.assertEquals(55, sum);
}
Inlining the three statements
I previously broke the three expressions over multiple lines so they are easy to parse and read. Normally, the expressions will all be on the same line, as follows:
// For loop from 1 to 10 incrementing by 1
for (int i = 1; i <= 10; i++)
// For loop from 10 to 1 decrementing by 1
for (int i = 10; i > 0; i--)
The for loop in Java is very versatile. Before the Java language had lambdas, the for loop was the preferred mechanism for iterating over an array or Collection.
Sum Array of ints —Indexed Access
The following for loop uses indices for summing up elements of an int array.
@Test
public void sumArrayOfIntsUsingIndexedAccess()
{
int sum = 0;
int[] array = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
for (
int i = 0; // Intialization
i < array.length; // Continue Condition
i++) // Advancement Expression
{
sum += array[i];
}
Assertions.assertEquals(55, sum);
}
Sum Array of ints — Java 5 for loop
The following for loop uses the simplified version of the for loop introduced in Java 5 for iterating over each element of a an int array.
@Test
public void sumArrayOfIntsUsingForEachLoop()
{
int sum = 0;
int[] array = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
for (int each : array)
{
sum += each;
}
Assertions.assertEquals(55, sum);
}
The first part of the for loop includes the type and name of a varaible for each element in the array. In this case, I use int each.The second part, separated by a :, is the array to loop over.
Sum List of Integers — Indexed Access
If we have a List of Integer objects, we have a few ways we can write a for loop to calculate the sum. We can loop using indexed access.
@Test
public void sumListOfIntegersUsingIndexedAccess()
{
int sum = 0;
List<Integer> list = List.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
for (
int i = 0; // Intialization
i < list.size(); // Continue Condition
i++) // Advancement Expression
{
sum += list.get(i).intValue();
}
Assertions.assertEquals(55, sum);
}
Sum List of Integers — Iterator
We can loop using an explicit iterator.
@Test
public void sumListOfIntegersUsingIterator()
{
int sum = 0;
List<Integer> list = List.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
for (
Iterator<Integer> it = list.iterator(); // Intialization
it.hasNext(); // Continue Condition
// No Advancement Expression
)
{
sum += it.next().intValue(); // Advancement in statement via next()
}
Assertions.assertEquals(55, sum);
}
Sum List of Integers — Java 5 for loop
We can loop using the enhanced for loop available since Java 5, which is really a shorthand for using the iterator approach above.
@Test
public void sumListOfIntegersUsingJava5ForLoop()
{
int sum = 0;
List<Integer> list = List.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
for (Integer each : list)
{
sum += each.intValue();
}
Assertions.assertEquals(55, sum);
}
All for one, and for for all
The versatile nature of a for loop makes it a tough competitor for looping. Oleg Pliss commented on my post of this article in LinkedIn:
A few important features of ‘for’ loops are missing in the article: access to the locals outside the loop; ‘continue’ and ‘break’ statements (potentially with a label); and ‘return’ (from the method).
This is some of what I was alluding to by the versatility of the for statement, and Oleg did a masterful job of identifying the functionality I did not cover in a single sentence. Here are links to further tutorials on for and the branching statements I didn’t cover here for those interested in learning more.
In the rest of the blog I will demonstrate how for loops are implemented in Smalltalk, and show how in Java 8 and with Eclipse Collections, Java has advanced towards a more object-oriented and functional model of for loops. I have been working on replacing unnecessary for loops in Java applications for the past 20 years as I explain in the following blog. Usually there is a higher level algorithm like filter, map, or reduce that is implemented imperatively with a for loop. It’s more readable if you can hide the implementation details of a for loop behind a higher level abstraction that explains what you are doing with an intention revealing name. It’s also potentially better for performance for different types to optimize for specific iteration patterns, instead of requiring developers to write different for loops for different types because one is faster with indexed access vs. being faster with an iterator.
My ten year quest for concise lambda expressions in Java
2. OO For Loops in Smalltalk
The following is a quote from my last blog about Smalltalk and control flow.
Smalltalk is a programming language that models control flow in its class library, instead of the language. There are no if statements, for loops, while statements in Smalltalk. There are instead methods on classes that make control flow possible. Methods are the abstraction that are used to model all control flow, along with code blocks, which are also known as lambdas or closures.
An object-oriented version of a for loop will result in looping behavior distributed across many classes. The behavior of different kinds of for loops are aligned with the object that makes the most sense to be responsible for that behavior.
There are both eager and lazy forms of a for loop in an object-oriented model. The statement version of a for loop in Java is always eager.
Smalltalk Interval — sum
I will start by showing how to sum the numbers from 1 to 10 using Smalltalk’s Interval type. Interval is a lazy for loop. Interval is also a lazy SequqencedCollection.
testSumNumbersFromOneToTen
|sum|
sum := (1 to: 10) sum.
self assert: sum equals: 55.
In my two previous “What if…” blogs, I explained that “everything is an object” in Smalltalk. I will explain one step at a time what all the objects are in the code above, and which are receiving the messages that are accomplishing the task at hand.
The first object instance encountered in the code is the literal 1. The object instance represented by the literal 1 is of type SmallInteger. The message to: is sent to the object 1 with the parameter 10, which is also an instance of SmallInteger. If I inspect the result of the code (1 to: 10) in Pharo Smalltalk, the result is an instance of an Interval. The following is a screen capture of the result.
![](https://cdn-images-1.medium.com/max/699/1*mjt98JF-ZoI0CmwRbilpkw.png)
Interval is lazy because it knows about the range of data (1 to 10 by 1) but has yet to do anything with that data. The Interval class in Smalltalk is designed as follows.
![](https://cdn-images-1.medium.com/max/697/1*XsoeJxpnVuy59sWC2KQH9A.png)
The decision to make Interval a SequencedCollection brings a lot of convenience. The internal iterator support for Interval is extensive. There are class methods on Interval which allow for construction. The convenient shorthand I used about calling to: on SmallInteger can be searched in the Smalltalk class library quickly to show how the Interval is constructed.
![](https://cdn-images-1.medium.com/max/854/1*vYtX-stsqxCNwmRqiGPINA.png)
The ^ means return in Smalltalk, so the code 1 to: 10 is going to result in Interval from: 1 to: 10 by: 1. An Interval in Smalltalk is inclusive for both the start and stop.
The final step to understanding how the loop itself is implemented in the sum of the integers from 1 to 10 example is to look at the sum method.
![](https://cdn-images-1.medium.com/max/862/1*wFDoAyyyDy68FEiLCEEqCw.png)
What we discover here is that sum is optimized for Interval. It uses a formula instead of iteration with a loop. This is one of the benefits of having loops represented by objects. They can provide encapsulate and optimized behaviors.
Smalltalk Interval — do:
In the interest of demonstrating the actual loop, I will implement an iterative sum by hand in a test.
testSumNumbersFromOneToTenWithDo
|sum|
sum := 0.
(1 to: 10) do: [ :each | sum := sum + each ].
self assert: sum equals: 55.
I use the do: method here with a Block (lambda) which updates the sum variable with the value of sum plus the value of each SmallInteger. The implementation of do: on Interval looks as follows.
![](https://cdn-images-1.medium.com/max/921/1*ltFcpg3oBEKD12eUV_NgUQ.png)
The implementation of do: uses a Block (Condition Continue Block) with whileTrue: followed by Block (Execution Block) to perform the looping. The Condition Continue Block and Execution Block both require access to the index variable which is scoped outside of the blocks, and the Execution Block actually increments the index variable. I will not be implementing whileTrue: for educational purposes in Java as it would require using a final int array or AtomicInteger, LongAdder or equivalent for index to be able to be incremented. There is a tweet reply from Vladimir Zakharov that shows how whileTrue could be implemented on a Functional Interface if someone wanted.
Smalltalk Interval — inject:into:
There is another internal iterator that I can use in Smalltalk that will not require updating a local variable for each element in the Interval. That method is named inject:into:, or as I like to call it, the Continuum Transfunctioner. Here is a sum implemented using inject:into:.
testSumNumbersFromOneToTenWithInjectInto
|sum|
sum := (1 to: 10) inject: 0 into: [ :result :each | result + each ].
self assert: sum equals: 55.
The way the above inject:into: code works can be explained as follows as each element is visited in the Interval.
result := 0
result + each = ?
=================
0 + 1 = 1
1 + 2 = 3
3 + 3 = 6
6 + 4 = 10
10 + 5 = 15
15 + 6 = 21
21 + 7 = 28
28 + 8 = 36
36 + 9 = 45
45 + 10 = 55
The result of each iteration is “injected” into the block for the next iteration as the first parameter. The implementation of inject:into: for the Interval class in Pharo Smalltalk is as follows.
![](https://cdn-images-1.medium.com/max/795/1*Fpy7xY_0sO5Bd5wS4HNNtg.png)
Smalltalk Interval —in reverse order
In order to reverse an Interval, I will need to add a negative step value using the to:by: method on SmallInteger as follows.
testSumNumbersFromTenToOne
|sum|
sum := (10 to: 1 by: -1) sum.
self assert: sum equals: 55.
There are also methods named reverseDo: and reversed on Interval which can take forward Interval and walk through it in reverse. The reversed method will wind up creating an array in reverse, which is why I didn’t demonstrate it here.
Smalltalk Interval — Any Number
The abstraction of Interval and the benefits of dynamic typing really become evident when you learn about the existence of Fraction in Smalltalk. Take the code 1/3 in Smalltalk. If you execute this code in Java for an int, you will expect a result of 0. The following is the result in Pharo Smalltalk.
![](https://cdn-images-1.medium.com/max/666/1*5zzW64Cb3BO4z4Ho21orhw.png)
If we want to represent a range from 1 to 10 by 1/4, we can achieve this simply by writing the following code.
![](https://cdn-images-1.medium.com/max/731/1*f6jWmv-EZS-k5u89gGyy3A.png)
Interval will support any number, so understanding the types of Number that are provided in Smalltalk is helpful. The following class diagram shows the hierarchy for Number in Pharo Smalltalk.
![](https://cdn-images-1.medium.com/max/1024/1*w4hFhc46YwjDawYCsh9RKQ.png)
Smalltalk Interval — More than just a loop
The Interval abstraction provides more than just a lazy for loop. Interval is a lazy Collection. All of the algorithms available to SequencedCollection are also available to Interval. For example, it’s possible to collect all of the numbers in an Interval as a collection of String.
testPrintString
|strings expected|
strings := (1 to: 5) collect: #printString.
expected := Array with: '1' with: '2' with: '3' with: '4' with: '5'.
self assert: strings equals: expected.
The method named collect: is defined on Collection, and can be used to transform from one type to another. Here I am converting SmallInteger to String by applying the method printString to each element of the Interval.
The following code filters the even values of an Interval using the select: method, and then converts the SmallInteger values to their square values and converts them to an array of String.
testEvensPrintString
|strings expected|
strings := ((1 to: 10) select: #even) squared collect: #printString.
expected := Array with: '4' with: '16' with: '36' with: '64' with: '100'.
self assert: strings equals: expected.
Smalltalk — Number meets Collection
Looping with a range of values in Interval is useful but somewhat limited. Looping over a collection of arbitrary values is more useful. There are many methods available on the Collection class that provide internal iterators. I am going to show what some of these methods do, and then explain how they do them. The how is where an eager loop provided by the Number class in a method named to:do: arrives.
The following is the method for do: in OrderedCollection, which is one of the most commonly uses collection types in Smalltalk. OrderedCollection in Smalltalk is the equivalent of ArrayList in Java.
![](https://cdn-images-1.medium.com/max/539/1*bi9kM_kSfG-Ws3KqdtGMVA.png)
The method do: is the equivalent of forEach defined on Iterable in Java. In this code, the first part, firstIndex to: lastIndex do: calls the to:do: method on Number. The code for to:do: looks as follows.
![](https://cdn-images-1.medium.com/max/813/1*Xst0Sez8EYNBd0X_SDEr_g.png)
This code uses a Block whileTrue: method to execute another Block the number of times covered by the range from self to stop. If we go back to look at the do: method in Interval, it looks somewhat similar, but requires a bit more math due to Interval having a start, stop and step value.
![](https://cdn-images-1.medium.com/max/869/1*7fCZ94w8xzQuc9EiVav01A.png)
The following code looks very similar, but winds up taking two different paths. One goes through Number to:do:, and the other goes through Interval do:. See if you can figure out which is which.
1 to: 10 do: [:each | Transcript show: each].
(1 to: 10) do: [:each | Transcript show: each].
The code Transcript show: is the equivalent of System.out.print() in Java. If you guessed the first line uses Number to:do: and the second uses Interval do:, then you are correct, and I am finished with the Smalltalk part of the Interval, Number, and Collection looping.
3. OO For Loops in Java
Since Java 8, we have IntStream and LongStream, both which can represent lazy for loops over a range of int or long values.
Java IntStream — range sum
The method range on IntStream is inclusive on the from and exclusive on the to.
@Test
public void sumIntStreamRangeOneToElevenExclusive()
{
int sum = IntStream.range(1, 11).sum();
Assertions.assertEquals(55, sum);
}
Java IntStream — rangeClosed sum
The method rangeClosed on IntStream is inclusive on both the from and the to.
@Test
public void sumIntStreamRangeClosedOneToTenInclusive()
{
int sum = IntStream.rangeClosed(1, 10).sum();
Assertions.assertEquals(55, sum);
}
Both calls to sum on IntStream have a potential silent overflow issue to be aware of. It would have been better if IntStream sum returned a long value. So long as your sum result is less than Integer.MAX_VALUE you will be ok. If it is greater than Integer.MAX_VALUE, the int value sum could wind up negative or some other unexpected positive value.
Java IntStream — forEach sum
IntStream is lazy, so you have to call a terminal method like sum or forEach to force iteration to happen. If we want to calculate a sum by hand, we can use the forEach method. With this version of sum, we can widen the result ourselves to long by using LongAdder.
@Test
public void sumIntStreamRangeClosedForEach()
{
LongAdder sum = new LongAdder();
IntStream.rangeClosed(1, 10).forEach(sum::add);
Assertions.assertEquals(55, sum.intValue());
}
I use the LongAdder class to create an instance of an object that will be effectively final and can be used as a method reference in the forEach. LongAdder internally keeps a long value. To illustrate how LongAdder handles larger numbers and avoids int overflow, where sum does not, I will create a small range in the billions.
@Test
public void sumIntStreamRangeClosedInBillions()
{
LongAdder sum = new LongAdder();
IntStream.rangeClosed(2_000_000_000, 2_000_000_001).forEach(sum::add);
Assertions.assertEquals(4_000_000_001L, sum.longValue());
// Overflow happened silently here with IntStream.sum
int intSum = IntStream.rangeClosed(2_000_000_000, 2_000_000_001).sum();
Assertions.assertEquals(-294_967_295, intSum);
}
Java LongStream — sum
Another alternative to IntStream.sum that is almost always safe from overflow is LongStream.sum. The following is an example of sum on LongStream.
@Test
public void sumLongStreamRangeClosedOneToTenInclusive()
{
long sum = LongStream.rangeClosed(1L, 10L).sum();
Assertions.assertEquals(55L, sum);
long bigSum = LongStream.rangeClosed(2_000_000_001L, 2_000_000_010L).sum();
Assertions.assertEquals(20_000_000_055L, bigSum);
}
Java IntStream — toList
If we want the elements of an IntStream to be represented in a List, we have to use the IntStream API to box the stream and convert it to a List<Integer>.
@Test
public void filterIntStreamRangeClosedEvensToList()
{
List<Integer> list = IntStream.rangeClosed(1, 10)
.filter(i -> i % 2 == 0)
.boxed()
.toList();
List<Integer> expected = List.of(2, 4, 6, 8, 10);
Assertions.assertEquals(expected, list);
}
Java Iterable — forEach
In Java 8, we got support for concise lambda expressions and the Java Stream API. We also got a forEach method on the Iterable interface, which allows all Collection types in Java to provide internal iterators that are optimized for each type.
The following code can be used to sum the List<Integer> of even numbers from 1 to 10 that I created above.
@Test
public void sumListOfEvensUsingForEach()
{
List<Integer> list = List.of(2, 4, 6, 8, 10);
LongAdder sum = new LongAdder();
list.forEach(sum::add);
Assertions.assertEquals(30L, sum.longValue());
}
4. OO For Loops in Eclipse Collections
One of the first custom Collection types I created in Eclipse Collections was the Interval class. I though it would be very useful to have a List<Integer> that you could create simply by specifying a range. I also thought it would be useful to have a full complement of rich internal iterators on Interval, so I had it also implement LazyIterable<Integer>. We have used Interval extensively in unit tests in Eclipse Collections. It is often the fastest way to create a List, Set, Bag, Stack or any other type where having some Collection of Integer is all we need. The following image shows the number of usages on Interval in the Eclipse Collections project.
![](https://cdn-images-1.medium.com/max/940/1*2LPVc3qsc7RobOeNXetMgQ.png)
There are ~1,900 usages in the tests module alone. The Interval class has proven itself very useful in Eclipse Collections unit tests.
Eclipse Collections Interval — sum
The following code will create an Interval from 1 to 10 and return a sum using sumOfInt. The method sumOfInt knows to widen the sum to a long.
@Test
public void sumIntervalOneToTen()
{
long sum = Interval.oneTo(10).sumOfInt(Integer::intValue);
Assertions.assertEquals(55L, sum);
}
Eclipse Collections Interval — sum evens
The following code will include only the even numbers from 1 to 10 and sum them.
@Test
public void sumIntervalEvensOneToTen()
{
long sum = Interval.evensFromTo(1, 10).sumOfInt(Integer::intValue);
Assertions.assertEquals(30L, sum);
}
Eclipse Collections Interval — as a List and as a LazyIterable
There are three possible types that Interval can be used as — Interval, List, LazyIterable.
@Test
public void intervalIsListAndLazyIterable()
{
Interval interval = Interval.oneTo(5);
List<Integer> list = interval;
LazyIterable<Integer> lazyIterable = interval;
Assertions.assertEquals(List.of(1, 2, 3, 4, 5), list);
Assertions.assertEquals(Set.of(1, 2, 3, 4, 5), interval.toSet());
Assertions.assertEquals(
Interval.oneTo(10),
lazyIterable.concatenate(Interval.fromTo(6, 10)).toList());
}
The following diagram shows the design of the Interval class in Eclipse Collections.
![](https://cdn-images-1.medium.com/max/914/1*hKzsPIpNY54bnyKBCFxxTg.png)
Eclipse Collections IntInterval — sum
Interval has proved itself extremely useful for quickly creating List<Integer> instances, especially in test code. For production use cases, where memory and performance matter, IntInterval may be a better alternative. IntInterval is an ImmutableIntList. The internal iterators on IntInterval are not lazy by default like Interval, but IntInterval does support lazy iteration via an explicit call to asLazy.
The following code shows how to calculate a sum using IntInterval using both eager and lazy approaches.
@Test
public void sumIntIntervalOneToTen()
{
IntInterval intInterval = IntInterval.oneTo(10);
long eagerSum = intInterval.sum();
LazyIntIterable lazy = intInterval.asLazy();
long lazySum = lazy.sum();
Assertions.assertEquals(55L, eagerSum);
Assertions.assertEquals(55L, lazySum);
}
I reuse the instance of IntInterval to create the LazyIntIterable, after already calculating the eager sum. I did this to illustrate that an IntInterval can be reused, unlike an IntStream from Java, which may only be used once.
Eclipse Collections IntInterval — usage
The usage of IntInterval in Eclipse Collections is more modest than Interval, but still quite good.
![](https://cdn-images-1.medium.com/max/937/1*zmpYhoXYT-ULXztnf0-neA.png)
Eclipse Collections LongInterval — sum
Eclipse Collections provides primitive Interval support for both int and long. The long support is provided by LongInterval.
The following code shows how to calculate a sum using LongInterval using both eager and lazy approaches.
@Test
public void sumLongIntervalBillionOneToBillionTen()
{
LongInterval longInterval =
LongInterval.fromTo(1_000_000_001L, 1_000_000_010L);
long eagerSum = longInterval.sum();
LazyLongIterable lazy = longInterval.asLazy();
long lazySum = lazy.sum();
Assertions.assertEquals(10_000_000_055L, eagerSum);
Assertions.assertEquals(10_000_000_055L, lazySum);
}
I reuse the instance of LongInterval to create the LazyLongIterable, after already calculating the eager sum. I did this to illustrate that a LongInterval can be reused, unlike a LongStream from Java, which may only be used once.
Eclipse Collections LongInterval — usage
The usage of LongInterval in Eclipse Collections is more modest than both Interval and IntInterval.
![](https://cdn-images-1.medium.com/max/939/1*tfRet3_zGX0w1CIH2Fyl_Q.png)
Eclipse Collections IntInterval and LongInterval Class Hierarchy
I have included both hierarchies for IntInterval and LongInterval in this diagram to show that they do ultimately share a root parent interface named PrimitiveIterable. The following is the UML class hierarchy for both IntInterval and LongInterval.
![](https://cdn-images-1.medium.com/max/1024/1*G_GyK1ZJruFyden8r9SwAQ.png)
There was an evolution in design approach from Interval to IntInterval and LongInterval. Interval was one of the earliest containers in Eclipse Collections, and was created before immutable and primitive types were added to the framework. Interval is heavily used already so it is too late to revisit its design as it would cause too much pain to convert it to an ImmutableList<Integer> just for consistency sake. This ship has sailed, and this is now just a historical implementation decision. There are things I continue to like about both design approaches.
Final Thoughts
I hope this blog helped you learn about different approaches and levels of abstraction for looping in an object-oriented language. I believe it is useful to have both language and library constructs available in Java to enhance the productivity of developers when it comes to looping.
Smalltalk takes a novel approach to implementing control flow that I found extremely insightful when I first learned about it in 1994. I hope the Smalltalk examples and explanations helped you learn something insightful about this venerable programming language. I believe there is still so much we can learn from the past in programming languages, and only by learning this storied past can we hope to create a better future for programmers.
I intentionally did not explain either eager parallel or lazy parallel looping in this blog. This can be a natural progression once you have understood how eager serial and lazy serial looping works using lambdas. The inclusion of lambdas in Java 8 has opened up many new possibilities for productivity enhancements for Java developers. I expect that we will continue to see improvements in the language and libraries of Java further leveraging this critical feature.
Thank you for reading!
I am the creator of and committer for the Eclipse Collections OSS project, which is managed at the Eclipse Foundation. Eclipse Collections is open for contributions.
January 15, 2024
The Choice of an IDE and Tool Platform: Eclipse Theia vs. Code OSS
by Jonas, Maximilian & Philip at January 15, 2024 12:00 AM
Building custom tools and IDEs are strategic and long term investments. Choosing the right platform for building custom tools and IDEs is a critical decision for stakeholders. To aid in this crucial …
The post The Choice of an IDE and Tool Platform: Eclipse Theia vs. Code OSS appeared first on EclipseSource.
Collaborative Specification Development
January 15, 2024 12:00 AM
January 08, 2024
The Eclipse Theia Project Update 2023
by Jonas, Maximilian & Philip at January 08, 2024 12:00 AM
2023 has been an extraordinary year for the Eclipse Theia project, marked by significant community advancements and key feature enhancements such as the improved startup performance, the introduction …
The post The Eclipse Theia Project Update 2023 appeared first on EclipseSource.
January 03, 2024
Add views to a Langium-powered VS Code extension
January 03, 2024 12:00 AM
December 29, 2023
Eclipse Theia 1.45 Release: News and Noteworthy
by Jonas, Maximilian & Philip at December 29, 2023 12:00 AM
We are happy to announce the Eclipse Theia 1.45 release! The release contains 28 merged pull requests and we welcome four new contributors. In this article we will highlight some selected improvements …
The post Eclipse Theia 1.45 Release: News and Noteworthy appeared first on EclipseSource.
December 28, 2023
Understanding Software Provenance Attestation: The Roles of SLSA and in-toto
December 28, 2023 02:00 PM
A software provenance attestation is a signed document that associates metadata with an artifact, encompassing details like the artifact’s origin, build steps, and dependencies. This information is critical for verifying the artifact’s authenticity and integrity. Featuring a cryptographic signature, provenance attestation ensures the document remains unaltered, playing a vital role in mitigating supply chain attacks. By scrutinizing the provenance of binaries, users can thwart the execution of malicious code on their systems. Let’s delve into some concrete examples:
-
Case of Compromised Package Manager: Imagine a scenario where an attacker gains access to a developer’s package manager account for a widely-used open-source software library. The attacker injects malicious code, builds, and publishes an updated library version. As users update the library, the malicious code spreads. With provenance attestation, users would have noticed discrepancies in the attestation, revealing the code did not originate from the official source. This proactive measure could have averted incidents like the UAParser.js library hijacking in 2021.
-
Software Supplier Compromise Example: Consider an attacker targeting a software supplier and tampering with their product. When customers use this compromised product, it could lead to further software breaches or data exfiltration. The CodeCov attack serves as a pertinent example. Here, a malicious
bash uploader
artifact was uploaded to CodeCov’s repository. Unknowingly downloaded and used this artifact by users resulted in stolen Git credentials and amplified the supply chain attack. Provenance attestation would have enabled users to detect the anomaly and prevent the execution of the malicious code.
Exploring SLSA
SLSA (Supply chain Levels for Software Artifacts) is a framework that enhances the security of software supply chains by defining levels for software projects to aspire to. It emphasizes the generation, distribution, and verification of provenance information.
The framework currently offers three Levels under the Build track in its 1.0 version. However, it’s beneficial to revisit the initial v0.1 draft for a broader understanding of SLSA’s scope and future direction.
SLSA aims to shield against tampering at various stages of the software supply chain. The initial levels presented a progressive approach to mitigating these threats. The higher the level, the more robust the supply chain security. The requirements for each level were comprehensive and provided a clear progression path.
![SLSA v0.1 Requirements](https://mikael.barbero.tech/blog/post/2023-12-28-slsa-and-in-toto/slsa-v0.1-requirements.png)
The 1.0 version narrowed its focus to the Build and Provenance requirements. The introduction of “tracks” allows for future expansion, with the newly created Build track being the sole focus in this version. Each track’s levels will eventually measure different aspects of supply chain security.
SLSA 1.0 refined the division of requirements between the project and the build platform. Achieving a higher Level in the Build Track implies greater trust in the Provenance information, thereby offering better protection against threats. The project requirements in the build track are now more straightforward, largely depending on the build platform’s ability to produce provenance that meets the level’s criteria.
![SLSA v1.0 Build Track Requirements](https://mikael.barbero.tech/blog/post/2023-12-28-slsa-and-in-toto/slsa-v1.0-build-track-requirements.png)
Introducing in-toto
in-toto is a framework centered around software attestations, focusing on the generation and verification of metadata of the software supply chain. Developers and stakeholders generate metadata reflecting actions like coding and testing. The project owner creates a layout, a critical document that defines the supply chain’s expected steps and corresponding metadata.
Key components of in-toto include the layout (a JSON document outlining expected the supply chain), functionaries (individuals or automated processes executing steps), and inspections (operations that need to be performed on the final product at the time of verification).
While similar to SLSA, in-toto offers broader attestation capabilities than just about provenance information and without specific guidance against a threat model, as seen in SLSA. It provides a standard format for outlining supply chain expectations and realities.
SLSA and in-toto: hand in hand
Given in-toto’s role in software attestation and SLSA’s focus on trustable provenance, their combination is logical. SLSA recommends (but does not mandate) the use of the in-toto format for provenance information, defining the necessary information for each Build Level as a custom in-toto predicate type.
This Provenance predicate aligns with in-toto’s framework: it models the supply chain as a series of steps, with each step generating attestations. These attestations are then verified against a supply chain layout, a signed metadata document defining the expected steps and their outcomes.
In-toto’s ability to define use-case-specific predicates complements SLSA by providing a flexible means to capture a wide array of contextual supply chain information. This includes code reviews, test results, and runtime traces, all of which can be tailored to the specific needs of a project.
By integrating SLSA Provenance with in-toto attestations, software supply chains can achieve a comprehensive verification process. This integration allows for detailed tracking and verification of each step in the supply chain, from code development to the final build, ensuring that all components meet the specified security and integrity standards.
In practice, this means that when a build service performs a build, it not only records the SLSA Provenance of the resulting artifact but also integrates this with the broader set of in-toto attestations, encompassing various aspects of the build process. These attestations, when combined, offer a more detailed and trustworthy view of the software’s development and build process, enhancing the overall security posture.
Conclusion
Software provenance attestation is crucial for mitigating a multitude of security threats. Frameworks like SLSA and in-toto play a significant role in enabling these attestations, ensuring the integrity and security of software supply chains. In a forthcoming blog post, we’ll explore in detail the process of creating SLSA provenance attestations specifically for Java/Maven projects. This deep dive will provide valuable insights and practical steps for developers looking to enhance the security of their Java applications. Keep an eye out for this upcoming post for a comprehensive guide on implementing these security measures.
December 26, 2023
Understanding Software Provenance
December 26, 2023 02:00 PM
In the ever-evolving landscape of open-source software development, the creation and distribution of artifacts—such as compiled binaries, libraries, and documentation—represent the tangible results of a multifaceted process. These artifacts are more than just a collection of code; they are the final product of myriad decisions, alterations, and contributions, each with its unique narrative. It’s essential to grasp these narratives or the provenance of these artifacts, to secure the supply chain effectively. Moreover, the integrity and security of these artifacts are paramount, as they underpin the trust and reliability users expect. This post aims to demystify the concept of provenance for these released artifacts. We will delve into why a comprehensive understanding of their origins and the path they take—examined through the lens of the journalistic 5W1H (Who, What, When, Where, Why, and How)—is crucial for enhancing the security posture of an open source project’s supply chain.
Understanding Artifact Provenance
Provenance in the context of released artifacts is a narrative of origin and evolution. It’s a detailed account of an artifact’s lifecycle from its inception in the developer’s mind to its final form when it is released to the world. This lineage includes every modification, every build, and every individual who has interacted with the artifact. A well-documented provenance is not just an academic record; it’s a testament to the artifact’s integrity, a shield ensuring that what users download and interact with is precisely what was intended, untainted by tampering or malicious alterations.
Challenges in Tracking Artifact Provenance
However, maintaining a comprehensive provenance is fraught with challenges. The complexity of dependencies where each layer has its own story, the sheer volume of artifacts and the speed at which they are updated, and the diverse sources they are compiled from, all contribute to a labyrinth of information that needs to be meticulously managed. Add to this the lack of standardized tools and practices for documenting and verifying provenance, and the task can seem Herculean. Yet, these challenges are not insurmountable barriers but rallying calls for robust solutions, for the security and reliability of the software supply chain hinge on this very capability.
Provenance information
If we consider what the provenance information of released artifacts should comprise, it’s akin to the outcome of any solid journalistic work: it should address the 5W1H (What, Who, Why, When, Where, and How) questions. At a fundamental level, the answers to these questions should be as follows.
- The What concerns identifying the released artifacts themselves, giving them an identity through an unambiguous identifier (e.g., using the Common Platform Enumeration (CPE) scheme or a Package URL). It can also cover the licenses of the artifacts, a list of the artifact’s dependencies, their respective licenses, and how they have been retrieved, among other things. This is more commonly known as a Software Bill of Materials (SBOM) and can be considered a part of the provenance information to be released with an artifact. Understanding the ‘What’ means having a clear, auditable trail of the components that form the backbone of your software, enabling you to assess, manage, and secure your software supply chain effectively.
- The Who can be as straightforward as identifying who triggered the release (or the build of the release) of the artifacts. It might also extend to include additional information about who contributed to the code included in this release, whether from the project’s inception or since the last release. Details regarding any signed Contributor License Agreement (CLA) or accepted Developer Certificate of Origin (DCO) by contributors can also be incorporated. Knowing who contributed what aids in tracking changes, auditing contributions, and most importantly, ensuring that only trustworthy code is incorporated into your projects.
- The Why pertains to understanding the reason behind the release: is it to fix a security vulnerability? Is it a scheduled release following the regular cadence? It might also involve tracking why a particular library was updated. As such, the release notes can be considered a (non-structured) part of the provenance information in this context. This aspect of provenance is about context and rationale, which is crucial for assessing the impact of changes on the overall security and functionality of your software.
- The When is straightforwardly about keeping track of the time of the release, to anchor it in a broader historical context. It can also involve recording the timing of the various contributions made prior to the release.
- The Where concerns tracing the locations of the various components that led to the released artifact. Where was the code developed and stored? Was it in a secure, trusted repository, or did it come from a less reliable source? Where was it built? Knowing these details can be the difference between a secure application and a vulnerable one. Coupled with the answer to the When, this mirrors the journalistic approach of establishing timelines and locations, helping you create a more comprehensive narrative of your software’s development and enhancing security and control over your project’s lifecycle.
- How relates to the methods, tools, and practices used to track and verify the origins of your code. It encompasses the mechanisms you implement to ensure that every line of code can be traced back to its source, thus ensuring integrity and reliability. This not only refers to the build pipelines and toolchains used to build and release the artifacts but also includes information about software development best practices such as code review, branch protections, secret scanning, and more.
![5w1h](https://mikael.barbero.tech/blog/post/2023-12-26-understanding-software-provenance/5w1h.png)
While the full details of implementing software provenance attestation will be covered in a future post, all this information can already be delivered to downstream users of your project in a simple text file, for example, in the form of buildinfo
files. Although not exhaustive, buildinfo
files are a testament to the commitment to transparency and security, serving as a foundational element for more advanced tools and practices.
The Importance of Artifact Provenance for Security
The narrative of provenance is critical for security. In a world where the threat landscape is as vast as it is vicious, the lack of provenance can lead to severe breaches. Compromised artifacts, malicious code insertions, and other vulnerabilities are not just theoretical risks; they are stark realities. A robust provenance framework is not just a defensive mechanism; it’s a foundational pillar in building a secure, trustworthy supply chain. To enhance the security posture of its projects, understanding and implementing provenance practices is not an option; it’s an imperative.
How to trust provenance data?
Trusting provenance data generated during the build process is a commendable start. However, recognizing its limitations is crucial for establishing a more robust system of trust
Integrity of Build-Generated Provenance
The integrity of build-generated provenance is inherently fragile. It’s as secure as the environment in which it’s stored and the transport methods used to deliver it. Imagine if a malicious actor gains access to the storage backend or intercepts the transport protocols; they could alter the provenance data, rendering it unreliable. A common countermeasure involves signing the provenance files or data. Digital signatures provide an additional layer of trust by making any tampering with the provenance data after its creation detectable. However, this step, while beneficial, is not a complete solution.
Vulnerability of the Build Script
Another critical aspect to consider is the vulnerability of the build script itself. If the build pipeline is compromised, then so is the provenance it generates, whether signed or not. A compromised script might produce misleading information, feeding false data into what should be a trusted record. This scenario underscores a crucial realization: to genuinely trust the provenance data, the responsibility for generating it should shift away from the build pipeline to the build platform.
The Shift in Responsibility
By making the build platform responsible for this task and having it sign the generated data, we create a system where the provenance is not only more resistant to tampering but also inherently more trustworthy. The build platform, ideally, is indeed in a unique position to observe and record the build process. It has access to all the information needed to generate accurate provenance data. This shift doesn’t eliminate the risk of compromise, but it does mean that any tampering with the build pipeline won’t affect the integrity of the provenance data we rely on.
Securing the Build Platform
It’s important to note that this approach is not a silver bullet. The build platform itself can be compromised, and securing it is a complex task that goes beyond the scope of this discussion. However, it’s an essential consideration for a truly trustworthy system. Even with a secured build platform, the environment generating the provenance data must also be secure to genuinely trust the data’s integrity.
In conclusion, while build-generated provenance is a valuable first step, it’s essential to be aware of its limitations. Shifting the responsibility to the build platform and securing that platform are critical moves towards a more trustworthy and resilient system. However, remember that in the realm of security, no solution is absolute. Each layer of trust we add is a step towards a more secure ecosystem, but vigilance and ongoing improvement are always necessary.
Closing notes
As we conclude our exploration of software provenance through the detailed lens of the 5W1H framework, it’s clear that this is not merely an exercise in compliance or best practices. It’s a fundamental shift in how we approach software development and security. Understanding the ‘Who,’ ‘What,’ ‘When,’ ‘Where,’ ‘Why,’ and ‘How’ of your artifacts isn’t just about enhancing security—it’s about instilling a culture of transparency and excellence.
The journey we’ve outlined is challenging, with numerous complexities and hurdles. However, the path to a secure and reliable software supply chain is not only necessary but also attainable with the right mindset and tools. Adopting a provenance-first approach is a paradigm shift. It means engraining the tracking and verification of the origin and journey of artifacts into the very fabric of the development and release process. It’s about integrating provenance tracking into the build process, adopting tools that automate and standardize provenance documentation, and fostering a community culture where knowledge, tools, and best practices are shared freely and openly.
As we look forward to diving into the practicalities of implementing a robust software provenance strategy in our next installment, remember that your engagement and continuous learning are vital. The principles and practices discussed here are just the beginning. With a blog post about the Supply-chain Levels for Software Artifacts (SLSA) framework on the horizon, we will have the guidelines and tools at our disposal to prevent tampering, improve integrity, and secure our packages and infrastructure.
We invite you to not just read but actively participate in shaping the future of software provenance. Join us and the Eclipse Foundation community in discussing and advancing these crucial topics. Your insights, experiences, and commitment are key to driving change and fostering a more secure digital world.
Together, let’s embrace the provenance-first mindset and lead the charge towards a future where software development is synonymous with security, transparency, and trust.
December 23, 2023
Eclipse Foundation Embraces Sigstore
December 23, 2023 10:00 AM
As part of our ongoing commitment to fortifying the security of our software development processes, we’re excited to announce a significant enhancement for all Eclipse Foundation projects utilizing our Jenkins infrastructure. This advancement comes with the integration of Sigstore, a cutting-edge solution designed to bolster the security and integrity of software supply chains. By exploring the integration of Sigstore within the Eclipse Foundation’s Jenkins setup, this article sets out to demonstrate how this advancement is reshaping secure software development and deployment for Eclipse Foundation projects.
What is Sigstore?
Sigstore represents a shift in the way we secure software artifacts. This open-source tool offers a transparent and secure method for both signing and verifying software artifacts, including binaries and container images. It’s designed to make digital signing simpler for developers by eliminating the complex management of keys. This allows users to confidently verify the artifacts’ origins and integrity. At its core, Sigstore’s “keyless” signing associates a signature with the signer’s identity, rather than a fixed set of keys.
The process begins when a developer obtains an identity token from an identity provider and creates a temporary public/private key pair in memory. This token, along with the public key, is sent to Sigstore’s certificate authority, which verifies the information against the token issuer. If the identity provider is recognized and the token is valid, Sigstore’s authority issues a short-lived certificate that binds the public key to the developer’s identity. This binding is crucial as it securely attaches the identity of the signer to the artifact being signed, ensuring traceability and accountability.
![sigstore](https://mikael.barbero.tech/blog/post/2023-12-23-eclipse-foundation-embraces-sigstore/sigstore_text.png)
During the signing phase, a transparency log entry is created. This entry is part of a public, tamper-evident ledger that records the artifact’s hash, the public key used, and the signature, all with a timestamp to validate the software’s integrity and origin at the time of signing. Once the signing is complete, the private key is discarded, and the short-lived certificate soon expires.
The trust in the verification process comes from this transparency log, not from the signer’s ability to safeguard a private key. Users can validate the logged details against the artifact to confirm its integrity and origin. This verification can occur online, with real-time access to the transparency log for the most up-to-date information. For environments where the transparency log is not accessible, such as air-gapped systems, offline verification is also possible. In these scenarios, the signed artifacts should be accompanied by the certificate and public key, allowing verification against these components without needing access to the transparency log. This method relies on the trust established by the Sigstore-issued certificate, ensuring the authenticity of the artifact as confirmed by a trusted CA.
This methodology goes beyond improving convenience; it serves as a strategic defense against a range of cyber threats, particularly those targeting software supply chains. By eliminating the need for developers to manage long-lived keys and by providing a transparent log of signed artifacts, Sigstore mitigates risks like code tampering (e.g., when used to sign commits) and unauthorized access, which are prevalent in supply chain attacks.
Using Sigstore on Eclipse Foundation’s Jenkins instances
The Eclipse Foundation has recently become a recognized identity provider for Sigstore’s certificate authority. This development is a game-changer for projects within the Foundation for several reasons:
-
Managed Identity Verification: With this status, the Eclipse Foundation can issue tokens for projects’ bot accounts. These tokens are recognized and verified by Sigstore, which then issues certificates based on the Eclipse Foundation’s managed identity. This process ensures a trusted link between the artifact and the Foundation, further bolstering trust and security.
-
Streamlined Artifact Signing: Initially focusing on bot accounts, this setup is tailored for automated processes, like those running on Jenkins instances. Projects can seamlessly sign artifacts during the build and release process, integrating security into the CI/CD pipeline without added complexity.
-
Extended Trust and Compliance: Having the Eclipse Foundation as a recognized identity provider means that artifacts signed through this process are backed by a trusted entity, meeting higher standards of security.
It’s worth noting that Sigstore can be used by all of Eclipse Foundation projects hosted on GitHub and using GitHub Actions, as detailed in GitHub’s blog post. For Eclipse Foundation projects that utilize both Jenkins and GitHub, this creates a cohesive and secure workflow for signing artifacts across platforms.
Implementing Sigstore in Your Jenkins Workflow
If you want to start signing artifacts with Sigstore’s keyless process in your Jenkins workflow, it’s very easy:
- The very first step is to open a help desk ticket to ask us to allow our identity provider to issue tokens that would be verifiable by Sigstore. We also configure your Jenkins instance with some new credentials.
- Adapt the workflow below to your use case and profit.
pipeline {
agent any
stages {
stage('Prepare') {
steps {
sh '''
echo "Hello World" > README
curl -sSL -o cosign https://github.com/sigstore/cosign/releases/latest/download/cosign-linux-amd64
chmod u+x cosign
'''
}
}
stage('Sign') {
steps {
withCredentials([usernamePassword(credentialsId: 'cbi-dev-sigstore', passwordVariable: '_BOT__PASSWORD', usernameVariable: '_BOT__USERNAME')]) {
sh '''
IDP_DATA=$(mktemp)
OID_TOKEN=$(mktemp)
chmod 600 "${IDP_DATA}" "${OID_TOKEN}"
trap 'rm -vf "${IDP_DATA}" "${OID_TOKEN}"' EXIT
cat <<EOF > "${IDP_DATA}"
username=${_BOT__USERNAME}
&password=${_BOT__PASSWORD}
&grant_type=password
&client_id=sigstore
EOF
curl -sSL -X POST \
--url https://auth.eclipse.org/auth/realms/sigstore/protocol/openid-connect/token \
--header "Content-Type: application/x-www-form-urlencoded" \
--data @"${IDP_DATA}" \
| jq -r ".access_token" \
| head -c -1 > "${OID_TOKEN}"
./cosign sign-blob README -y --bundle README.bundle --oidc-issuer=https://auth.eclipse.org/auth/realms/sigstore --identity-token="${OID_TOKEN}"
'''
}
sh '''
./cosign verify-blob README --bundle README.bundle --certificate-oidc-issuer=https://auth.eclipse.org/auth/realms/sigstore --certificate-identity=cbi-dev@eclipse.org
'''
}
}
}
}
During the Prepare
phase, we just download the cosign
tool, which is a CLI client to sigstore. We could also go the hard way and only communicate with Sigstore via its REST API with curl, but cosign
make is much simpler.
During the Sign
phase, we start by retrieving the project’s bot credentials and use curl
to retrieve a token from the Eclipse Foundation identity provider. We aim at making this phase transparent to projects in the future and create the token automatically on each workflow startup, à la GITHUB_TOKEN
. We then pass this token to the cosign tool to sign the README
file.
Note that we save the file what cosign
call a --bundle
. This bundle is just an aggregate of the signature and the certificate of the signature. This avoids having to distribute 2 files along with the signed artifacts, simplifying the transfer and the verification.
At the end of the signing process, the cosign
tool prints the index of the transparency log entry that has been created:
tlog entry created with index: 58260299
One can then check the information relative to this operation by going on the transparency log web interface at https://search.sigstore.dev/?logIndex=58260299.
![rekor](https://mikael.barbero.tech/blog/post/2023-12-23-eclipse-foundation-embraces-sigstore/rekor.png)
Finally, for testing purpose, we verify the signature during the Verify
phase. We reuse the bundle we just introduced, and ask the cosign
tool to verify that the file has been signed with a certificate for the identity cbi-dev@eclipse.org
as issued by the identity provider https://auth.eclipse.org/auth/realms/sigstore
.
+ ./cosign verify-blob README --bundle README.bundle --certificate-oidc-issuer=https://auth.eclipse.org/auth/realms/sigstore --certificate-identity=cbi-dev@eclipse.org
Verified OK
Conclusion
We encourage all project teams within the Eclipse Foundation to adopt this new capability. The integration is straightforward and offers significant benefits in securing your software artifacts. By doing so, you’ll be taking a proactive stance in securing your projects and contributing to a safer software supply chain.
In conclusion, the adoption of Sigstore within our Jenkins infrastructure is more than just a technical update; it’s a commitment to the security and integrity of the Eclipse Foundation projets. We look forward to seeing its positive impact on our community.
We welcome feedback and questions from the Eclipse Foundation community on this journey together towards a more secure software future.
This work was made possible thanks to the funding the Foundation received from the Alpha-Omega Project.
December 19, 2023
Good News on the Cyber Resilience Act
by Mike Milinkovich at December 19, 2023 09:01 AM
As the title says, there is good news to share on the progress of the European Union’s proposed Cyber Resilience Act (“CRA”) as the final revisions agreed to in the trilogue negotiations appear to largely exclude the open source community from its scope.
I have written (here and here) and spoken extensively about our concerns with the European Union’s proposed Cyber Resilience Act (“CRA”) in the past. As originally drafted, the CRA would have had an enormous negative impact on both the open source community and the EU’s innovation economy. In short, it would have required most open source projects (and every open source project that matters) made available in Europe to meet unrealistic regulatory requirements related to their secure software development and maintenance. OSS projects would have also been required to affix the CE Mark on their releases certifying that these regulatory requirements had been met, which additionally would have required outside audits performed for critical infrastructure projects such as operating systems. You can read the links above if you want to get a full understanding of the dire implications of the original draft of the CRA.
While the Eclipse Foundation has always shared the goals of the CRA to improve the state of security in the software industry, we have been very vocal in expressing our concerns with how unrealistic requirements could damage the open source community and Europe’s innovation economy. We have been very active in raising community awareness of the issues over the past year. For example, we helped facilitate two open letters co-signed with many of our peer organizations detailing the issues (here and here).
But we also invested a great deal of time and energy in constructively engaging with policymakers by providing explanations of the functioning of our ecosystems and technologies. The European Commission, the European Parliament, the Council through the Spanish Presidency, as well as numerous policy makers at the national level have all been open to our contributions and recognise our efforts to protect European open innovation. I would like to thank my colleagues Gesine Freund, Enzo Ribagnac, Mikaël Barbero, and Gaël Blondelle for their many contributions to this process.
We were not alone in these efforts. An assuredly incomplete list of other open source organizations that contributed to raising awareness includes: Apache Software Foundation, Internet Society, Free Software Foundation Europe, Linux Foundation, Mozilla Foundation, NLNet Labs, Open Source Initiative, Python Software Foundation, The Document Foundation, and many others. OpenForum Europe played a pivotal role in facilitating communication between these groups, and Ciarán O’Riordan at the OFE deserves recognition for his yeoman’s effort in coordinating the community’s input throughout the discussions on the CRA.
On December 1st it was announced that the EU co-legislators had reached political agreement on the CRA. Although the final text is still being worked on, we are happy to report the open source community has been listened to. The revised legislation has vastly improved its exclusion of open source projects, communities, foundations, and their development and package distribution platforms. It also creates a new form of economic actor, the “open source steward,” which acknowledges the role played by foundations and platforms in the open source ecosystem. This is the first time this has appeared in a regulation, and it will be interesting to see how this evolves. The Eclipse Foundation will be investing a great deal of effort into helping refine this concept and its implementation to ensure it aligns with the norms of the open source community. The final revisions also extended the implementation phase to three years, which means full compliance with the CRA will likely start in early 2027. OpenForum Europe’s recent press release on the CRA is certainly worth a read for additional context.
It is important to recognize and thank the many people that were involved in achieving this significantly better outcome. Both those who were involved from the side of the co-legislators who genuinely listened and made extensive improvements, and the many people from the open source community who invested their time and energy into explaining the unique requirements of the open source community.
But this journey is only beginning.
It is important to note that while the CRA has been revised to largely exclude the open source community from its scope, this legislation will still have an enormous impact on the software industry as a whole.
Open source projects will not be required to directly implement the mandated processes described in the CRA. But every commercial product made available in the EU which is built on top of those open source projects will. For the first time in the software industry’s history, it will soon have regulatory requirements for secure software development and maintenance. I predict this will put pressure on projects and communities to enhance their processes to assist in downstream commercialization.
After all, if a project is used in hundreds of products, doing the bulk of the CE Mark conformance work in the project rather than repeating the effort hundreds of times makes enormous sense. But as we all know, OSS projects at the moment simply do not have the resources to do this. It is impossible to know how all of this will play out, but an optimistic hypothesis is that once companies are required by law to meet secure software development practices they will be incented to invest in the upstream projects they rely upon. The Eclipse Foundation will be working hard to ensure that we evolve to support the needs of our committers, projects, and members in order to support the implementation of these new regulatory requirements. We will be discussing this early in the new year.
Interesting times!
December 18, 2023
Industry Collaboration in Action: Eclipse SDV, OpenMobility and ThreadX
by Sharon Corbett at December 18, 2023 04:21 PM
If you’ve read my two previous blog posts, you already have an understanding of how interest groups and working groups provide two different mechanisms for industry collaboration, how your organisation can get started on its own collaboration journey, and the numerous benefits that come from collaborating on open source software at the Eclipse Foundation.
But the best way to understand what joining an industry collaboration can do for your organisation is by taking a look at some of our current collaborations.
The Eclipse Foundation currently hosts 21 Industry Collaborations focused on various technologies and domains, from developer tools to cloud native Java, IoT and beyond. One working group that has experienced considerable momentum recently is Eclipse Software Defined Vehicle (SDV).
Over 40 organisations have joined Eclipse SDV since the working group’s launch in 2022. Members range from automotive OEMs and Tier-1’s, to enterprise software companies, to the cloud hyperscalers. This is driven by the fact that the software defined vehicles of the future will be highly connected, and the systems engineering requirements will span deeply embedded and safety critical components all the way to connectivity to cloud-based IT systems.
Eclipse SDV members collaborate on non-differentiating technologies and share best practices, which decreases their time to market and makes things easier for their developers. The move to open source software is a significant departure from the norm for the automotive industry, which has historically embraced proprietary solutions where common building blocks are often replicated.
Visit the Eclipse SDV project page to see the code first approach across more than 20 projects.
While interest groups are fairly new to the Eclipse Foundation, there are a few active collaborations that are benefiting from the foundation’s governance structure, like Models for Privacy Engineering, OpenMobility and Eclipse ThreadX.
In the case of OpenMobility, a group of four members came together to work on evolving and driving adoption of mobility modelling and simulation technologies.
Its members are interested in delivering a methodology and a framework of tools that are based on validated models. These tools are intended to be recognised as “standard tools” in industry applications and academia for mobility modelling and simulation. OpenMobility has declared interest in Eclipse MOSAIC and Eclipse SUMO and Eclipse openMCx.
Eclipse ThreadX: A New Era for Embedded RTOS Technology
The Eclipse Foundation’s newest interest group is a unique case. With Microsoft contributing Azure RTOS to the Eclipse Foundation under the Eclipse ThreadX project last month, plans are underway to establish a working group that will consolidate the project, preserve its certifications, promote the brand, and grow the technology’s ecosystem and community.
However, this cannot be done without first establishing an industry-supported, sustainable funding model for Eclipse ThreadX. This will be the focus of the new ThreadX Interest Group. The founding members of this interest group intend to form a working group dedicated to the project after investigating key topics around the potential working group’s funding and goals. Any company with an interest in embedded technology is welcome to join the interest group to define ThreadX’s future.
While interest groups are not necessarily intended to serve as a jumping off point for new working groups, ThreadX shows just how flexible this collaboration model can be. With interest groups, members can come together to share a common interest in a topic or domain in a vendor-neutral manner. What members choose to collaborate on is up to them.
To learn more about our industry collaborations and our current showcase, please visit eclipse.org/collaborations, and contact us if you are interested in joining and/or forming a new collaboration!
Elevating Software Supply Chain Security: Eclipse Foundation's 2FA Milestone
December 18, 2023 04:00 PM
In the realm of open-source software, security of the supply chain is not just a concern—it’s a crucial battleground. The Eclipse Foundation, at the forefront of this fight, has taken a decisive step with its 2023 initiative to enforce two-factor authentication (2FA) across its platforms. This move is more than a security upgrade; it’s a testament to the Foundation’s commitment to safeguarding the open-source software supply chain against escalating threats.
The traditional reliance on password-based authentication poses a significant risk, especially in open-source software development. As highlighted in a previous article, compromised developer accounts can become conduits for malicious code, affecting not only the developers themselves but also downstream users. The alarming 742% average annual increase in software supply chain attacks in recent years underscores the urgency of robust security measures. Recognizing this threat, the Eclipse Foundation has championed the shift to more secure authentication methods with 2FA.
The road to comprehensive 2FA implementation was not without its challenges. One of the main hurdles was addressing misunderstandings about what 2FA entails. For example, there was confusion about whether 2FA required hardware tokens. Additionally, concerns arose about what actions to take in case of a loss of the second factor. The Foundation tackled these issues head-on through repeated communication and education, providing clear, accessible information to demystify 2FA and allay fears.
Feedback and insights from the Eclipse community were invaluable in shaping the 2FA initiative. A particularly unique challenge came from members who were unable to use mobile phones or hardware tokens at their workplaces due to internal policies. To address this, the Foundation helped identify software solutions that facilitated TOTP-based 2FA, aligning with the IT requirements of these members: we were committed committed to help everybody and find practical solutions to all problems.
![2FA Bird](https://mikael.barbero.tech/blog/post/2023-12-18-2fa-at-eclipse-foundation/2fa.png)
For the Eclipse Foundation, 2FA is just one aspect of a broader vision to harden software supply chain security. Recognizing that the first line of defense starts with developers, the Foundation has positioned itself as a role model in software supply chain security. Beyond 2FA, it is actively helping its projects to better understand and communicate their dependencies through Software Bill of Materials (SBOMs), manage vulnerabilities in these dependencies, and secure their build pipelines against potential threats. These initiatives are set to continue throughout 2024.
The impact of the 2FA enforcement initiative is clearly demonstrated by the significant adoption rates within the Eclipse community. On GitHub, 91% of our committers have now enabled 2FA, with 63% of organizations achieving complete member compliance. In 2024, we will take the final steps to fully enforce 2FA for committers on GitHub, ensuring that all organizations will exclusively have members with 2FA enabled. For projects hosted on gitlab.eclipse.org, 63% of committers have enabled 2FA. Since December 11th, committers are required to enable 2FA upon signing in—if they haven’t already—before they can proceed with any other actions.
The 2FA enforcement initiative of the Eclipse Foundation represents an essential measure in hardening the security of the open-source software supply chain of its projects. This initiative underscores the significance of shared responsibility and vigilance in cybersecurity.
This work was made possible thanks to the funding the Foundation received from the Alpha-Omega Project.
Celebrating Eclipse Theia’s Milestone: Full Compatibility with VS Code Extension API
by Mike Milinkovich at December 18, 2023 12:09 PM
We are thrilled to announce a landmark achievement in the evolution of Theia: full compatibility with the Visual Studio Code (VS Code) extension API, marking a significant milestone in the journey of Theia towards becoming a universally adaptable development environment.
Unleashing a World of Features with VS Code Extensions
Theia has supported hosting VS Code extensions for many years. The integration of the VS Code extension API unlocked an unprecedented array of features for Theia-based applications. This compatibility means that users can leverage the extensive ecosystem of VS Code extensions, bringing thousands of new capabilities to Theia. With the completion of a recent initiative, Theia now is fully compatible with the VS Code API allowing the vast majority of VS Code extensions to be used in any Theia-based application. Of particular note is the recent addition of support for notebook editors, a game-changer that opens Theia to new audiences, such as data scientists, who rely heavily on notebook interfaces for languages like Python.
A Symphony of Collaboration
This achievement is not just a technical milestone; it is a testament to the power of collaborative open-source development. The original VS Code API compatibility implementation was contributed by Red Hat. The journey to full compatibility, initiated by STMicroelectronics and crafted through the concerted efforts of EclipseSource, Ericsson, Typefox, and other contributors, has been one of shared vision and united effort. STMicroelectronics and EclipseSource played a pivotal role in establishing an open, structured process for regular API comparison and issue tracking. This approach facilitated a broad-based contribution, allowing various organizations to contribute effectively to the project.
Empowering the Developer Community
The compatibility with the VS Code API multiplies Theia’s effectiveness as a development platform. For developers, this means access to the latest and most advanced tools available in the VS Code ecosystem, significantly enhancing both the adopter and user experience with Theia.
Overcoming Challenges through Open Source Collaboration
The journey to this point wasn’t without challenges. Initially, contributions were focused only on specific missing API features needed for particular extensions used by contributors. However, the structured process initiated by STMicroelectronics set a new direction – aiming for complete compatibility. This approach significantly simplified the distribution and parallelization of work. As a result, this process galvanized the open-source community, leading to a surge in contributions and exemplifying the true spirit of collaborative innovation.
Maintaining the Pace: The Future Roadmap
For nearly half a year, Theia has maintained full compatibility with the VS Code extension API. The commitment to this standard is unwavering. With regular scans of new VS Code API updates, contributors that Theia stays in lockstep with the latest advancements, continually integrating new features and capabilities.
Join Us in this Continual Journey
As we celebrate this milestone, we also look to the future. Theia’s journey is ongoing, and the path ahead is as exciting as the accomplishments behind us. We invite the developer community, contributors, and enthusiasts to join us in this vibrant and continually evolving project. Together, we will keep pushing the boundaries of what’s possible in open-source development environments.
Let’s continue to shape the future of software development tools with Theia. Your contributions, feedback, and engagement are not just welcome – they are essential to our shared success.
Here are a couple of links to get you started in your journey with Eclipse Theia:
- Theia’s website
- Project overview page
- Github organization
- Project readme
- Getting started with Theia
- Contributing to Theia
Building cloud-native (modeling) tools
by Jonas, Maximilian & Philip at December 18, 2023 12:00 AM
Are you on the journey to develop a domain-specific (modeling) tool based on modern web technologies? Curious about the latest tech innovations and their seamless integration for cloud efficiency? …
The post Building cloud-native (modeling) tools appeared first on EclipseSource.
December 14, 2023
Eclipse fonts in Windows 11
by Lorenzo Bettini at December 14, 2023 09:06 AM
The Eclipse Theia Community Release 2023-11
by Jonas, Maximilian & Philip at December 14, 2023 12:00 AM
We are happy to announce the fourth Eclipse Theia community release “2023-11”, version 1.43.x! Don’t know about Eclipse Theia, yet? It is the next-generation platform for building IDEs and tools for …
The post The Eclipse Theia Community Release 2023-11 appeared first on EclipseSource.
December 11, 2023
Collaborative, Testable and Accessible diagrams with Eclipse GLSP
by Jonas, Maximilian & Philip at December 11, 2023 12:00 AM
Modern web-based diagram editors are not only about shapes and edges; they’re about creating an interactive, collaborative environment that elevates user experience and productivity. With technologies …
The post Collaborative, Testable and Accessible diagrams with Eclipse GLSP appeared first on EclipseSource.