8.2.0 (TBD)

Juneau 8.2.0 is a major release. The most significant change is the addition of an entirely new {@link oajr.client2.RestClient} API build from scratch with near 100% unit test coverage. The new API is located in the org.apache.juneau.rest.client2 package and will replace the old API in 9.0.

##### juneau-marshall

- {@link oaj.annotation.Bean @Bean} and {@link oaj.annotation.BeanIgnore @BeanIgnore} annotations can alternately occur in parent class hierarchy. The first one found dictates whether a class is ignored as a bean or not.
- Applying the {@link oaj.annotation.Bean @Bean} annotation on a class will now force non-public classes to be interpreted as beans. For example, applying {@link oaj.annotation.Bean @Bean} to a private class will force it to be treated as a bean.
  Also, if a public bean constructor cannot be found, the default constructor will be used regardless of it's visibility if the {@link oaj.annotation.Bean @Bean} annotation is on the class.
- The @Beanc annotation can now be recognized and used on non-public constructors.
- Annotations are now aggregated across the entire class hierarchy instead of simply being overridden.
  The following is an example.

  // Parent class with properties a,b,c @Bean(bpi="a,b,c") public class MyClass { public int a, b, c, d; } // New behavior: Child class with properties a,c because @Beans are aggregated. // Old behavior: Child class with properties a,c,d because @Bean is overridden. @Bean(bpx="b") public class MyClass { public int a, b, c, d; }

