Giter Site home page Giter Site logo

kontent-ai / java-packages Goto Github PK

View Code? Open in Web Editor NEW
14.0 20.0 28.0 44.38 MB

Delivery Java SDK for Kontent.ai including examples for Spring, Gradle, Kotlin and Java Android app

Home Page: https://kontent.ai/learn/tutorials/develop-apps/overview/?tech=java

License: MIT License

Java 83.26% HTML 1.84% CSS 14.32% Kotlin 0.58%
headless-cms java content-delivery hacktoberfest kotlin kotlin-android delivery-sdk kontent-ai kontent-ai-sample kontent-ai-tool

java-packages's Introduction

Kontent.ai Java Packages

Stack Overflow Discord

Monorepo with Java Kontent.ai packages.

Packages

Package Summary Version
Kontent.ai Delivery Java SDK The Kontent.ai Delivery Java SDK is a client library used for retrieving content from Kontent.ai Maven Central
Kontent.ai Generators This tool generates strongly-typed models based on Content Types in a Kontent.ai project. Maven Central
Kontent.ai Sample Spring Boot app Showcase of the Spring boot application displaying data from Kontent.ai. source
Kontent.ai Sample Gradle Console app Simple Java console application showcasing how to load data from Kontent.ai. source
Kontent.ai Sample Android app (Java) Showcase of the Android application written in Java using RxJava for data fetching from Kontent.ai. source
Kontent.ai Sample Android app (Kotlin) Showcase of the Android application written in Kotlin using Kotlin Coroutines for data fetching from Kontent.ai. source
Kontent.ai Java packages docs Documentation for Kontent.ai Java packages source

Development

If you wish to find out more about the project specification. Check out the Project information.

Prerequisites

Required:

  • Java 8 SDK (Oracle & OpenJDK both tested and supported)
  • Android SDK for the sample application (minimal version 28) - command line tools would be sufficient

Build and Test

  • Ensure your JAVA_HOME environment is set.

  • Clone this repository

    git clone https://github.com/kontent-ai/java-packages
  • Enter the cloned repository

    cd kontent-java-packages
  • Copy local.properties.template file in this directory to local.properties (which will be ignored by Git)

  • Set the sdk.dir variable Android SDK location

  • Build the project via the provided Gradle wrapper.

    To grant execution rights for gradlew binary, you could use chmod a+x ./gradlew which allows execution to everybody.

    ./gradlew clean build

    The command will build whole solution and run all tests in this monorepo.

Dependency verification

Due to security reasons the verifications of dependencies checksums is enabled in this repository. When you update the dependency on some libray you might need to update gradle/verification-metadata.xml.

