5.2.0.0 (Dec 30, 2015)

Juno 5.2.0.0 is a major update. Major changes have been made to the microservice architecture and config INI file APIs.

##### Core

- Significant changes and enhancements to the org.apache.juneau.config API.
  - More consistent handling of comma-delimited lists of objects.
  - New methods in {@del ConfigFile}:
    - {@del ConfigFile#getStringArray(String)},{@del ConfigFile#getStringArray(String,String[])}
    - {@del ConfigFile#getSectionAsBean(String,Class)} - Instantiate a new bean with property values in the specified section..
    - {@del ConfigFile#writeProperties(String,Object,boolean,Class[])} - Copy the properties in a config file section into properties on an existing bean or POJO.
    - {@del ConfigFile#getSectionMap(String)} - Get all the resolved values in a section.
    - {@del ConfigFile#containsNonEmptyValue(String)}
    - {@del ConfigFile#isEncoded(String)}
    - {@del ConfigFile#addListener(ConfigFileListener)} - Listen for modification events on the config file.
    - {@del ConfigFile#merge(ConfigFile)} - Merge the contents of another config file into this config file.
    - {@del ConfigFile#getResolving()}, {@del ConfigFile#getResolving(StringVarResolver)} - Return an instance of the config file that resolves string variables. Much more efficient than the previous design since the same underlying config file object is shared.
    - {@del ConfigFile#toWritable()} - Wraps the config file in a {@del oaj.Writable} interface so that it can be serialized by the REST interface as a plain-text INI file instead of as a serialized POJO.
    - {@del ConfigFile#getInt(String)} - Now supports "M" and "K" to identify millions and thousands.
  - New methods in {@del ConfigMgr}:
    - {@del ConfigMgr#create()}, {@del ConfigMgr#create(Reader)}, {@del ConfigMgr#create(File)}
    - {@del ConfigMgr#deleteAll()}
  - New methods in {@del Section}:
    - {@del Section#setParent(ConfigFileImpl)} - Used by parsers to set the config file for this section.
    - {@del Section#setName(String)} - Used by parsers to set the name for this section.
  - New interfaces:
    - {@del org.apache.juneau.config.ConfigFileListener}
    - {@del org.apache.juneau.config.SectionListener}
    - {@del org.apache.juneau.config.EntryListener}
  - {@del org.apache.juneau.config.Encoder} methods have access to field names to use them as salt values.
  - The name of the default section is now "default". Before it was just null.
  - {@del org.apache.juneau.config.XorEncoder} XOR key can be overridden through the "org.apache.juneau.config.XorEncoder.key" system property.
- Support for converting Strings to POJOs if the POJO class has any of the following static methods:
  - fromString(String)
  - valueOf(String) (e.g. enums)
  - parse(String) (e.g. logging Level class)
  - parseString(String)
  - forName(String) (e.g. Class and Charset classes)
- Support for parsing into objects with unbound type variables. For example, if you have a class Pair<S,T> and you try to parse into this class (e.g. parser.parse(in, Pair.class)), the unbound type variables is interpreted as Object instead of throwing an exception.
- Support for serializing/parsing the following new types:
  - AtomicInteger
  - AtomicLong
  - BigInteger
  - BigDecimal
- Parsers have been enhanced to allow parent POJOs and field names to be passed into child POJOs. New {@link oaj.annotation.NameProperty @NameProperty} and {@link oaj.annotation.ParentProperty @ParentProperty} annotations are provided for identifying methods for setting names and parent POJOs on child POJOs. For example, the config file {@del Section} class represents a section in a config file. It needs to know it's own name and have a link to the {@del ConfigFile} that it belongs to. With these new annotations, config files can be reconstructed using any of the parsers.
- New classes and interfaces:
  - {@del oaj.Streamable} interface for identifying objects that can be serialized directly to an output stream.
  - {@del oaj.Writable} interface for identifying objects that can be serialized directly to a writer.
  - {@del StringObject} class that can be used for delayed object serialization.
  - {@del ByteArrayCache}
  - {@del oaj.internal.ByteArrayInOutStream}
  - {@link oaj.internal.FileUtils}
  - {@link oaj.internal.ThrowableUtils}
  - {@del StringVarMultipart}
  - {@del StringVarWithDefault}
- New fields on {@del oaj.ObjectList}:
  - {@del oaj.ObjectList#EMPTY_LIST}
- New fields and methods on {@del oaj.ObjectMap}:
  - {@del oaj.ObjectMap#EMPTY_MAP}
  - {@del oaj.ObjectMap#getStringArray(String)}
  - {@del oaj.ObjectMap#getStringArray(String,String[])}
  - {@del oaj.ObjectMap#putIfNull(String,Object)}
  - {@del oaj.ObjectMap#putIfEmpty(String,Object)}
- New methods in {@link oaj.internal.ArrayUtils}:
  - {@del oaj.internal.ArrayUtils#contains(Object,Object[])}
  - {@del oaj.internal.ArrayUtils#indexOf(Object,Object[])}
  - {@del oaj.internal.ArrayUtils#toPrimitiveArray(Object)}
- New methods in {@link oaj.internal.IOUtils}:
  - {@del IOUtils#pipe(Reader,Writer)}
  - {@link oaj.internal.IOUtils#read(File)}
  - {@del IOUtils#readFile(String)}
  - {@del IOUtils#write(File,Reader)}
- New methods on {@del oaj.utils.PojoRest}:
  - {@del PojoRest#get(Class,String,Object)}
  - {@del oaj.utils.PojoRest#getString(String)}
  - {@del oaj.utils.PojoRest#getString(String,String)}
  - {@del oaj.utils.PojoRest#getInt(String)}
  - {@del oaj.utils.PojoRest#getInt(String,Integer)}
  - {@del oaj.utils.PojoRest#getLong(String)}
  - {@del oaj.utils.PojoRest#getLong(String,Long)}
  - {@del oaj.utils.PojoRest#getBoolean(String)}
  - {@del oaj.utils.PojoRest#getBoolean(String,Boolean)}
  - {@del oaj.utils.PojoRest#getMap(String)}
  - {@del oaj.utils.PojoRest#getMap(String,Map)}
  - {@del oaj.utils.PojoRest#getList(String)}
  - {@del oaj.utils.PojoRest#getList(String,List)}
  - {@del getObjectMap(String)}
  - {@del getObjectMap(String,ObjectMap)}
  - {@del getObjectList(String)}
  - {@del getObjectList(String,ObjectList)}
- New methods on {@del oaj.utils.ProcBuilder}:
  - {@del oaj.utils.ProcBuilder#pipeTo(Writer,boolean)}
  - {@del oaj.utils.ProcBuilder#pipeTo(Writer)}
  - {@del oaj.utils.ProcBuilder#logTo(Writer,boolean)}
  - {@del oaj.utils.ProcBuilder#logTo(Writer)}
  - {@del oaj.utils.ProcBuilder#logTo(Level,Logger)}
  - {@del oaj.utils.ProcBuilder#maxExitStatus(int)}
- New methods on {@link oaj.internal.StringUtils}:
  - {@del oaj.internal.StringUtils#isEmpty(Object)}
  - {@link oaj.internal.StringUtils#nullIfEmpty(String)}
  - {@link oaj.internal.StringUtils#base64EncodeToString(String)}
  - {@link oaj.internal.StringUtils#base64Encode(byte[])}
  - {@link oaj.internal.StringUtils#base64DecodeToString(String)}
  - {@link oaj.internal.StringUtils#base64Decode(String)}
  - {@del oaj.internal.StringUtils#generateUUID(int)}
  - {@link oaj.internal.StringUtils#trim(String)}
  - {@del StringUtils#parseISO8601Date(String)}
  - {@link oaj.internal.StringUtils#replaceVars(String,Map)}
  - {@del oaj.internal.StringUtils#pathStartsWith(String,String)}
  - {@del oaj.internal.StringUtils#pathStartsWith(String,String[])}
- New {@del StringVar#doResolve(String)} method.
- New {@del StringVarResolver#DEFAULT} field.
- Eliminated dependency on javax.mail.internet.MimeUtility by implementing our own {@link oaj.internal.StringUtils#base64Encode(byte[])} method.
- {@del oaj.transforms.CalendarSwap} and {@del oaj.transforms.DateSwap} classes now handle blank input better. Returns null instead of throwing an exception.
- {@link oaj.html.HtmlDocSerializer} specifies the default CSS location as /servletPath/style.css instead of /servletPath/htdocs/juneau.css. This coincides with enhancements made in the server code for specifying styles.
- {@link oaj.html.HtmlDocSerializer} wraps output in two div tags instead of one (e.g. <div class='outerdata'><div class='data' id='data'>...</div></div>). Needed for supporting the new devops look-and-feel.
- Fixed indentation inconsistencies in {@link oaj.html.HtmlDocSerializer}.
- Renamed {@del HtmlSchemaSerializer} to {@del HtmlSchemaDocSerializer}.
- RDF serializers and parsers now support RdfProperties.RDF_looseCollection loose collections.
- RDF parser handles case where resources point to themselves (an unfortunate behavior in JFS RDF documents).
- JSON parser with throw an exception in strict mode if it encounters numbers that are valid in Java but invalid in JSON (e.g. octal, hexadecimal numbers).
- {@link oaj.parser.Parser} methods now check for null input.
- {@del oaj.serializer.SerializerGroup} and {@del oaj.parser.ParserGroup} ignores serializers and parsers if they throw NoClassDefFoundErrors.
- {@link oaj.urlencoding.UrlEncodingParser} creates lists if the same attribute name is encountered more than once. Before it would just replace the previous value with the new value.
- New {@del UrlEncodingSerializer#DEFAULT_SIMPLE_EXPANDED} serializer.
- Changes to {@del Args}:
  - getMainArg(int) changed to {@del Args#getArg(int)}. Non-existent arguments are returned as null instead of blank strings. This is more inline with the behavior of the rest of the library.
  - New {@del Args#hasArg(int)} method.
- Removed org.apache.juneau.utils.CharsetUtils class.
- Removed org.apache.juneau.utils.ConcurrentIdentityList class.
- Fixed bug in {@link oaj.internal.MultiIterable} class.
- {@del oaj.utils.PojoIntrospector} must now be instantiated with a ReaderParser. Simplifies the API on the class.
- {@del oaj.utils.PojoRest} must now be instantiated with a ReaderParser. Simplifies the API on the class.
- {@del oaj.utils.MessageBundle} and SafeResourceMultiBundle moved from server component.
- Several bug fixes and performance improvements in {@del StringVarResolver}.
- Various enhancements to {@del oaj.internal.TeeWriter} and {@del oaj.internal.TeeOutputStream}.
- Renamed {@del CharSet} to {@link oaj.internal.AsciiSet}.
- {@del oaj.serializer.SerializerGroup} and {@del oaj.parser.ParserGroup} now ignores NoClassDefFoundErrors so that resources that include Jena support can continue to operate even if the Jena libraries are not present.
- New {@link oaj.internal.FileUtils#createTempFile(String)} method.
- New {@link oaj.utils.PojoQuery} modified to handle bean getters that throw exceptions.

##### Client

- Upgraded to use Apache HttpClient 4.5.
- New classes:
  - {@del oajrc.AllowAllRedirects}
  - {@del oajrc.HttpMethod}
  - {@del oajrc.ResponsePattern}
  - {@del oajrc.SimpleX509TrustManager}
  - {@del SSLOpts}
- Removed org.apache.juneau.rest.client.LaxRedirectStrategy. Use HTTP Client equivalent.
- New methods on {@del oajrc.RestCall}:
  - {@del RestCall#addInterceptor(RestCallInterceptor)}
  - {@del oajrc.RestCall#pipeTo(Writer)}
  - {@del oajrc.RestCall#pipeTo(Writer,boolean)}
  - {@del oajrc.RestCall#pipeTo(String,Writer,boolean)}
  - {@del oajrc.RestCall#getWriter(String)}
  - {@del oajrc.RestCall#pipeTo(OutputStream)}
  - {@del oajrc.RestCall#pipeTo(OutputStream,boolean)}
  - {@del oajrc.RestCall#pipeTo(String,OutputStream,boolean)}
  - {@del oajrc.RestCall#getOutputStream(String)}
  - {@del oajrc.RestCall#byLines()}
  - {@del oajrc.RestCall#captureResponse()}
  - {@del oajrc.RestCall#successPattern(String)}
  - {@del oajrc.RestCall#failurePattern(String)}
  - {@del RestCall#addResponsePattern(ResponsePattern)}
  - {@del oajrc.RestCall#run()} - Renamed from execute().
  - {@del oajrc.RestCall#getCapturedResponse()}
  - {@del oajrc.RestCall#getResponsePojoRest(Class)}
  - {@del oajrc.RestCall#getResponsePojoRest()}
  - {@del oajrc.RestCall#logTo(Level,Logger)}
  - {@del oajrc.RestCall#setConfig(RequestConfig)}
- New lifecycle listener methods on {@del oajrc.RestCallInterceptor}:
  - {@del RestCallInterceptor#onInit(RestCall)}
  - {@del RestCallInterceptor#onClose(RestCall)}
- New methods on {@link oajrc.RestClient}:
  - {@del RestClient#setBasicAuth(String,int,String,String)}
  - {@del RestClient#logTo(Level,Logger)}
  - {@del RestClient#setRootUrl(String)}
  - {@del RestClient#enableSSL(SSLOpts)}
  - {@del RestClient#enableLaxSSL()}
  - {@del RestClient#doCall(HttpMethod,Object,Object)}
  - {@del RestClient#createHttpClientBuilder()}
- New passthrough methods on {@link oajrc.RestClient} defined on HttpClientBuilder:
  - {@del RestClient#setRedirectStrategy(RedirectStrategy)}
  - {@del RestClient#setDefaultCookieSpecRegistry(Lookup)}
  - {@del RestClient#setRequestExecutor(HttpRequestExecutor)}
  - {@del RestClient#setSSLHostnameVerifier(HostnameVerifier)}
  - {@del RestClient#setPublicSuffixMatcher(PublicSuffixMatcher)}
  - {@del RestClient#setSSLContext(SSLContext)}
  - {@del RestClient#setSSLSocketFactory(LayeredConnectionSocketFactory)}
  - {@del RestClient#setMaxConnTotal(int)}
  - {@del RestClient#setMaxConnPerRoute(int)}
  - {@del RestClient#setDefaultSocketConfig(SocketConfig)}
  - {@del RestClient#setDefaultConnectionConfig(ConnectionConfig)}
  - {@del RestClient#setConnectionTimeToLive(long,TimeUnit)}
  - {@del RestClient#setConnectionManager(HttpClientConnectionManager)}
  - {@del RestClient#setConnectionManagerShared(boolean)}
  - {@del RestClient#setConnectionReuseStrategy(ConnectionReuseStrategy)}
  - {@del RestClient#setKeepAliveStrategy(ConnectionKeepAliveStrategy)}
  - {@del RestClient#setTargetAuthenticationStrategy(AuthenticationStrategy)}
  - {@del RestClient#setProxyAuthenticationStrategy(AuthenticationStrategy)}
  - {@del RestClient#setUserTokenHandler(UserTokenHandler)}
  - {@del RestClient#disableConnectionState()}
  - {@del RestClient#setSchemePortResolver(SchemePortResolver)}
  - {@del RestClient.setUserAgent(String)}
  - {@del RestClient#setDefaultHeaders(Collection)}
  - {@del RestClient#addInterceptorFirst(HttpResponseInterceptor)}
  - {@del RestClient#addInterceptorLast(HttpResponseInterceptor)}
  - {@del RestClient#addInterceptorFirst(HttpRequestInterceptor)}
  - {@del RestClient#addInterceptorLast(HttpRequestInterceptor)}
  - {@del RestClient#disableCookieManagement()}
  - {@del RestClient#disableContentCompression()}
  - {@del RestClient#disableAuthCaching()}
  - {@del RestClient#setHttpProcessor(HttpProcessor)}
  - {@del RestClient#setRetryHandler(HttpRequestRetryHandler)}
  - {@del RestClient#disableAutomaticRetries()}
  - {@del RestClient#setProxy(HttpHost)}
  - {@del RestClient#setRoutePlanner(HttpRoutePlanner)}
  - {@del RestClient#disableRedirectHandling()}
  - {@del RestClient#setConnectionBackoffStrategy(ConnectionBackoffStrategy)}
  - {@del RestClient#setBackoffManager(BackoffManager)}
  - {@del RestClient#setServiceUnavailableRetryStrategy(ServiceUnavailableRetryStrategy)}
  - {@del RestClient#setDefaultCookieStore(CookieStore)}
  - {@del RestClient#setDefaultCredentialsProvider(CredentialsProvider)}
  - {@del RestClient#setDefaultAuthSchemeRegistry(Lookup)}
  - {@del RestClient#setContentDecoderRegistry(Map)}
  - {@del RestClient#setDefaultRequestConfig(RequestConfig)}
  - {@del RestClient#useSystemProperties()}
  - {@del RestClient#evictExpiredConnections()}
  - {@del RestClient#evictIdleConnections(long,TimeUnit)}
- JazzRestClient now supports OIDC authentication.
- These classes are now deprecated and will be removed in a future release:
  - org.apache.juneau.rest.client.jazz.CertificateStore
  - org.apache.juneau.rest.client.jazz.ICertificateValidator
  - org.apache.juneau.rest.client.jazz.ITrustStoreProvider
  - org.apache.juneau.rest.client.jazz.LenientCertificateValidator
  - org.apache.juneau.rest.client.jazz.SharedTrustStoreProvider
  - org.apache.juneau.rest.client.jazz.ValidatingX509TrustManager

##### Server

- New {@del ReaderResource} class. Represents the contents of a text file with convenience methods for resolving {@del StringVar} variables and adding HTTP response headers. REST Java methods can return instances of these to serialize Readers containing text with {@del StringVarResolver} variables in them.
- New {@del StreamResource} class. REST Java methods can return instances of these to serialize OutputStreams.
- Fixed a bug in the stack trace hash algorithm in {@del oajr.RestException}.
- New methods in {@link oajr.RestRequest}:
  - {@del RestRequest#getReaderResource(String)} - Replaces getVarResource(String).
  - {@del RestRequest#getReaderResource(String,boolean)}
  - {@del RestRequest#getReaderResource(String,boolean,String)}
- Changes in {@link oajr.RestResponse}:
  - Don't set Content-Encoding: identity when no encoding is used. Some clients don't interpret it correctly.
- New methods in {@del oajr.RestServlet}:
  - {@del RestServlet#getChildClasses()} - Programmatic equivalent to {@del @RestResource(children)} annotation.
  - {@del RestServlet#shouldLog(HttpServletRequest,HttpServletResponse,RestException)}
  - {@del RestServlet#shouldLogStackTrace(HttpServletRequest,HttpServletResponse,RestException)}
  - {@del RestServlet#logObjects(Level,String,Object[])}
  - {@del RestServlet#resolveStaticFile(String)}
  - {@del RestServlet#createStyleSheet()}
  - {@del RestServlet#createFavIcon()}
  - {@del RestServlet#createStaticFilesMap()}
  - {@del RestServlet#getConfigMgr()}
- Removed {@del oaj.jso.JsoParser} from {@del oajr.BasicRestServlet} and {@del RestServletJenaDefault}. These may represent a security risk if not handled correctly, so removed them as a precaution.
- Removed RestServletProperties.REST_htDocsFolder. Replaced with {@del @RestResource(staticFiles)}}.
- New annotations on {@del @RestResource}.
  - {@del RestResource#stylesheet()}
  - {@del RestResource#favicon()}
  - {@del @RestResource(staticFiles)}
- Eliminated org.apache.juneau.rest.jaxrs.JsonProvider class. Some JAX-RS implementations use code scanning to find providers, so if you were using DefaultJenaProvider, it would pick up JsonProvider as well. It's easy enough to create your own implementation if needed.
- OPTIONS pages now specify consumes and produces fields instead of accept and contentType which was confusing.
- Eliminated properties from OPTIONS pages.
- New {@del ResourceLink#ResourceLink(String,RestRequest,String,Object[])} constructor.
- New response handlers:
  - {@del StreamableHandler} - Allows REST Java methods to return instances of {@del oaj.Streamable}.
  - {@del WritableHandler} - Allows REST Java methods to return instances of {@del oaj.Writable}.
- New DevOps stylesheet.
- Servlet initialization and HTTP requests are now logged at FINE level.
- Added abstract modifier on various RestServlet subclasses to indicate that they're meant to be subclassed.
- New {@del RestUtils#trimPathInfo(StringBuffer,String,String)} method.

##### Microservice

- Completely revamped API.
- New {@link oaj.microservice.Microservice} class that serves as a generic interface for microservices and their lifecycles.
- New {@del RestMicroservice} class that implements a microservice consisting of a REST interface.
  - REST resources and configuration settings can be defined through either manifest files or config files.
  - Enhanced logging support.
  - Easy-to-configure SSL support.
  - BASIC auth support.
  - Automatic restartability if the config file changes.
- Eliminated org.apache.juneau.microservice.Main class. This is replaced by the microservice classes defined above.
- {@del Resource} and {@del ResourceGroup} classes now support the following new string variables:
  - "$A{key,default}"" - Command line arguments.
  - "$MF{key,default}"" - Manifest file entries.
- CSS stylesheet now configurable through config file entry "REST/stylesheet".
- New {@del BasicRestServletJena} class if you want your REST interface to support RDF.
- Eliminated the following classes:
  - org.apache.juneau.microservice.RootResource
  - org.apache.juneau.microservice.SampleResource
- New predefined reusable resources:
  - {@link oaj.microservice.resources.ConfigResource} - REST resource for viewing and editing microservice config file.
  - {@link oaj.microservice.resources.LogsResource} - REST resource for viewing log files.
  - {@link oaj.microservice.resources.SampleRootResource} - Sample REST resource that contains the config and logs resource as children.
  - {@link oaj.microservice.resources.ShutdownResource} - REST resource for stopping the microservice JVM. Useful for testing purposes.

##### Samples

- Converted to a REST microservice.
- Look-and-feel changed to IBM DevOps.

##### Documentation Updates

- {@del org.apache.juneau.microservice} - New package-level javadoc.
- {@del org.apache.juneau.config} - New package-level javadoc.
- {@del StringVarResolver} - New documentation.
- {@del org.apache.juneau.rest.client} - New package-level javadoc.
- Overview / Samples - New section.
- org.apache.juneau.swap / Stop Classes - New section.
- {@del org.apache.juneau.rest} - Extensive updates.