- Include/exclude/read-only/write-only properties defined on the bean context now override those defined on annotations of the class itself. For example, the following methods override the {@link oaj.annotation.Bean @Bean} annotations on classes:
  - {@link oaj.BeanContextBuilder}
    - {@link oaj.BeanContextBuilder#bpi(Class,String) bpi(Class,String)}
    - {@link oaj.BeanContextBuilder#bpi(String,String) bpi(String,String)}
    - {@link oaj.BeanContextBuilder#bpx(Class,String) bpx(Class,String)}
    - {@link oaj.BeanContextBuilder#bpx(String,String) bpx(String,String)}
    - {@link oaj.BeanContextBuilder#bpro(Class,String) bpro(Class,String)}
    - {@link oaj.BeanContextBuilder#bpro(String,String) bpro(String,String)}
    - {@link oaj.BeanContextBuilder#bpwo(Class,String) bpwo(Class,String}
    - {@link oaj.BeanContextBuilder#bpwo(String,String) bpwo(String,String}
- Config annotations now override class-level annotations.
  For example, only the 'a' and 'b' properties get serialized on the bean below:

  // Parent class with properties a,b,c @Bean(bpi="a,b,c") public class MyClass { public int a, b, c, d; } @RestMethod @BeanConfig(beanApply={@Bean(on="MyClass",bpi="a,b")} public MyClass getMyClass() {...}

- The following concrete annotation implementation classes are now provided that can be used with the {@link oaj.BeanContextBuilder#annotations(Annotation...)} method:
  - {@link oaj.annotation.BeanAnnotation} implements {@link oaj.annotation.Bean}
  - {@link oaj.annotation.BeancAnnotation} implements {@link oaj.annotation.Beanc}
  - {@link oaj.annotation.BeanIgnoreAnnotation} implements {@link oaj.annotation.BeanIgnore}
  - {@link oaj.annotation.BeanpAnnotation} implements {@link oaj.annotation.Beanp}
  - {@link oaj.annotation.ExampleAnnotation} implements {@link oaj.annotation.Example}
  - {@link oaj.annotation.NamePropertyAnnotation} implements {@link oaj.annotation.NameProperty}
  - {@link oaj.annotation.ParentPropertyAnnotation} implements {@link oaj.annotation.ParentProperty}
  - {@link oaj.annotation.SwapAnnotation} implements {@link oaj.annotation.Swap}
  - {@link oaj.annotation.UriAnnotation} implements {@link oaj.annotation.URI}
  - {@link oaj.csv.annotation.CsvAnnotation} implements {@link oaj.csv.annotation.Csv}
  - {@link oaj.html.annotation.HtmlAnnotation} implements {@link oaj.html.annotation.Html}
  - {@link oaj.jso.annotation.JsoAnnotation} implements {@link oaj.jso.annotation.Jso}
  - {@link oaj.json.annotation.JsonAnnotation} implements {@link oaj.json.annotation.Json}
  - {@link oaj.jsonschema.annotation.SchemaAnnotation} implements {@link oaj.jsonschema.annotation.Schema}
  - {@link oaj.msgpack.annotation.MsgPackAnnotation} implements {@link oaj.msgpack.annotation.MsgPack}
  - {@link oaj.oapi.annotation.OpenApiAnnotation} implements {@link oaj.oapi.annotation.OpenApi}
  - {@link oaj.plaintext.annotation.PlainTextAnnotation} implements {@link oaj.plaintext.annotation.PlainText}
  - {@link oaj.soap.annotation.SoapXmlAnnotation} implements {@link oaj.soap.annotation.SoapXml}
  - {@link oaj.uon.annotation.UonAnnotation} implements {@link oaj.uon.annotation.Uon}
  - {@link oaj.urlencoding.annotation.UrlEncodingAnnotation} implements {@link oaj.urlencoding.annotation.UrlEncoding}
  - {@link oaj.xml.annotation.XmlAnnotation} implements {@link oaj.xml.annotation.Xml}
  Example:

  @Bean(bpi="street,city") // Will be overridden public class AddressBean {...} Bean ba = new BeanAnnotation("AddressBean").bpi("street,city,state"); WriterSerializer ws = JsonSerializer.create().annotations(ba).build(); String json = ws.toString(addressBean); // Will print street,city,state

- Bean maps now have the concept of "hidden" properties (properties that aren't serialized but otherwise accessible).
  For example, the {@link oaj.html.annotation.Html#link()} can now reference hidden properties:

  @Bean(bpi="a") // Will be overridden public class MyBean { @Html(link="servlet:/{b}") public String a; public String b; // Not serialized, but referenced in link on a. }

  The general rule for the {@link oaj.BeanMap} class is that get(),put(), and containsKey() will work against hidden properties, but keySet() and entrySet() will skip them.
- Several bug fixes in the {@link oaj.html.HtmlSerializer} and {@link oaj.html.HtmlParser} classes around the handling of collections and arrays of beans with @Bean(typeName) annotations.
- New swaps auto-added to all serializers/parsers:
  - {@link oaj.transforms.MatchResultSwap}
  - {@link oaj.transforms.StackTraceElementSwap}
- {@link oaj.html.annotation.Html#noTableHeaders} now can be applied to collections of beans.
- New {@link oaj.html.annotation.HtmlDocConfig#asideFloat()} setting so that you can position the contents of the aside section on the page.
- Various minor fixes surrounding HTML serialization.
  - Collections of beans that were supposed to be serialized as tables were being serialized as lists.
  - Collections of beans with @Bean(bpi) were not being serialized in the correct column order.
- Fixed a bug where a copy constructor can erroneously be recognized as a builder constructor if the class also has a static create method. Net effect was that the copy constructor would needlessly be called during parsing.
- New {@link oaj.collections} package containing various convenience fluent-style collection classes:
  - {@link oaj.collections.AList}
  - {@link oaj.collections.ASet}
  - {@link oaj.collections.ASortedSet}
  - {@link oaj.collections.AMap}
  - {@link oaj.collections.ASortedMap}
  - {@link oaj.collections.OMap}
  - {@link oaj.collections.OList}
- {@link oaj.ObjectMap} is being deprecated and replaced with {@link oaj.collections.OMap}.
- {@link oaj.ObjectList} is being deprecated and replaced with {@link oaj.collections.OList}.
- All classes in the {@link oaj.http.response} and {@link oaj.http.exception} now have header(String,Object) methods for adding response headers.

  // Method that performs a BASIC Auth handshake. @RestMethod public Ok checkBasicAuth(@Header("Authorization") String auth) throws Unauthorized { if (auth == null) throw new Unauthorized().header("WWW-Authenticate", "BASIC realm=\"foo\""); return Ok.OK; }

- New annotations for multi-part support:
  - {@link oaj.http.annotation.Header#multi()}
  - {@link oaj.http.annotation.Query#multi()}
  - {@link oaj.http.annotation.FormData#multi()}
- {@link oaj.BeanTraverseContext#BEANTRAVERSE_ignoreRecursions} setting no longer requires {@link oaj.BeanTraverseContext#BEANTRAVERSE_detectRecursions} to be enabled.
- Fixed bug in JSON/UON/URL-Encoding serializers where indentation was not correct of first line when {@link oaj.BeanTraverseContext#BEANTRAVERSE_initialDepth} used.
- Fixed bug in JSON/UON/URL-Encoding serializers where properties past the max depth were being serialized as null instead of being treated as null and not being serialized at all.
- Fixed bug in HTML serializer where tables of maps were not sorted if SERIALIZER_sortMaps was specified.
- SERIALIZER_trimNullProperties has been replaced with {@link oaj.serializer.Serializer#SERIALIZER_keepNullProperties SERIALIZER_keepNullProperties}.
- Improvements to OpenAPI serializer and parser:
  - Collection format can now be specified on OBJECTs to allow key/value pairs to be delimited with the same support as ARRAYs.
  - New {@link oaj.oapi.OpenApiCommon#OAPI_format OAPI_format} and {@link oaj.oapi.OpenApiCommon#OAPI_collectionFormat OAPI_collectionFormat} properties.
- Convenience methods added to {@link oaj.httppart.HttpPartSchema} and related classes to simplify schema definitions:

  import static org.apache.juneau.httppart.HttpPartSchema.*; // Old HttpPartSchema s = schema("object") .property("f01", schema("array").collectionFormat("pipes").items(schema("string"))) .property("f02", schema("array").collectionFormat("pipes").items(schema("string", "byte"))) .property("f03", schema("array").collectionFormat("pipes").items(schema("string", "date-time"))) .build(); // New HttpPartSchema s = tObject() .p("f01", tArray(tString())) .p("f02", tArray(tByte())) .p("f03", tArray(tDateTime())) .build();

- Fixes where the bean method/constructor visibility wasn't being used when finding swap methods and constructors.
- HTML-Schema support is being deprecated due to low-use and difficulty in maintaining. It will be removed in 9.0.
- JuneauLogger class is being deprecated. Improvements in logging in Java 8 make it obsolete.
- Bean filters can now be specified programmatically through a builder API.

  // Create a JSON serializer that only includes specified fields on a specific class. WriterSerializer s = JsonSerializer .create() .beanFilters(BeanFilter.create(MyBean.class).bpi("foo,bar,baz").build()) .build();

- BeanContext.REST_pojoSwaps replaced with {@link oaj.BeanContext#BEAN_swaps} (and builder methods as well).
- New Bean Property Interceptor API for intercepting calls to bean getters/setters.
  - {@link oaj.transform.BeanInterceptor}
  - {@link oaj.annotation.Bean#interceptor Bean(interceptor)}
  - {@link oaj.BeanContextBuilder#beanInterceptor(Class,Class)}
- Fluent setters that follow the withX convention are now automatically detected by all parsers.

  // A bean with a fluent setter. public class MyBean { public MyBean withFoo(String foo) { this.foo = foo; return this; } }

  Note you could previously use the @BeanProperty annotation to identify these setters.

##### juneau-rest-server

- New {@link oajr.RestContext#REST_context REST_context}/{@link oajr.annotation.Rest#context() @Rest(context)} setting to allow you to extend the {@link oajr.RestContext} class.
- {@link oajr.annotation.Rest}-annotated classes can now implement the following interfaces directly instead of having to define secondary classes and hook them up through annotations:
  - {@link oajr.RestCallHandler} - Normally defined through {@link oajr.annotation.Rest#callHandler() @Rest.callHandler()}.
  - {@link oajr.RestInfoProvider} - Normally defined through {@link oajr.annotation.Rest#infoProvider() @Rest.infoProvider()}.
  - {@link oajr.RestCallLogger} - Normally defined through {@link oajr.annotation.Rest#callLogger() @Rest.callLogger()}.
  - {@link oaj.utils.ClasspathResourceFinder} - Normally defined through {@link oajr.annotation.Rest#classpathResourceFinder() @Rest.classpathResourceFinder()}.
  The methods added for {@link oajr.RestInfoProvider} are:
  - {@link oajr.RestServlet}
    - {@link oajr.RestServlet#getSwagger(RestRequest) getSwagger(RestRequest)}
    - {@link oajr.RestServlet#getSiteName(RestRequest) getSiteName(RestRequest)}
    - {@link oajr.RestServlet#getTitle(RestRequest) getTitle(RestRequest)}
    - {@link oajr.RestServlet#getDescription(RestRequest) getDescription(RestRequest)}
    - {@link oajr.RestServlet#getMethodSummary(Method,RestRequest) getMethodSummary(Method,RestRequest)}
    - {@link oajr.RestServlet#getMethodDescription(Method,RestRequest) getMethodDescription(Method,RestRequest)}
  - {@link oajr.BasicRest}
    - {@link oajr.BasicRest#getSwagger(RestRequest) getSwagger(RestRequest)}
    - {@link oajr.BasicRest#getSiteName(RestRequest) getSiteName(RestRequest)}
    - {@link oajr.BasicRest#getTitle(RestRequest) getTitle(RestRequest)}
    - {@link oajr.BasicRest#getDescription(RestRequest) getDescription(RestRequest)}
    - {@link oajr.BasicRest#getMethodSummary(Method,RestRequest) getMethodSummary(Method,RestRequest)}
    - {@link oajr.BasicRest#getMethodDescription(Method,RestRequest) getMethodDescription(Method,RestRequest)}
  The methods added for {@link oajr.RestCallLogger} are:
  - {@link oajr.RestServlet}
    - {@link oajr.RestServlet#log(RestCallLoggerConfig,HttpServletRequest,HttpServletResponse) log(RestCallLoggerConfig,HttpServletRequest,HttpServletResponse)}
  - {@link oajr.BasicRest}
    - {@link oajr.BasicRest#log(RestCallLoggerConfig,HttpServletRequest,HttpServletResponse) log(RestCallLoggerConfig,HttpServletRequest,HttpServletResponse)}
  The methods added for {@link oaj.utils.ClasspathResourceFinder} are:
  - {@link oajr.RestServlet}
    - {@link oajr.RestServlet#findResource(Class,String,Locale) findResource(Class,String,Locale)}
  - {@link oajr.BasicRest}
    - {@link oajr.BasicRest#findResource(Class,String,Locale) findResource(Class,String,Locale)}
  The methods added for {@link oajr.RestResourceResolver} are:
  - {@link oajr.RestServlet}
    - {@link oajr.RestServlet#resolve(Object,Class,RestContextBuilder,Object...) resolve(Object,Class<T>,RestContextBuilder,Object...)}
  - {@link oajr.BasicRest}
    - {@link oajr.BasicRest#resolve(Object,Class,RestContextBuilder,Object...) resolve(Object,Class<T>,RestContextBuilder,Object...)}
- Added the following convenience hook methods on the {@link oajr.RestServlet} and {@link oajr.BasicRest} classes:
  - {@link oajr.RestServlet}
    - {@link oajr.RestServlet#onInit(RestContextBuilder) onInit(RestContextBuilder)}
    - {@link oajr.RestServlet#onPostInit(RestContext) onPostInit(RestContext)}
    - {@link oajr.RestServlet#onPostInitChildFirst(RestContext) onPostInitChildFirst(RestContext)}
    - {@link oajr.RestServlet#onDestroy(RestContext) onDestroy(RestContext)}
    - {@link oajr.RestServlet#onStartCall(HttpServletRequest,HttpServletResponse) onStartCall(HttpServletRequest,HttpServletResponse)}
    - {@link oajr.RestServlet#onPreCall(RestRequest,RestResponse) onPreCall(RestRequest,RestResponse)}
    - {@link oajr.RestServlet#onPostCall(RestRequest,RestResponse) onPostCall(RestRequest,RestResponse)}
    - {@link oajr.RestServlet#onEndCall(HttpServletRequest,HttpServletResponse) onEndCall(HttpServletRequest,HttpServletResponse)}
  - {@link oajr.BasicRest}
    - {@link oajr.BasicRest#onInit(RestContextBuilder) onInit(RestContextBuilder)}
    - {@link oajr.BasicRest#onPostInit(RestContext) onPostInit(RestContext)}
    - {@link oajr.BasicRest#onPostInitChildFirst(RestContext) onPostInitChildFirst(RestContext)}
    - {@link oajr.BasicRest#onDestroy(RestContext) onDestroy(RestContext)}
    - {@link oajr.BasicRest#onStartCall(HttpServletRequest,HttpServletResponse) onStartCall(HttpServletRequest,HttpServletResponse)}
    - {@link oajr.BasicRest#onPreCall(RestRequest,RestResponse) onPreCall(RestRequest,RestResponse)}
    - {@link oajr.BasicRest#onPostCall(RestRequest,RestResponse) onPostCall(RestRequest,RestResponse)}
    - {@link oajr.BasicRest#onEndCall(HttpServletRequest,HttpServletResponse) onEndCall(HttpServletRequest,HttpServletResponse)}
- New {@link oajr.annotation.Rest#debugOn() @Rest(debugOn)} annotation for turning on debug mode using class/method identifiers:

  ##### Example:

  // Turn on debug per-request on the class and always on the doX() method. @Rest( debugOn="MyResource=per-request,Mysource.doX=true" // Typically defined via system or env property. ) public class MyResource { @RestMethod public void String doX() { ... }

- {@link oajr.BasicRestConfig} has been broken up into {@link oajr.BasicRestConfig} and {@link oajr.BasicRestMethods} so that you're not forced to implement methods such as getOptions() and getStats() if you're implementing the interface to configure your REST class.
- Any of the following classes can now be instantiated with public static create() methods:
  - {@link oajr.RestCallHandler}
  - {@link oajr.RestCallLogger}
  - {@link oajr.RestInfoProvider}
  - {@link oaj.utils.ClasspathResourceFinder}
  - {@link oajr.RestResourceResolver}
  - {@link oajr.RestGuard}
  - {@link oajr.ResponseHandler}
- New {@link oaj.http.annotation.Path#required() @Path(required)} annotation support.
  A path can be marked as not-required when the path variable is resolved by a parent resource like so:

  @Rest(path="/parent/{p1}",children=Child.class) public class Parent { ... } @Rest(path="/child") public class Child { @RestMethod(path="/") public String doGet(@Path(name="p1",required=false) String p1) { // p1 will be null when accessed via "/child" // p1 will be non-null when accessed via "/parent/p1/child". } ... }

  This allows the child resource to be mapped to multiple parents that may resolve various different path variables.
- New {@link oajr.annotation.RestMethod#paths() @RestMethod(paths)} annotation that allows you to map multiple paths to the same Java method.
  Example:

  @RestMethod( name=GET, paths={"/","/{foo}"} ) public String doGet(@Path(name="foo",required=false) String foo) {...}

- The {@link oajr.annotation.RestMethod @RestMethod} annotation is now implied on all unannotated methods of a {@link oajr.annotation.Rest @Rest}-annotated interface.

  @Rest public interface MyRest { String getFoo(); // @RestMethod(name=GET,path="/foo") is implied. }

- Improved {@link oajr.RestContext#REST_messages REST_messages} support (mostly bug fixes).

##### juneau-rest-server-springboot

- {@link oajr.springboot.JuneauRestInitializer} now provides a no-arg constructor so that it can be used in the @ConfigurationContext(initializers=JuneauRestInitializer.class) when unit testing using @SpringBootTest.
- New {@link oajr.helper.ResourceDescription#ResourceDescription(String,String,String)} constructor and {@link oajr.helper.ResourceDescriptions#append(String,String,String)} method.
- New {@link oajr.helper.Hyperlink} class.

##### juneau-rest-client

- Completely revamped RestClient API.
  - All APIs now extend from HttpClient interfaces.
  - Better integration with HttpClient.
  - New fluent-style methods with many new convenience methods.
  - Updated {@doc juneau-rest-client documentation}.
- @RemoteMethod-annotated methods can now return {@link java.util.concurrent.Future Futures} and {@link java.util.concurrent.CompletableFuture CompletableFutures} for concurrent processing of requests.
  Example:

  @Remote public interface MyInterface { public Future<String> doGet(); } MyInterface i = client.getRemote(MyInterface.class, "http://localhost:12345/myInterface"); Future<String> f = i.doGet(); // Do other stuff. String result = f.get();

- Additions to {@link oaj.http.remote.Remote} annotation:
  - {@link oaj.http.remote.Remote#version version} - Adds a client version header to all requests.
  - {@link oaj.http.remote.Remote#headers headers} - Adds a set of headers to all requests.
  - {@link oaj.http.remote.Remote#headerSupplier headerSupplier} - Adds a dynamic supplier of headers to all requests.

##### juneau-rest-mock

- The MockRest and MockRemote classes have been remove entirely and all existing functions have been moved into the improved {@link oajr.mock2.MockRestClient} class. All REST test mocking can be done through this single class.