unic / neba Goto Github PK
View Code? Open in Web Editor NEWLightning fast and simple content mapping for Apache Sling and Adobe AEM
Home Page: https://neba.io
License: Apache License 2.0
Lightning fast and simple content mapping for Apache Sling and Adobe AEM
Home Page: https://neba.io
License: Apache License 2.0
Currently, Neba still supports AEM versions that are no longer supported by Adobe. This support can be faded out in a sense that newer releases no longer support these versions. However, bugfixes should still be backported for users on these deprecated versions.
Currently, a convenient NEBA package is available for installation via the AEM CRX package manager. It would be great if users of Sling would have a similar convenience package for installation. This could be achieved using a delivery bundle with Sling-Initial-Content loading.
The filter expression autocompletion currently only consideres the first character of an invalid input sequence to filter autocompletion options. This should be extended to all characters of the invalid input sequence
The taglib URI of NEBA 3.1.0 (http://www.neba.io/core/1.0) should be changed: The tag libraries are now published via the API because of #8. Also, there is no "www" in the neba top level domain.
Thus, the new taglib URI shall be
http://neba.io/1.0
The delivery artifact features a classifier (-aem). However, there are no other variants. More importantly, the vault-maven-plugin provided by adobe seems not to support classifiers when referencing a maven dependency to be deployed (only group and -artifactId are supported).
Coveralls currently reports a coverage of almost 90% (https://coveralls.io/r/unic/neba). It would be great to improve the coverage of some of the listed classes, even though nothing critical lacks coverage.
Bundles using Blueprint may start asynchronously. This has the advantage that bundle startup is less likely to result in locking conditions and allows a faster system startup and recovery from change. However, the asynchronous nature of OSGi and the potentially complex relationship graphs of bundles often make it hard to comprehend the root cause of an application context failure.
For instance, a bundle may fail two minutes after it has been started, if it waits for a service dependency until a configurable timeout has been reached,
Here, a Felix Web Console plugin may provide an overview of all bundles featuring blueprint, their status and - if possible - their issues, e.g. missing dependencies. It would be desirable to provide a direct way to filter related logfile information as well.
Currently, potentially mappable fields annotated with @Inject or @unmapped are excluded from the resource to model mapping. However, there are additional annotations that shall make an explicit @unmapped annotation superflous: @Autowired (Spring's custom annotation) and @resource (the java OOTB annotation).
Currently, the NEBA log viewer displays all available log files for selection - including rotated versions. This may result in bad usability if a lot of logfiles and rotated versions exist. Here, the log viewer should hide rotated versions by default and allow displaying them on demand.
One of NEBA's unique features is the performant collection of performance metadata for resource models. The metadata is currently visualized in the system console (resource model metadata). This allows real-time analysis of model performance on any system and is a valuable tool for both optimizing model implementations and assessing the effect of (unsuspected) content changes on site performance.
As of 3.4.0, the visualization employs a two-dimensional graph with logarithmic axes. This approach is problematic, as collisions of models with the same coordinates (performance charactierstics) are inevitable. Also, clustering tends to hapen which furhter downgrades the quality of visualization. This makes often makes it hard to spot resource models in unfavorable performance characteristics.
In addition, the user has no means to dynamically filter the displayed models.
A better approach is to always draw one diagram per model. The diagramm shall allow immeedia recognition of unfavorable performance patterns without forcing a user to read axis values or perform calculations. For instance, D3 star plot would be an effective solution for this purpose:
A careful selection of the dimensions would allow the user to immediatly spot "odd" patterns, such as models causing to many subsequent mappings or generally taking unusual amounts of mapping time.
In addition, users should be allowed to dynamically filter the models displayed using a suitable query expression. This query expression should be validated. If possible, the user should be provided with content assist while specifying the query. This could be achieved using a suitable parser, for instance PEG.js.
Hide the claim next to logo on mobile devices.
Main usage of Neba is within AEM. In AEM it is common to have properties containing links to other Pages. Those links can be resolved and a matching ResourceModel provided using the @reference annotation.
It is a common requirement to retrieve a model for a subnode of the linked Page instead of a Model for the Page itself. The fact that every Page in AEM has the resourceType cq:Page and only the jcr:content node might have a more specific ResourceType makes this even more common.
Therefore I would suggest the following
@reference(path = "jcr:content")
We should take care that this also works when combined with @children. Where it is even more useful.
Add an automatic scroll-down function on click of a link, in the navigation for the "User Guide" page, instead of just jumping directly to the desired location.
This gives the viewer a better idea for his/her position on the page.
The @ResourceParam tag could be enhanced with a default value, like so:
@ResourceParam(defaultValue = "/some/path")
This would do two things:
a) The param would implicitly be required=false
b) If no parameter is provided, the default value is used, resolved (and, if required, adapted)
Add a screen cast demonstrating core features and introducing the fundamental concepts.
By default, Spring's DispatcherServlet answers both OPTIONS and TRACE requests with a standard response and does not forward such requests to handlers (controllers), even if a controller was explicitly created for the corresponding HTTP method and path, see for instance [1].
This is an issue when implementing CORS services, where explicit control over the OPTIONS response headers is required.
Furthermore, it seems unlikely that there is a proper use case requiring the current default behavior, i.e. a static response enumerating all HTTP methods known to the DispatcherServlet, regardless whether an endpoint accepting such a method exists.
Thus, it would make sense to enable dispatching both OPTIONS and TRACE by default.
[1] http://stackoverflow.com/questions/23103832/spring-mvc-does-not-handle-requestmethod-options
Update documentation for @children and @reference in http://neba.io/userguide.html
It is easy to (carelessly...) write @ResourceModels with enourmous amounts transitive dependencies, for instance by using @children and @reference on models with even more @children and @reference. While such issues can be easily detected (e.g. using the /system/console/modelmetadata), they could be partially be prevented if relationships defined by @children / @reference and perhaps @path could be made lazy by default.
In a NEBA-based project we have a resource model post processor that searches for fields annotated with @x and injects a value in those. So basically it does the same as NEBA does, but for an AEM-based property.
Performance measurements and profiling showed that this post processor produces a big overhead, even for resource models that do not have any @x at all! The java reflection is just quite slow, to go through all the fields of the current or a super class.
So I did the following test:
30.10.2014 08:47:49.963 DEBUG [0:0:0:0:0:0:0:1 [1414655269869] GET x.html HTTP/1.1] ...TagReferencePostProcessor Time after getAllFields(): 1ms, time after reflections: 45ms
30.10.2014 08:47:53.578 DEBUG [0:0:0:0:0:0:0:1 [1414655269869] GET x.html HTTP/1.1] ...TagReferencePostProcessor Time after getAllFields(): 606ms, time after reflections: 113ms
But using reflections in an OSGi context is quite cumbersome, because we'd have to care about bundle changes and the resource model implementations are actually not exported, so we cannot even use Sling's global class loader.
On the other hand, NEBA already creates such an "index" of resource models. In NEBA this is called ResourceModelMetadata. So what about extending NEBA, such that the metadata can be extended dynamically such that
What do you think about this change?
Add a screencast featuring advanced features, e.g. explicitly referencing resource models by name, leveraging the inheritance hierarchy of both sling resources and the models, extending NEBA (custom annotations) etc.
Currently the labels in the model registry (see /system/console/modelregistry) are misleading and should be improved.
Filter: mapping to
is used to filter the models by only showning those which can map the resource behind the given path.
Suggestion
Only show models that can map the (resource belonging to the) path [/content...]
Filter: compatible to
is used to filter the models, by only showing does which could be cast to a certain (super-)class or interface. Basically only showing those for which "instanceof" would return true.
Suggestion
Only show models that can be cast to [class/interface]
@Reference(append = "/jcr:content")
private Resource pageContent; // this works!
@Reference(append = "jcr:content")
private Resource pageContent2; // this does not work!
Above example makes no sense in my oppinion. Actually a relative path in Sling normally starts without a slash /
, so "jcr:content" as append value makes more sense. But this does not work.
Depending on the JQuery product version, including the rotated versions of logfiles in the view of the log viewer console plugin may be distorted when the elements are set to display:inline.
NEBA guarantees that mappable collection-typed members of @ResourceModels are never null, even if they have a null default value. However, when a resource without properties (adaptation to ValueMap yields null) is adapted to a model, the FieldValueMappingCallback skips mapping of fields relying on the existence of properties. In this case, null collection-typed members that would otherwise be mappable are not provided with a default value.
On release-anouncement.png there is a black dot. Is this on purpose?
Before NEBA became OSS, a private sonar instance was used to gather generated converage results and code metrics. coveralls.io may be a viable solution to automatically generate at least the code coverage data.
Currently, the number of subsequent mappings and mapping durations are calculated as the sum of all mapping depths and durations occurring during a mapping. However, this may yield unrealisticly high numbers, for instance if subsequent mappings occur in a chain including multiple instances of the same mnodel mapped to different content paths. This should be improved to the extend that per subsequent mapping, every mapping count in the stack of ongoing mappings is simply incremented by one, and nested mapping times should be ignored for same-type nests.
In most cases we could make use of a PlaceholderVariableResolver, the variable depends on the request context, or on the resource model for whom the placeholder resolver is requested. So what about extending the PlaceholderVariableResolver API by
public String resolve(String variableName, Resource resource);
Or maybe rather defining an super type of PlaceholderVariableResolver to support both variants and to be compliant to older NEBA versions.
To automate the release process we should have some documentation how to do it and implement maybe needed Maven/Travis definitions.
With the number of NEBA annotations increasing and the future implementation of custom annotation-based field injectors (#16 ), it makes sense to support combining custom and NEBA annotations in an arbitrary fashion, like so:
@Reference
@Path("reference")
@Retention(RUNTIME)
public @interface MyAnnotation {}
NEBA should check for annotations in the entire transitive hull of annotations and meta-annotations and allow NEBA annotations to be used as meta-annotations.
Sometimes, for instance when a JSP was (manually) modified, the following error arises during JSP compilation:
File "tld:http://www.neba.io/core/1.0" not found
However, the tag library shows up in Sling's "JSP taglibs" status console: /system/console/status-jsptaglibs. This very likely related to Felix issues regarding fragment bundles.
As a workaround, the tag libraries could be moved to the API bundle and the dependencies to the core could be modeled as an OSGi service dependency, with the service interface provided by the API.
Sometimes, particularly in a multi-tenant setup, it would be helpful if the @ResourceModel annotation could be made to apply only to some subtree in the content hierarchy. This could eliminate some problems with "competing" resource models that apply to the same resource type.
I envisage specifying an arbitrary number of Strings or even Patterns either as a "paths" parameter in the @ResourceModel annotation or in an extra annotation that can be combined with @ResourceModel. For the Strings, the method to check whether the criterion succeeds must not simply be "startsWith" but rather the one used in PagePathUtils.isPagePathInSubtree(String, String) [from the CQ Foundation library which is not part of this repository]. For Patterns, the code to decide wether a path matches would probably have to be something like this:
Matcher matcher = pattern.matcher(resourcePath);
boolean criterionMet;
if (matcher.lookingAt()) {
if (matcher.end() <= 1) {
criterionMet = true; // the pattern matched "" or "/"
} else if (matcher.end() == resourcePath.length() || resourcePath.charAt(matcher.end()) == '/') {
criterionMet = true; // the full path was matched, or the path continues with "/"
} else {
criterionMet = false;
}
} else {
criterionMet = false;
}
It appears Spring 3.2.12 was provided by the apache servicemix team - we can thus upgrade to that version.
In Sling Engine 2.3.3, the interpretation of the OSGi service.ranking property for sling filters was adjusted (see: https://issues.apache.org/jira/browse/SLING-2920). Consequently, the ranking of the filters is inverted. Before, a low (e.g. negative) value meant a higher priority of the filter, i.e. an earlier position in the filter chain. Now, the opposite is the case.
To allow the same NEBA version to run on both AEM 5.3+ and AEM 6.1, the service.ranking of filters published by NEBA must thus be automatically adjusted to preserve the intended filter order.
Since we are preforming a new release, we should take the opportunity to update from 3.2.9 to the latest version. 3.2.11.
In AEM 6.1 or in Sling versions featuring Sling Models, the package javax.inject is provided by two bundles. Both are exporting the package using the OSGi default version 0.0.0. However, Spring and Neba (correctly) require package version >= 1.0.0.
javax.inject, version 0.0.0 exported by org.apache.sling.scripting.java (237)
<dependency>
<groupId>org.apache.sling</groupId>
<artifactId>org.apache.sling.scripting.java</artifactId>
<version>2.0.12</version>
<scope>provided</scope>
</dependency>
javax.inject, version 0.0.0 exported by org.apache.sling.models.api (381)
<dependency>
<groupId>org.apache.sling</groupId>
<artifactId>org.apache.sling.models.api</artifactId>
<version>1.1.0</version>
<scope>provided</scope>
</dependency>
Consequently, the javax.inject bundle 1.0.0 is still shipped with NEBA. However, project using NEBA may have dependenies - such as the google guava packages shipped with Sling - depending on the javax.inject default version. This leads to errors of the form
the bundle .... is exposed to the package javax.inject via two dependency chains ...
This is rather nasty, as it potentially depends on the bundle startup order, thus forming a race condition.
Suggested mitigation: Alter NEBA and the spring versions shipped therein to accept javax.inject versions [0, 2) and remove javax.inject from the shipped bundles. This has the additional advantage of adhering to the optional nature of Spring's javax.inject support.
@children and @reference support now "append" parameters, which allow appending a relative path to the resulting resource(s). Why not supporting the same for @ResourceParam.
Example:
@RequestMapping
public void handleRequest(@ResourceParam(append = "jcr:content") MyPageModel path) {}
This would simplify the following:
@RequestMapping
public void handleRequest(@ResourceParam Resource path) {
Resource jcrContentResource = path.getChild("jcr:content");
if (jcrContentResource != null) {
MyPageModel myPageModel = jcrContentResource.adaptTo(MyPageModel.class);
}
The logfile viewer allows selecting a logfile and a number of files to view. If the list of logfiles is very long, re-selecting the suitable logfile can be cumbersome. Also, it is not possible to share the selection at the moment. It would thus be a great improvement to be able to bookmark this selection along with the number of lines specified.
The Activity Feed just got quite a bit larger (vertically), because of one huge "activity"-message. Now the slider-arrows are not where they should be. I think this should be fixed in some way.
A solution could be, to set a character limit and instead of the rest of the "activity"-message, add "..." to the end.
Or the arrows should be placed further up.
There's an error that currently crops up every 30s in a live CQ instance, caused by a scheduled background task. As requested by Olaf, here is the stack trace.
18.02.2015 20:04:55.215 *ERROR* [pool-4-thread-1] org.springframework.scheduling.support.TaskUtils$LoggingErrorHandler Unexpected error occurred in scheduled task. java.lang.IllegalStateException: Invalid BundleContext.
at org.apache.felix.framework.BundleContextImpl.checkValidity(BundleContextImpl.java:365)
at org.apache.felix.framework.BundleContextImpl.getBundle(BundleContextImpl.java:137)
at io.neba.core.blueprint.ReferenceConsistencyChecker.getBundle(ReferenceConsistencyChecker.java:52)
at io.neba.core.blueprint.ReferenceConsistencyChecker.isValid(ReferenceConsistencyChecker.java:41)
at io.neba.core.resourcemodels.registration.ModelRegistry.removeInvalidReferences(ModelRegistry.java:383)
at sun.reflect.GeneratedMethodAccessor287.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:64)
at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:53)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:441)
at java.util.concurrent.FutureTask$Sync.innerRunAndReset(FutureTask.java:317)
at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:150)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$101(ScheduledThreadPoolExecutor.java:98)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.runPeriodic(ScheduledThreadPoolExecutor.java:181)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:205)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:619)
The log file viewer attempts to determine the configured log file directory using the apache sling logger configuration. However, the configuration is not persistent in pure Sling but falls back to the implementation's default (${sling.home}/logs). This leads to an NPE:
org.eclipse.jetty.servlet.ServletHandler /system/console/logviewer
java.lang.NullPointerException: null
at io.neba.core.logviewer.LogfileViewerConsolePlugin.getConfiguredLogfile(LogfileViewerConsolePlugin.java:337)
at io.neba.core.logviewer.LogfileViewerConsolePlugin.getLogfileDirectory(LogfileViewerConsolePlugin.java:328)
at io.neba.core.logviewer.LogfileViewerConsolePlugin.resolveLogFiles(LogfileViewerConsolePlugin.java:286)
It must thus be expected that the properties of the configuration is null.
Reproduce:
I've been trying to track down a strange bug since refactoring a couple of AEM projects I work on, and have traced it down to a behaviour in io.neba.core.resourcemodels.mapping.AnnotatedFieldMappers
.
My situation is:
@MyAnnotation
and 3 AnnotatedFieldMapper
's to handle various usages of that annotationAnnotatedFieldMapper
for another use-case of the annotation, specific to that project.The bug I have is that if I install "project2" after I install "shared", the AnnotatedFieldMapper
's in "shared" stop working, and visa-versa if I install "shared" after "project2".
This happens because AnnotatedFieldMappers#remove
calls:
this.fieldMappers.remove(mapper.getAnnotationType());
Which removes all mappers matching the annotation type (e.g. @MyAnnotation
) and not just the specific mapper being unbound.
I can (and I think will have to in the short term at least) refactor my code to work around this behaviour, but it feels like it may be an unintended behaviour?
I'm happy to listen to any good arguments that I'm misusing AnnotationFieldMapper
's if that is indeed the case, otherwise this seems like it could be a fairly straightforward fix by doing a deep comparison of the mapper being unbound against the cache of registered mappers.
For reasons of legacy support, NEBA is still based on JDK 6. This can change along with #50 , i.e. once the majority of deployments have migrated to the current AEM versions and have upgraded to more recent JVM versions.
Transitioning to this version will make sense if the benefits outweigh the resulting backwards compatibility issues. Also, just switching to the new version yields no benefit in itself. A Benefit would only result when refactoring the NEBA core code to leverage the new functional programming elements - which effectively ends backwards compatibility.
I wanted to create a field mapper for fields of type boolean. The problam is that I cannot use the boolean (primitive) type. NEBA does then not call the AnnotationFieldMapper, and I cannot parameterize the field mapper with , as this does not work for primitive types. So I think when a field mapper provides the field type Boolean (or Integer, Long, ...), it should also be called for primitive types (boolean, int, long, ...). Just like the other NEBA annotations are handled.
This is proposed by @DaniRey.
The requirements analysis is in progress.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.