Skip to main content

Release 5.2.0.0

Date: 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 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:
      • ConfigFileListener
      • SectionListener
      • EntryListener
    • 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.
    • 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 @NameProperty and @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:

    • Streamable interface for identifying objects that can be serialized directly to an output stream.
    • Writable interface for identifying objects that can be serialized directly to a writer.
    • StringObject class that can be used for delayed object serialization.
    • ByteArrayCache
    • ByteArrayInOutStream
    • FileUtils
    • ThrowableUtils
    • StringVarMultipart
    • StringVarWithDefault
  • New fields on ObjectList:

    • ObjectList.EMPTY_LIST
  • New fields and methods on ObjectMap:

    • ObjectMap.EMPTY_MAP
    • ObjectMap.getStringArray(String)
    • ObjectMap.getStringArray(String,String[])
    • ObjectMap.putIfNull(String,Object)
    • ObjectMap.putIfEmpty(String,Object)
  • New methods in ArrayUtils:

    • ArrayUtils.contains(Object,Object[])
    • ArrayUtils.indexOf(Object,Object[])
    • ArrayUtils.toPrimitiveArray(Object)
  • New methods in IOUtils:

    • IOUtils.pipe(Reader,Writer)
    • IOUtils.read(File)
    • IOUtils.readFile(String)
    • IOUtils.write(File,Reader)
  • New methods on PojoRest:

    • PojoRest.get(Class,String,Object)
    • PojoRest.getString(String)
    • PojoRest.getString(String,String)
    • PojoRest.getInt(String)
    • PojoRest.getInt(String,Integer)
    • PojoRest.getLong(String)
    • PojoRest.getLong(String,Long)
    • PojoRest.getBoolean(String)
    • PojoRest.getBoolean(String,Boolean)
    • PojoRest.getMap(String)
    • PojoRest.getMap(String,Map)
    • PojoRest.getList(String)
    • PojoRest.getList(String,List)
    • getObjectMap(String)
    • getObjectMap(String,ObjectMap)
    • getObjectList(String)
    • getObjectList(String,ObjectList)
  • New methods on ProcBuilder:

    • ProcBuilder.pipeTo(Writer,boolean)
    • ProcBuilder.pipeTo(Writer)
    • ProcBuilder.logTo(Writer,boolean)
    • ProcBuilder.logTo(Writer)
    • ProcBuilder.logTo(Level,Logger)
    • ProcBuilder.maxExitStatus(int)
  • New methods on StringUtils:

    • StringUtils.isEmpty(Object)
    • StringUtils.nullIfEmpty(String)
    • StringUtils.base64EncodeToString(String)
    • StringUtils.base64Encode(byte[])
    • StringUtils.base64DecodeToString(String)
    • StringUtils.base64Decode(String)
    • StringUtils.generateUUID(int)
    • StringUtils.trim(String)
    • StringUtils.parseISO8601Date(String)
    • StringUtils.replaceVars(String,Map)
    • StringUtils.pathStartsWith(String,String)
    • StringUtils.pathStartsWith(String,String[])
  • New StringVar.doResolve(String) method.

  • New StringVarResolver.DEFAULT field.

  • Eliminated dependency on javax.mail.internet.MimeUtility by implementing our own StringUtils.base64Encode(byte[]) method.

  • CalendarSwap and DateSwap classes now handle blank input better. Returns null instead of throwing an exception.

  • 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.

  • 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 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).

  • Parser methods now check for null input.

  • SerializerGroup and ParserGroup ignores serializers and parsers if they throw NoClassDefFoundErrors.

  • 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 MultiIterable class.

  • PojoIntrospector must now be instantiated with a ReaderParser. Simplifies the API on the class.

  • PojoRest must now be instantiated with a ReaderParser. Simplifies the API on the class.

  • MessageBundle and SafeResourceMultiBundle moved from server component.

  • Several bug fixes and performance improvements in StringVarResolver.

  • Various enhancements to TeeWriter and TeeOutputStream.

  • Renamed CharSet to AsciiSet.

  • SerializerGroup and ParserGroup now ignores NoClassDefFoundErrors so that resources that include Jena support can continue to operate even if the Jena libraries are not present.

  • New FileUtils.createTempFile(String) method.

  • New PojoQuery modified to handle bean getters that throw exceptions.

Client

  • Upgraded to use Apache HttpClient 4.5.

  • New classes:

    • AllowAllRedirects
    • HttpMethod
    • ResponsePattern
    • SimpleX509TrustManager
    • SSLOpts
  • Removed org.apache.juneau.rest.client.LaxRedirectStrategy. Use HTTP Client equivalent.

  • New methods on RestCall:

    • RestCall.addInterceptor(RestCallInterceptor)
    • RestCall.pipeTo(Writer)
    • RestCall.pipeTo(Writer,boolean)
    • RestCall.pipeTo(String,Writer,boolean)
    • RestCall.getWriter(String)
    • RestCall.pipeTo(OutputStream)
    • RestCall.pipeTo(OutputStream,boolean)
    • RestCall.pipeTo(String,OutputStream,boolean)
    • RestCall.getOutputStream(String)
    • RestCall.byLines()
    • RestCall.captureResponse()
    • RestCall.successPattern(String)
    • RestCall.failurePattern(String)
    • RestCall.addResponsePattern(ResponsePattern)
    • RestCall.run() - Renamed from execute().
    • RestCall.getCapturedResponse()
    • RestCall.getResponsePojoRest(Class)
    • RestCall.getResponsePojoRest()
    • RestCall.logTo(Level,Logger)
    • RestCall.setConfig(RequestConfig)
  • New lifecycle listener methods on RestCallInterceptor:

    • RestCallInterceptor.onInit(RestCall)
    • RestCallInterceptor.onClose(RestCall)
  • New methods on RestClient:

    • RestClient.setBasicAuth(String,int,String,String)
    • RestClient.logTo(Level,Logger)
    • RestClient.setRootUrl(String)
    • RestClient.enableSSL(SSLOpts)
    • RestClient.enableLaxSSL()
    • RestClient.doCall(HttpMethod,Object,Object)
    • RestClient.createHttpClientBuilder()
  • New passthrough methods on 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)
    • setUserAgent(String)
    • 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 RestException.

  • New methods in RestRequest:

    • RestRequest.getReaderResource(String) - Replaces getVarResource(String).
    • RestRequest.getReaderResource(String,boolean)
    • RestRequest.getReaderResource(String,boolean,String)
  • Changes in RestResponse:

    • Don't set Content-Encoding: identity when no encoding is used. Some clients don't interpret it correctly.
  • New methods in 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 JsoParser from 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 Streamable.
    • WritableHandler - Allows REST Java methods to return instances of 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 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:

    • ConfigResource - REST resource for viewing and editing microservice config file.
    • LogsResource - REST resource for viewing log files.
    • SampleRootResource - Sample REST resource that contains the config and logs resource as children.
    • 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

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