To let gradle obtain checksum and rewrite them to gradle/verification-metadata.xml` you can use command:

gradle --write-verification-metadata sha256 help 

However, we recommend to use the command with switch option --dry-run to create a copy of the file and check the results before:

gradle --write-verification-metadata sha256 help --dry-run

💡 Next steps

The ideal next step is to test out the Kontent.ai Sample Spring Boot app or load the project in In IDE (IntelliJ IDEA recommended) and run/debug tests in Kontent.ai Delivery Java SDK.

Publishing

To publish a new version, it is required to have write permissions for this repository (to be able to create releases) and access to the Nexus Repository Manager.

  1. Verify that everything in the branch is ready to be published and the build and tests are passing.

  2. Create new GitHub release - the tag name of the release will be used as a version

    • If you define tag name with "-SNAPSHOT" suffix i.e. 5.0.0-SNAPSHOT artifact will be published to the https://s01.oss.sonatype.org/content/repositories/snapshots/, so that you could use it when you want to try out the beta version.

    • The creation of a release triggers the Publish Github workflow and creates and publishes the artifacts to "Staging" repositories on Nexus repository manager.

  3. Log in to the Nexus Repository Manager.

  4. Select "Staging repositories", verify the repository content (sometimes it takes a couple of minutes until the repository is visible in the Nexus Repository Manager UI).

  5. Close the Staging repository

  6. Release the Closed repository

  7. Increase the patch version and append -SNAPSHOT in the bottom of /build.gradle file (i.e. 4.4.1-SNAPSHOT).

💡 This is just an abbreviated description of the publishing process. If you want to see the detailed publishing description, checkout the wiki page "Publishing process".

java-packages's People

Contributors

aweigold avatar coleanderson-tc avatar colliercz avatar connyduck avatar cunhazera avatar garugaru avatar ivankiral avatar jancerman avatar jerrmartin avatar kentico-timothyf avatar kontent-ai-bot avatar mberry1989 avatar petrsvihlik avatar rlindooren avatar shawnrc avatar simply007 avatar tiagorlampert avatar zenbhang avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

java-packages's Issues

Add logging

Use SLF4J fascade to not burden users with any particular logging framework.

Add support for image optimization

Kentico Cloud now supports image optimization. It gives developers the option of transforming images using URL parameters. The goal of this task is to implement a helper class that will make generation of image URLs easy for the developers.

The reference code can be observed in the .NET SDK.

The full specification follows:

Example

Scale
image.jpg?mode=scale&width=300
image.jpg?mode=scale&height=150
image.jpg?mode=fit&height=150&width=300

DPR
image.jpg?mode=scale&width=300&dpr=2.0

Specification

If a developer provides a parameter with invalid value or omits a parameter that is required for desired optimization, the Asset API will either ignore this parameter, or return the original asset without any optimizations.

Also, to keep our sanity, we will transform each image optimization parameter independently from others. Yes, this approach might sometimes produce surprising results. However, both Fastly and imgix are designed to handle a set of parameters that do not make sense and we are not making the situation worse.

Regarding requests to the Asset API, the idea is to go through all parameters, transform the supported ones and get rid of everything else.

To get a grasp of the image optimization You can experiment with two identical images:

rect=x,y,w,h (incompatible with crop)

- -
x is not float Nothing
x < 0.0 Nothing
y is not float Nothing
y < 0.0 Nothing
w is not float Nothing
w <= 0.0 Nothing
h is not float Nothing
h <= 0.0 Nothing
h <= 0.0 Nothing
otherwise crop={w},{h},x{x},y{y}

If the rect parameter is malformed, just ignore it.

fit=crop&crop=focalpoint&fp-x=x&fp-y=y&fp-z=z (incompatible with rect)

- -
x is not float set x as 0.5
y is not float set y as 0.5
z is not float Nothing
z <= 1.0 Nothing
1 / z < 1.0 Nothing
otherwise crop={1 / z},{1 / z},offset-x{(x * z - 0.5) / (z - 1)},offset-y{(y * z - 0.5) / (z - 1) * 100}

Both offset-x and offset-y must be clamped into range from 0 to 100.

imgix supports crop by both rectangle and focal point. Unfortunately, it is not so easy to calculate Fastly parameters. Therefore, let's declare the rect parameter more important. So, if both crop by rectangle and focal point are specified, choose the first.

fm=x

- -
x = gif format=gif
x = png format=png
x = png8 format=png8
x = jpg format=jpg
x = pjpg format=pjpg
x = webp format=webp
otherwise Nothing

fm=webp&lossless=x

- -
x = 1 format=webpll
x = true format=webpll
x = 0 format=webply
x = false format=webply
otherwise format=webp

q=x

- -
x is not float Nothing
otherwise quality={x}\

auto=x

- -
x = format auto=webp
otherwise Nothing

Local variables and related functions will be required to transform parameters.

Invalid ISO 8601 last_modified in ContentTypes response example

The example JSON on the Kentico API site shows a last_modified date as "1. 1. 0001 0:00:00", which fails ISO 8601 DateTime parsing.

Try to reproduce this with the actual API and add support if it's valid. Otherwise reach out to Kentico to update docs.

HttpClient connection management

The default HttpClient probably only has 2 connections per host in it's pool. Create more adequate defaults as well as a pattern for customization.

See this link.

Missing documentation on Rich Text Rendering

Motivation

Rendering of rich text elements is a significantly more complex process than that of the ordinary plan text elements. Also, it can be approached in two distinct ways--by writing imperative code to render the rich text content, or by using a templating engine of some sort. One might not grasp the pros and cons of those two approaches at first.

Guidelines

Document how to render contents of rich text elements.

Similarly to:

Javadoc

Pull in documentation from REST API into JavaDoc.

Provide .castTo(String contentType) and .castToDefault() on ContentItem

A ContentItem allows casting to Class which looks up a registered type from the StronglyTypedContentItemConverter. When working within a view template in various rendering technologies, creating a Class reference may be overly verbose, when could do this via String due to the contentTypeToClassMapping within it.

Ideally, a consumer could do something like this from within a template:

${model.relatedArticles[0].castToDefault().title}
${model.relatedArticles[0].castTo("article").title}

See the T Convert(ContentItem, Map<String, ContentItem> modularContent, Class tClass) method within StronglyTypedContentItemConverter to see how we do this when Object.class is passed in for an example of how this can be done.

Create mapping plan construct for strongly typed models

Currently strongly typed model conversion relies on extensive reflection that may potentially be a bottleneck when placed in a high performance system. Introduction of a plan construct would allow caching of this after the first resolution of a mapping.

Shadow Joda or another library to implement JSR-310 time dependencies

Currently the Java SDK uses Java 8 ZonedDateTime objects. This depends on Duration which doesn't exist in the Android API until version 26 (which less than 1% of devices are on).

Explore adding Joda or another library into the shadow jar created for Android to provide the JSR-310 java.time API and identify the lowest Android API compatible with it. If the API compatibility is still > 19, create a new issue identifying the new barrier.

Strongly typed nested modular items

Hey,

I was going through the code and it seems that modular items nested within a strongly typed class can be only of generic ContentItem item. This can be seen for example with the 'relatedArticles' property in this sample class.

It would be nice so that you could define strongly typed classes within a class and let SDK handle conversion for you. Something like this is implemented in our TypeScript SDK (example).

Add support for recursively resolving inline modular content

Currently both the InlineContentItemsResolvers and TemplateEngineInlineContentItemsResolvers run a single pass through rich text. Under certain scenarios, a resolver may provide in it's resolution an object element that would further need resolution.

An example would be, if the content type being resolved itself has a rich text element with modular content. The default Thymeleaf template support is not able to resolve this adequately in it's response.

Add support for secured access to published (production) content

In coming weeks, the Delivery API will start supporting authenticated access.

In the first version of this feature, content will be secured using an API key. The developer will be able to turn the authenticated access on and off for the whole project. There will be one authentication key for the project, not multiple ones (for various user roles, for example).

Implement support for submitting the key in the form of the "Authorization" request header. The key should be sent via the Bearer scheme (with a "Bearer " prefix).

We'll provide more information once they become available.

Add ViewResolver/Rendering Interface

It may not be immediately clear to consumers of the SDK how to link their InlineContentItemsResolver to their View Rendering library of choice. Provide an interface that can abstract the implementation to allow choice for consumers.

Furthermore add a Thymeleaf implementation that will check the classpath first for the dependency, and if it exists run the engine, but do not make it a required dependency to use the SDK.

This would work similar to how Spring Boot autoconfigures ViewResolvers based on what is on the classpath.

DeliveryClient Hanging, Starving Request Thread Pool

Hi @aweigold,

There is an intermittent issue with the DeliveryClient which causing a request thread to wait and never return. This seems to happen periodically and causes all request threads to eventually block. When this happens, the server becomes unresponsive (no threads available to service incoming requests).

No clear reproduction path has been identified yet. This seems to occur for us every week or so.

Specifications

  • Version: com.kenticocloud:delivery-sdk-java:1.0.6
  • Platform: Embedded Tomcat w/ Spring Boot

Stacktrace

Below is a thread stacktrace from a waiting thread:

sun.misc.Unsafe.park(Unsafe.java:-2) native
java.util.concurrent.locks.LockSupport.park(LockSupport.java:175) 
java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039) 
org.apache.http.pool.AbstractConnPool.getPoolEntryBlocking(AbstractConnPool.java:380) 
org.apache.http.pool.AbstractConnPool.access$200(AbstractConnPool.java:69) 
org.apache.http.pool.AbstractConnPool$2.get(AbstractConnPool.java:246) 
org.apache.http.pool.AbstractConnPool$2.get(AbstractConnPool.java:193) 
org.apache.http.impl.conn.PoolingHttpClientConnectionManager.leaseConnection(PoolingHttpClientConnectionManager.java:303) 
org.apache.http.impl.conn.PoolingHttpClientConnectionManager$1.get(PoolingHttpClientConnectionManager.java:279) 
org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:191) 
org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:185) 
org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:89) 
org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:111) 
org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:185) 
org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:83) 
org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:108) 
org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:56) 
com.kenticocloud.delivery.DeliveryClient.lambda$executeRequest$1(DeliveryClient.java:420) 
com.kenticocloud.delivery.DeliveryClient$$Lambda$44/1953333936.execute(:-1) 
com.trustedchoice.kentico.DeliveryClientConfiguration.lambda$trustedChoiceKenticoCache$0(DeliveryClientConfiguration.java:66) 
com.trustedchoice.kentico.DeliveryClientConfiguration$$Lambda$32/826865256.resolveRequest(:-1) 
com.kenticocloud.delivery.DeliveryClient.executeRequest(DeliveryClient.java:419) 
com.kenticocloud.delivery.DeliveryClient.executeRequest(DeliveryClient.java:412) 
com.kenticocloud.delivery.DeliveryClient.getItems(DeliveryClient.java:188) 
com.kenticocloud.delivery.DeliveryClient.getItems(DeliveryClient.java:203) 
com.trustedchoice.sitemap.SiteMapItemRetriever.getSitemapLocation(SiteMapItemRetriever.java:422) 
com.trustedchoice.sitemap.SiteMapItemRetriever.getForRequest(SiteMapItemRetriever.java:105) 
com.trustedchoice.kentico.KenticoContextHolder.loadContextFromRequest(KenticoContextHolder.java:126) 
com.trustedchoice.kentico.KenticoFilter.doFilterInternal(KenticoFilter.java:46) 
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) 
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) 
com.trustedchoice.redirect.RedirectFilter.doFilterInternal(RedirectFilter.java:102) 
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) 
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) 
com.trustedchoice.log.PerformanceLoggingFilter.doFilterInternal(PerformanceLoggingFilter.java:66) 
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) 
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) 
com.trustedchoice.requesthost.RequestHostFilter.doFilterInternal(RequestHostFilter.java:62) 
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) 
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) 
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:317) 
org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:114) 
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137) 
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111) 
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:170) 
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63) 
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilterInternal(BasicAuthenticationFilter.java:158) 
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116) 
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
org.springframework.security.web.csrf.CsrfFilter.doFilterInternal(CsrfFilter.java:100) 
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:64) 
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105) 
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56) 
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) 
org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:214) 
org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:177) 
org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:347) 
org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:263) 
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) 
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) 
org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) 
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) 
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) 
org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:108) 
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) 
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) 
org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81) 
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) 
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) 
org.springframework.session.web.http.SessionRepositoryFilter.doFilterInternal(SessionRepositoryFilter.java:167) 
org.springframework.session.web.http.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:80) 
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) 
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) 
org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197) 
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) 
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) 
org.springframework.boot.actuate.autoconfigure.MetricsFilter.doFilterInternal(MetricsFilter.java:106) 
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) 
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) 
org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199) 
org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) 
org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:504) 
org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) 
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81) 
org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) 
org.apache.catalina.valves.RemoteIpValve.invoke(RemoteIpValve.java:677) 
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342) 
org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:803) 
org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) 
org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:790) 
org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1459) 
org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) 
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) 
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) 
org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) 
java.lang.Thread.run(Thread.java:748) 

Page.nextPage() fails with NPE

The DeliveryClient does not set the stronglyTypedContentItemConverter on the ContentItemsListingResponse on calls to getPageOfItems and getNextPage causing the constructor of the new Page to throw an NPE when it invokes to response.castTo(tClass).

Strongly Typed Content Item Converter does not support mapping name from an Option

Motivation

When rendering a multiple choice elements in a strongly typed model, one must access the List<Option> value property of the MultipleChoiceElement class, which might be tedious. There should be a more straightforward path to the names of options.

One potential way to handle this would be like the following:

@ContentItemMapping("product")
public class Product {
  @ElementMapping("product_categories")
  List<Option> productCategories;

  //New feature
  @ElementMappingOption(elementCodeName = "product_categories", optionCodeName = "footwear")
  Boolean isFootwear;
}

Original description

If an Option is mapped to a field, the name from the option should be used.

Using inline content items that contain dollar signs will cause java.util.regex.Matcher to throw java.lang.IndexOutOfBoundsException: No group #

The matcher.appendReplacement method on line 202 of com.kenticocloud.delivery.RichTextElementConverter that places inline content item html inside parent content item html will interpret dollar signs (and their trailing numbers) as capturing groups in the matcher's pattern. If the interpreted capturing group does not exist in the Matcher object, java.lang.IndexOutOfBoundsException: No group # is thrown. The dollar signs in replacement strings should be escaped to avoid this behavior. See https://docs.oracle.com/javase/7/docs/api/java/util/regex/Matcher.html#appendReplacement(java.lang.StringBuffer,%20java.lang.String)

Add 'Kentico' dialect for Thymeleaf engine

Motivation

Say your application needs to show an alert text box in blue or red background depending on the user’s role (admin or non-admin). You can compute this with conditional expressions on your template, but too many conditions could render your code a little bit hard to read …

Solution: create a new Thymeleaf attribute called alertclass and an attribute processor for it (Java code that will compute the right CSS class), and package it into your own MyOwnDialect Thymeleaf dialect. Add this dialect to your template engine with the th prefix (same as the SpringStandard dialect) and you’ll now be able to use th:alertclass="${user.role}".

(Taken from the docu.)

Design guidelines

This Thymeleaf dialect should provide various expressions and content resolvers to simplify usage of KenticoCloud objects from within Thymeleaf. This dialect can be registered by an application's Thymeleaf rendering engine, as well as should be registered in the inline linked items rendering engine provided with the SDK.

Reference

FastClasspathScanner is outdated -- consider porting to ClassGraph

Your project, Kentico/delivery-sdk-java, depends on the outdated library FastClasspathScanner in the following source files:

FastClasspathScanner has been significantly reworked since the version your code depends upon:

  • a significant number of bugs have been fixed
  • some nontrivial API changes have been made to simplify and unify the API
  • FastClasspathScanner has been renamed to ClassGraph: https://github.com/classgraph/classgraph

ClassGraph is a significantly more robust library than FastClasspathScanner, and is more future-proof. All future development work will be focused on ClassGraph, and FastClasspathScanner will see no future development.

Please consider porting your code over to the new ClassGraph API, particularly if your project is in production or has downstream dependencies:

Feel free to close this bug report if this code is no longer in use. (You were sent this bug report because your project depends upon FastClasspathScanner, and has been starred by 4 users. Apologies if this bug report is not helpful.)

SDK tracking header

Motivation:
We'd like to start sending a header for identifying SDKs + their versions with each request from all SDKs. The header would be then tracked by App Insights and should provide us with information valuable for multiple departments in Kentico. App Insights already gather information about the user agent, but that is not always usable or present (there are some screenshots below).

In the future, the tracking should help us:

  • identify trends and make decisions regarding future SDK development like:
    • avoid breaking changes (in APIs that are highly used)
    • identify new SDK opportunities (e.g. we may see that users are making plain calls from a certain platform while not using any SDK)
    • new functionality opportunities (similarly to SDK opportunities, we may discovery that certain part of the API is not covered by SDK)
  • discover misbehavior of certain SDK versions
    • see whether users are using the latest version or if they are stuck
  • send out targeted messages about an SDK version being deprecated
  • save round-trips to customer asking about platform they're using and the SDK version (Support)

Specification:
Send the following header with each request to the Kentico Cloud Delivery API.

  • Header name: X-KC-SDKID
  • Header format: ;;
    • PackageRepositoryHost - HOST part of the package repository URI. The value can be hardcoded.
    • SDKPackageID - ID specific for the package repository. In other words, the identifier that's used when specifying the package as a dependency of the resulting application (typically in a json or xml file - package.json, *.csproj, composer.json, etc.) Sometimes the ID can consist of a vendor name and package name. The value can be hardcoded.
    • SDKVersion - version of the package (typically in a semantic version format). This information needs to be either retrieved programmatically during the runtime or hardcoded and manually updated with every release.

Examples:

X-KC-SDKID: nuget.org;KenticoCloud.Delivery;4.12.0
X-KC-SDKID: packagist.org;kentico-cloud/delivery-sdk-php;0.9.1
X-KC-SDKID: maven.org;com.kenticocloud:delivery-sdk-java;1.0.5
X-KC-SDKID: npmjs.com;kentico-cloud-delivery-typescript-sdk;2.2.2

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.