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 ConfigFile:
    - ConfigFile.getStringArray(String),ConfigFile.getStringArray(String,String[])
    - ConfigFile.getSectionAsBean(String,Class) - Instantiate a new bean with property values in the specified section..
    - ConfigFile.writeProperties(String,Object,boolean,Class[]) - Copy the properties in a config file section into properties on an existing bean or POJO.
    - ConfigFile.getSectionMap(String) - Get all the resolved values in a section.
    - ConfigFile.containsNonEmptyValue(String)
    - ConfigFile.isEncoded(String)
    - ConfigFile.addListener(ConfigFileListener) - Listen for modification events on the config file.
    - ConfigFile.merge(ConfigFile) - Merge the contents of another config file into this config file.
    - ConfigFile.getResolving(), 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.
    - ConfigFile.toWritable() - Wraps the config file in a {@link 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.
    - ConfigFile.getInt(String) - Now supports "M" and "K" to identify millions and thousands.
  - New methods in ConfigMgr:
    - ConfigMgr.create(), ConfigMgr.create(Reader), ConfigMgr.create(File)
    - ConfigMgr.deleteAll()
  - New methods in Section:
    - Section.setParent(ConfigFileImpl) - Used by parsers to set the config file for this section.
    - Section.setName(String) - Used by parsers to set the name for this section.
  - New interfaces:
    - org.apache.juneau.config.ConfigFileListener
    - org.apache.juneau.config.SectionListener
    - org.apache.juneau.config.EntryListener
  - 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.
  - 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 Section class represents a section in a config file. It needs to know it's own name and have a link to the ConfigFile that it belongs to. With these new annotations, config files can be reconstructed using any of the parsers.
- New classes and interfaces:
  - {@link oaj.Streamable} interface for identifying objects that can be serialized directly to an output stream.
  - {@link oaj.Writable} interface for identifying objects that can be serialized directly to a writer.
  - StringObject class that can be used for delayed object serialization.
  - ByteArrayCache
  - {@link oaj.internal.ByteArrayInOutStream}
  - {@link oaj.internal.FileUtils}
  - {@link oaj.internal.ThrowableUtils}
  - StringVarMultipart
  - StringVarWithDefault
- New fields on {@link oaj.ObjectList}:
  - {@link oaj.ObjectList#EMPTY_LIST}
- New fields and methods on {@link oaj.ObjectMap}:
  - {@link oaj.ObjectMap#EMPTY_MAP}
  - {@link oaj.ObjectMap#getStringArray(String)}
  - {@link oaj.ObjectMap#getStringArray(String,String[])}
  - {@link oaj.ObjectMap#putIfNull(String,Object)}
  - {@link oaj.ObjectMap#putIfEmpty(String,Object)}
- New methods in {@link oaj.internal.ArrayUtils}:
  - {@link oaj.internal.ArrayUtils#contains(Object,Object[])}
  - {@link oaj.internal.ArrayUtils#indexOf(Object,Object[])}
  - {@link oaj.internal.ArrayUtils#toPrimitiveArray(Object)}
- New methods in {@link oaj.internal.IOUtils}:
  - IOUtils.pipe(Reader,Writer)
  - {@link oaj.internal.IOUtils#read(File)}
  - {@link oaj.internal.IOUtils#readFile(String)}
  - {@link oaj.internal.IOUtils#write(File,Reader)}
- New methods on {@link oaj.utils.PojoRest}:
  - PojoRest.get(Class,String,Object)
  - {@link oaj.utils.PojoRest#getString(String)}
  - {@link oaj.utils.PojoRest#getString(String,String)}
  - {@link oaj.utils.PojoRest#getInt(String)}
  - {@link oaj.utils.PojoRest#getInt(String,Integer)}
  - {@link oaj.utils.PojoRest#getLong(String)}
  - {@link oaj.utils.PojoRest#getLong(String,Long)}
  - {@link oaj.utils.PojoRest#getBoolean(String)}
  - {@link oaj.utils.PojoRest#getBoolean(String,Boolean)}
  - {@link oaj.utils.PojoRest#getMap(String)}
  - {@link oaj.utils.PojoRest#getMap(String,Map)}
  - {@link oaj.utils.PojoRest#getList(String)}
  - {@link oaj.utils.PojoRest#getList(String,List)}
  - {@link oaj.utils.PojoRest#getObjectMap(String)}
  - {@link oaj.utils.PojoRest#getObjectMap(String,ObjectMap)}
  - {@link oaj.utils.PojoRest#getObjectList(String)}
  - {@link oaj.utils.PojoRest#getObjectList(String,ObjectList)}
- New methods on {@link oaj.utils.ProcBuilder}:
  - {@link oaj.utils.ProcBuilder#pipeTo(Writer,boolean)}
  - {@link oaj.utils.ProcBuilder#pipeTo(Writer)}
  - {@link oaj.utils.ProcBuilder#logTo(Writer,boolean)}
  - {@link oaj.utils.ProcBuilder#logTo(Writer)}
  - {@link oaj.utils.ProcBuilder#logTo(Level,Logger)}
  - {@link oaj.utils.ProcBuilder#maxExitStatus(int)}
- New methods on {@link oaj.internal.StringUtils}:
  - {@link 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)}
  - {@link oaj.internal.StringUtils#generateUUID(int)}
  - {@link oaj.internal.StringUtils#trim(String)}
  - StringUtils.parseISO8601Date(String)
  - {@link oaj.internal.StringUtils#replaceVars(String,Map)}
  - {@link oaj.internal.StringUtils#pathStartsWith(String,String)}
  - {@link oaj.internal.StringUtils#pathStartsWith(String,String[])}
- New StringVar.doResolve(String) method.
- New StringVarResolver.DEFAULT field.
- Eliminated dependency on javax.mail.internet.MimeUtility by implementing our own {@link oaj.internal.StringUtils#base64Encode(byte[])} method.
- {@link oaj.transforms.CalendarSwap} and {@link 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 HtmlSchemaSerializer to 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.
- {@link oaj.serializer.SerializerGroup} and {@link 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 UrlEncodingSerializer.DEFAULT_SIMPLE_EXPANDED serializer.
- Changes to Args:
  - getMainArg(int) changed to 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 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.
- {@link oaj.utils.PojoIntrospector} must now be instantiated with a ReaderParser. Simplifies the API on the class.
- {@link oaj.utils.PojoRest} must now be instantiated with a ReaderParser. Simplifies the API on the class.
- {@link oaj.utils.MessageBundle} and SafeResourceMultiBundle moved from server component.
- Several bug fixes and performance improvements in StringVarResolver.
- Various enhancements to {@link oaj.internal.TeeWriter} and {@link oaj.internal.TeeOutputStream}.
- Renamed CharSet to {@link oaj.internal.AsciiSet}.
- {@link oaj.serializer.SerializerGroup} and {@link 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:
  - {@link oajrc.AllowAllRedirects}
  - {@link oajrc.HttpMethod}
  - {@link oajrc.ResponsePattern}
  - {@link oajrc.SimpleX509TrustManager}
  - SSLOpts
- Removed org.apache.juneau.rest.client.LaxRedirectStrategy. Use HTTP Client equivalent.
- New methods on {@link oajrc.RestCall}:
  - RestCall#addInterceptor(RestCallInterceptor)
  - {@link oajrc.RestCall#pipeTo(Writer)}
  - {@link oajrc.RestCall#pipeTo(Writer,boolean)}
  - {@link oajrc.RestCall#pipeTo(String,Writer,boolean)}
  - {@link oajrc.RestCall#getWriter(String)}
  - {@link oajrc.RestCall#pipeTo(OutputStream)}
  - {@link oajrc.RestCall#pipeTo(OutputStream,boolean)}
  - {@link oajrc.RestCall#pipeTo(String,OutputStream,boolean)}
  - {@link oajrc.RestCall#getOutputStream(String)}
  - {@link oajrc.RestCall#byLines()}
  - {@link oajrc.RestCall#captureResponse()}
  - {@link oajrc.RestCall#successPattern(String)}
  - {@link oajrc.RestCall#failurePattern(String)}
  - RestCall#addResponsePattern(ResponsePattern)
  - {@link oajrc.RestCall#run()} - Renamed from execute().
  - {@link oajrc.RestCall#getCapturedResponse()}
  - {@link oajrc.RestCall#getResponsePojoRest(Class)}
  - {@link oajrc.RestCall#getResponsePojoRest()}
  - {@link oajrc.RestCall#logTo(Level,Logger)}
  - {@link oajrc.RestCall#setConfig(RequestConfig)}
- New lifecycle listener methods on {@link oajrc.RestCallInterceptor}:
  - {@link oajrc.RestCallInterceptor#onInit(RestCall)}
  - {@link oajrc.RestCallInterceptor#onClose(RestCall)}
- New methods on {@link oajrc.RestClient}:
  - RestClient.setBasicAuth(String,int,String,String)
  - RestClient.logTo(Level,Logger)
  - RestClient.setRootUrl(String)
  - RestClient.enableSSL(SSLOpts)
  - RestClient.enableLaxSSL()
  - {@link oajrc.RestClient#doCall(HttpMethod,Object,Object)}
  - RestClient.createHttpClientBuilder()
- New passthrough methods on {@link oajrc.RestClient} defined on HttpClientBuilder:
  - RestClient.setRedirectStrategy(RedirectStrategy)
  - RestClient.setDefaultCookieSpecRegistry(Lookup)
  - RestClient.setRequestExecutor(HttpRequestExecutor)
  - RestClient.setSSLHostnameVerifier(HostnameVerifier)
  - RestClient.setPublicSuffixMatcher(PublicSuffixMatcher)
  - RestClient.setSSLContext(SSLContext)
  - RestClient.setSSLSocketFactory(LayeredConnectionSocketFactory)
  - RestClient.setMaxConnTotal(int)
  - RestClient.setMaxConnPerRoute(int)
  - RestClient.setDefaultSocketConfig(SocketConfig)
  - RestClient.setDefaultConnectionConfig(ConnectionConfig)
  - RestClient.setConnectionTimeToLive(long,TimeUnit)
  - RestClient.setConnectionManager(HttpClientConnectionManager)
  - RestClient.setConnectionManagerShared(boolean)
  - RestClient.setConnectionReuseStrategy(ConnectionReuseStrategy)
  - RestClient.setKeepAliveStrategy(ConnectionKeepAliveStrategy)
  - RestClient.setTargetAuthenticationStrategy(AuthenticationStrategy)
  - RestClient.setProxyAuthenticationStrategy(AuthenticationStrategy)
  - RestClient.setUserTokenHandler(UserTokenHandler)
  - RestClient.disableConnectionState()
  - RestClient.setSchemePortResolver(SchemePortResolver)
  - RestClient.setUserAgent(String userAgent)
  - RestClient.setDefaultHeaders(Collection)
  - RestClient.addInterceptorFirst(HttpResponseInterceptor)
  - RestClient.addInterceptorLast(HttpResponseInterceptor)
  - RestClient.addInterceptorFirst(HttpRequestInterceptor)
  - RestClient.addInterceptorLast(HttpRequestInterceptor)
  - RestClient.disableCookieManagement()
  - RestClient.disableContentCompression()
  - RestClient.disableAuthCaching()
  - RestClient.setHttpProcessor(HttpProcessor)
  - RestClient.setRetryHandler(HttpRequestRetryHandler)
  - RestClient.disableAutomaticRetries()
  - RestClient.setProxy(HttpHost)
  - RestClient.setRoutePlanner(HttpRoutePlanner)
  - RestClient.disableRedirectHandling()
  - RestClient.setConnectionBackoffStrategy(ConnectionBackoffStrategy)
  - RestClient.setBackoffManager(BackoffManager)
  - RestClient.setServiceUnavailableRetryStrategy(ServiceUnavailableRetryStrategy)
  - RestClient.setDefaultCookieStore(CookieStore)
  - RestClient.setDefaultCredentialsProvider(CredentialsProvider)
  - RestClient.setDefaultAuthSchemeRegistry(Lookup)
  - RestClient.setContentDecoderRegistry(Map)
  - RestClient.setDefaultRequestConfig(RequestConfig)
  - RestClient.useSystemProperties()
  - RestClient.evictExpiredConnections()
  - 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 ReaderResource class. Represents the contents of a text file with convenience methods for resolving StringVar variables and adding HTTP response headers. REST Java methods can return instances of these to serialize Readers containing text with StringVarResolver variables in them.
- New StreamResource class. REST Java methods can return instances of these to serialize OutputStreams.
- Fixed a bug in the stack trace hash algorithm in {@link oajr.RestException}.
- New methods in {@link oajr.RestRequest}:
  - RestRequest.getReaderResource(String) - Replaces getVarResource(String).
  - RestRequest.getReaderResource(String,boolean)
  - 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 {@link oajr.RestServlet}:
  - RestServlet.getChildClasses() - Programmatic equivalent to @RestResource(children) annotation.
  - RestServlet.shouldLog(HttpServletRequest,HttpServletResponse,RestException)
  - RestServlet.shouldLogStackTrace(HttpServletRequest,HttpServletResponse,RestException)
  - RestServlet.logObjects(Level,String,Object[])
  - RestServlet.resolveStaticFile(String)
  - RestServlet.createStyleSheet()
  - RestServlet.createFavIcon()
  - RestServlet.createStaticFilesMap()
  - RestServlet.getConfigMgr()
- Removed {@link oaj.jso.JsoParser} from {@link oajr.BasicRestServlet} and RestServletJenaDefault. These may represent a security risk if not handled correctly, so removed them as a precaution.
- Removed RestServletProperties.REST_htDocsFolder. Replaced with @RestResource(staticFiles)}.
- New annotations on @RestResource.
  - RestResource.stylesheet()
  - RestResource.favicon()
  - @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 ResourceLink.ResourceLink(String,RestRequest,String,Object[]) constructor.
- New response handlers:
  - StreamableHandler - Allows REST Java methods to return instances of {@link oaj.Streamable}.
  - WritableHandler - Allows REST Java methods to return instances of {@link 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 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 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.
- Resource and 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 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

- org.apache.juneau.microservice - New package-level javadoc.
- org.apache.juneau.config - New package-level javadoc.
- StringVarResolver - New documentation.
- org.apache.juneau.rest.client - New package-level javadoc.
- Overview / Samples - New section.
- org.apache.juneau.transform / Stop Classes - New section.
- org.apache.juneau.rest - Extensive updates.