Skip to content

Instantly share code, notes, and snippets.

@benweidig
Created July 26, 2020 08:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save benweidig/21d3876188a7761632816c1f2684b102 to your computer and use it in GitHub Desktop.
Save benweidig/21d3876188a7761632816c1f2684b102 to your computer and use it in GitHub Desktop.
Proposal for improving tapestry-json with Java 8 features and more

tapestry-json Improvements

Date: 2020-07-26
Author: Ben Weidig

Summary

Add modern Java 8 features to tapestry-json to make it more versatile. Improve existing functionality without breaking changes.

Goals

With Tapestry development picking up speed and supporting newer Java version, its dependencies should also support some of the newly available features:

  • Stream-support
  • Additional instance creators
  • Approximate to the conceptional interfaces (Collection/Map)
  • Generic methods
  • Better/more informative exceptions

The general idea is making JSONArray more like java.util.Collection, and JSONObject more like java.util.Map, without implementing the interfaces explicitly. If we would implement them directly, it would method duplication (size() vs. length(), add() vs put(...)).

Motivation

Tapestry's use of JSON types is deeply ingrained into its services. By using its own types, we can improve upon them to adapt to any new features. The framework and Java itself evolved, and they should be too.

Java 8 was bringing a lot of new features, like lambdas, Streams, and Optionals, thereby changing the way how we can deal with collection types in a significant way.

It's time to adapt tapestry-json to the new features available to us.

Risks and Assumptions

Only minimal risk is assumed.

Existing functionality shouldn't be changed, for backward-compatibility. Any new feature has to be able to stand on its own.

The only proposed change will be the exact exception types and messages. Changing the type should not pose a problem, they will still be descendant of RuntimeException. And relying on the actual exception message is bad practice, and shouldn't be part of the guaranteed API contract.

Alternatives

Instead of extending existing types we could always use utility classes to wrap the functionality.

Details of Proposed Changes

Most of the proposed changes are based on utility classes used in our projects. But some are just of theoretical nature, and might not be as easy as implementable as thought.

JSONArray

  • Stream<Object> stream()
  • Stream<T> stream(Class<T> clazz)
  • Stream<Object> parallelStream()
  • Stream<T> parallelStream(Class<T> clazz)
  • List<T> toList(Class<T> clazz)
  • static JSONArray from(Iterable<?> iterable, boolean preserveNull)
  • JSONArray(String jsonStr, boolean emptyIfInvalid)
  • boolean putUnique(Object value)
  • boolean isEmpty()
  • boolean contains(Object obj)
  • boolean removeIf(Predicate<Object> filter)
  • boolean removeAll(Iterable<Object> iterable)
  • void clear()

JSONObject

  • Map<String, T> toMap(Class<T> valueClazz)
  • Optional<Type> tryGetType(String key) for all types
  • Type getType(String key, Type fallbackValue) for all types
  • static JSONObject from(Map<String, ?> map)
  • void clear()
  • void clear()
  • Object putIfAbsent(String key, Object value)
  • Object computeIfAbsent(String key, Function<String, Object> mapFn)
  • Object computeIfPresent(String key, Function<String, Object> remapFn)
  • void merge(JSONObject other)

Exceptions

  • Use IndexOutOfBoundsException correctly
  • org.apache.tapestry5.json.JSON should throw more fine-grained exceptions:
    • Add JSONTypeUnsupportedException
    • Add JSONTypeMismatchException
    • Add JSONValueNotFoundException

Streams

  • Add Collectors to improve Stream use

Testing

All added functionality should be unit tested to ensure no existing code will be broken by it.

@MarineBerth
Copy link

Hi Ben, just a friendly follow-up to see how you are progressing with this proposed improvement? All the best, Chris.

@benweidig
Copy link
Author

benweidig commented Oct 7, 2020

Hi Chris,

Thiago already merged the improvements into master (apache/tapestry-5@2dab8e0) and marked the ticket as "Fixed Version/s: 5.6.2" https://issues.apache.org/jira/browse/TAP5-2640

Although the actual changes are a little different, JSONArray and JSONCollection now implement Collection and Map directly, instead of just mimicking the behaviour.

Cheers,
Ben

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment