twcable / grabbit Goto Github PK
View Code? Open in Web Editor NEWGrabbit - Fast Content Sync tool for AEM/CQ
License: Apache License 2.0
Grabbit - Fast Content Sync tool for AEM/CQ
License: Apache License 2.0
I have newly started working on AEM 6.01 SP2 and found grabbit to copy data from different server to localhost but could not make it work in my localhost. Below is the error trace. Please help me to identify what went wrong and what changes are required to make it work. Appreciate your help!
< HTTP/1.1 100 ContinuePUT /grabbit/job HTTP/1.1
Authorization: Basic YWRtaW46YWRtaW4=
User-Agent: curl/7.30.0
Host: localhost:4502
Accept: /
Content-Type: application/json
Content-Length: 1154
Expect: 100-continue
Paths with large amounts of content (often seen in /content/dam
) tend run out of memory.
The problem has been observed to be alleviated by increasing the heap size (from 2GB to 4GB)
NOTE: Try out server using the raw methods on protobuf's CodedOutputStream ... rather than the node API.
Reference : MessageLite : https://developers.google.com/protocol-buffers/docs/reference/java/com/google/protobuf/MessageLite
CodedOutputStream : https://developers.google.com/protocol-buffers/docs/reference/java/com/google/protobuf/CodedOutputStream
This ticket is to track implementing Spring Batch's Retry feature - http://docs.spring.io/spring-batch/trunk/reference/html/retry.html
Also, the "catchable" exception here is javax.jcr.InvalidItemStateException
We get the following error on copy every single time. The error was located in the batch-client.log file. The job stops and does not continue.
16.06.2015 19:04:34.723 [clientJobLauncherTaskExecutor-9] com.twc.grabbit.client.batch.steps.jcrnodes.JcrNodesWriter ERROR Exception writing JCR Nodes to current JCR Session : session-admin-6306766. javax.jcr.RepositoryException: Invalid last path element for adding node event[2] relative to node /content/(OBFUSCATED_PATH)/jcr:content
at org.apache.jackrabbit.core.session.AddNodeOperation.perform(AddNodeOperation.java:72)
at org.apache.jackrabbit.core.session.AddNodeOperation.perform(AddNodeOperation.java:37)
at org.apache.jackrabbit.core.session.SessionState.perform(SessionState.java:216)
at org.apache.jackrabbit.core.ItemImpl.perform(ItemImpl.java:91)
at org.apache.jackrabbit.core.NodeImpl.addNodeWithUuid(NodeImpl.java:1814)
at org.apache.jackrabbit.core.NodeImpl.addNode(NodeImpl.java:1774)
at org.apache.jackrabbit.commons.JcrUtils.getOrCreateByPath(JcrUtils.java:1136)
at org.apache.jackrabbit.commons.JcrUtils.getOrCreateByPath(JcrUtils.java:1016)
at org.apache.jackrabbit.commons.JcrUtils.getOrCreateByPath(JcrUtils.java:909)
at com.twc.grabbit.client.batch.steps.jcrnodes.JcrNodesWriter.writeToJcr(JcrNodesWriter.groovy:95)
at com.twc.grabbit.client.batch.steps.jcrnodes.JcrNodesWriter.write(JcrNodesWriter.groovy:57)
at org.springframework.batch.core.step.item.SimpleChunkProcessor.writeItems(SimpleChunkProcessor.java:175)
at org.springframework.batch.core.step.item.SimpleChunkProcessor.doWrite(SimpleChunkProcessor.java:151)
at org.springframework.batch.core.step.item.SimpleChunkProcessor.write(SimpleChunkProcessor.java:274)
at org.springframework.batch.core.step.item.SimpleChunkProcessor.process(SimpleChunkProcessor.java:199)
at org.springframework.batch.core.step.item.ChunkOrientedTasklet.execute(ChunkOrientedTasklet.java:75)
at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:395)
at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:130)
at org.springframework.batch.core.step.tasklet.TaskletStep$2.doInChunkContext(TaskletStep.java:267)
at org.springframework.batch.core.scope.context.StepContextRepeatCallback.doInIteration(StepContextRepeatCallback.java:77)
at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:368)
at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:215)
at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:144)
at org.springframework.batch.core.step.tasklet.TaskletStep.doExecute(TaskletStep.java:253)
at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:195)
at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:141)
at org.springframework.batch.core.job.flow.JobFlowExecutor.executeStep(JobFlowExecutor.java:64)
at org.springframework.batch.core.job.flow.support.state.StepState.handle(StepState.java:60)
at org.springframework.batch.core.job.flow.support.SimpleFlow.resume(SimpleFlow.java:151)
at org.springframework.batch.core.job.flow.support.SimpleFlow.start(SimpleFlow.java:130)
at org.springframework.batch.core.job.flow.FlowJob.doExecute(FlowJob.java:135)
at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:301)
at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:134)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:744)
Grabbit currently manages workflow launcher configs for paths that include DAM content. It turns off the asked workflow launcher configs before writing DAM content to the client and turns them back on at the end.
Adobe (http://docs.adobe.com/docs/en/cq/current/dam/managing_digitalassets.html#PackagingAssets) and other resources online resources (http://aemtips.blogspot.com/2013/05/how-to-migrate-huge-number-of-assets.html) recommend to ONLY turn off a couple of WorkflowLauncher bundles before writing DAM content.
Investigate if this is all we need and fix the Grabbit job correspondingly.
Running against /home
complains about mandatory property "rep:principalName"
being missing.
Users/groups are being stored in Authorizable nodes. Even though both sides are running as "admin", theSession().save()
in JcrNodesWriter
gives errors like: javax.jcr.nodetype.ConstraintViolationException: OakConstraint0021: /home/groups/b[[rep:Group]]: Mandatory property rep:principalName not found in a new node
The issue is that this is a protected property in CRX 2.4 / JCR so the JCR API can not be used. (c.f. Interaction With Protected Properties, Repository Model - Protected.)
Before writing we need to check if the node type to be written is a user/group and use Jackrabbit's UserManager API to create the node.
(see com.twcable.grabbit.client.batch.steps.jcrnodes.JcrNodesWriter
in Grabbit.)
Add a section to the readme that describes version requirements between client and server. In other words, given a server version, which clients are compatible.
If you go to /grabbit/
and all "legal" subpaths you should always get a response. If it's not specific data, it should at least give HTML/JSON on legal calls from there. (i.e., self-documenting)
This flag will be per path in a grabbit configuration. If this flag is enabled for a particular path, then that path will be deleted from the client before writing
.
The configuration can look something like this :
{
"path" : "/content/someContent",
"workflowConfigIds" :
[
"/etc/workflow/launcher/config/update_asset_mod",
"/etc/workflow/launcher/config/update_asset_create",
"/etc/workflow/launcher/config/dam_xmp_nested_writeback",
"/etc/workflow/launcher/config/dam_xmp_writeback"
],
"deleteBeforeWrite" : true
}
Currently, the Grabbit build setup has more of a multi-module project flavor to it. For example, there is a top level grabbit
project and then there is a subproject again with the name grabbit
.
There is a lot of potential for re-work of the setup to make it much simpler; both to understand and maintain.
I am trying to install grabbit on my development environment, but it fails when trying to run the ':grabbit:checkBundleStatus' task.
Running gradlew with the --debug flag, I can see that the issue is related to the installer not being able to query http://localhost:4502/system/console/bundles.json for the bundle list.
Log reads as follows:
10:06:33.165 [DEBUG] [org.apache.http.impl.conn.DefaultClientConnection] Sending request: GET /system/console/bundles.json HTTP/1.1
10:06:33.165 [DEBUG] [org.apache.http.headers] >> GET /system/console/bundles.json HTTP/1.1
10:06:33.165 [DEBUG] [org.apache.http.headers] >> Authorization: Basic YWRtaW46YWRtaW4
10:06:33.165 [DEBUG] [org.apache.http.headers] >> Accept: application/json
10:06:33.165 [DEBUG] [org.apache.http.headers] >> Host: localhost:4502
10:06:33.165 [DEBUG] [org.apache.http.headers] >> Connection: Keep-Alive
10:06:33.165 [DEBUG] [org.apache.http.headers] >> User-Agent: Apache-HttpClient/4.1.2 (java 1.5)
10:06:33.167 [DEBUG] [org.apache.http.impl.conn.DefaultClientConnection] Receiving response: HTTP/1.1 401 Unauthorized
10:06:33.167 [DEBUG] [org.apache.http.headers] << HTTP/1.1 401 Unauthorized
10:06:33.167 [DEBUG] [org.apache.http.headers] << Connection: Keep-Alive
10:06:33.167 [DEBUG] [org.apache.http.headers] << Server: Day-Servlet-Engine/4.1.52
10:06:33.167 [DEBUG] [org.apache.http.headers] << Content-Length: 0
10:06:33.167 [DEBUG] [org.apache.http.headers] << Date: Thu, 30 Apr 2015 15:06:33 GMT
10:06:33.167 [DEBUG] [org.apache.http.headers] << WWW-Authenticate: Basic realm="OSGi Management Console"
10:06:33.167 [DEBUG] [org.apache.http.client.protocol.ResponseAuthCache] Caching 'basic' auth scheme for http://localhost:4502
10:06:33.167 [DEBUG] [org.apache.http.impl.client.DefaultHttpClient] Connection can be kept alive indefinitely
10:06:33.167 [DEBUG] [org.apache.http.impl.client.DefaultHttpClient] Target requested authentication
10:06:33.167 [DEBUG] [org.apache.http.impl.client.DefaultHttpClient] Authorization challenge processed
10:06:33.167 [DEBUG] [org.apache.http.impl.client.DefaultHttpClient] Authentication scope: BASIC 'OSGi Management Console'@localhost:4502
10:06:33.167 [DEBUG] [org.apache.http.impl.client.DefaultHttpClient] Authentication failed
It seems that the installer is trying to get the bundle list but it can't because it needs authentication.
I grepped around in the source code but didn't find any reference to the task, to be able to change it and add the proper credentials.
I wonder if this is a real bug/enhancement, or if it is just an issue I am having. In any case, I hope you can help me out.
I can hand over additional environment info if need be.
Ricardo
We should be able to use batch:split/batch:flow to parallelize presync steps such as deleteBeforeWrite, and namespaceSync. Parallelizing clientWorkflowOff may not be safe, as the client could have workflows around deletion of nodes; and we may run into a situation where nodes are deleted, and workflows are started, before the workflows are turned off.
JcrJobRepository
currently does not delete any job statistics from JCR. We should delete any JcrJobRepository data older than X (may be keep only the last successful data for every path)
We are consistently getting this error on our production servers. I have tried restarting the Adobe instances, but the error is the same. We are not getting the error in lower environments, only production. I'm working to see if there are any differences between the environments, but so far I haven't found any. Here is the error.
20.07.2015 12:58:26.843 -0400 ERROR [SpringOsgiExtenderThread-6] org.springframework.osgi.extender.internal.activator.ContextLoaderListener Application context refresh failed (OsgiBundleXmlApplicationContext(bundle=com.twcable.grabbit, config=osgibundle:/META-INF/spring/*.xml)) org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'clientJobLauncher' defined in URL [bundle://629.0:0/META-INF/spring/client-batch-job-context.xml]: Cannot resolve reference to bean 'clientJobRepository' while setting bean property 'jobRepository'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'clientJobRepository' defined in URL [bundle://629.0:0/META-INF/spring/client-batch-job-context.xml]: Instantiation of bean failed; nested exception is java.lang.VerifyError: Stack map does not match the one at exception handler 54
Exception Details:
Location:
com/twcable/grabbit/spring/batch/repository/JcrJobRepositoryFactoryBean.getJobExecutionDao()Lorg/springframework/batch/core/repository/dao/JobExecutionDao; @54: dup
Reason:
Type top (current frame, locals[0]) is not assignable to 'com/twcable/grabbit/spring/batch/repository/JcrJobRepositoryFactoryBean' (stack map, locals[0])
Current Frame:
bci: @52
flags: { }
locals: { }
stack: { 'java/lang/Throwable' }
Stackmap Frame:
bci: @54
flags: { }
locals: { 'com/twcable/grabbit/spring/batch/repository/JcrJobRepositoryFactoryBean', '[Ljava/lang/Object;', 'java/lang/Object' }
stack: { 'java/lang/Throwable' }
Bytecode:
0000000: 03bd 0043 4c13 0172 1301 732a 12ea 1301
0000010: 742b b801 7a4d 2ab4 0062 014e 593a 0413
0000020: 0172 1301 732a 12ea 1301 742b 2c2d 1904
0000030: b801 7eb0 00bf 593a 0501 3a06 1301 7213
0000040: 0173 2a12 ea13 0174 2b2c 1905 1906 b801
0000050: 7ebf
Exception Handler Table:
bci [22, 54] => handler: 54
Stackmap Table:
full_frame(@52,{},{Object[#100]})
full_frame(@54,{Object[#2],Object[#384],Object[#67]},{Object[#100]})
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:329)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:107)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1360)
To increase the flexibility of deploying Grabbit, the bundles that it depends on should be extracted into their own deployable package. Though Felix/AEM has some reasonably smarts when it comes to dependencies, it is also pretty inflexible in other ways. This would give a little more Operational control to people.
The build.gradle file is gaining in size and has the potential to get overwhelming. It can be broken up in to smaller files to keep contents organized.
Whenever we run a Grabbit job and if server fails to send the path requested (various reasons; like The requested path was not found
, Could not access the requested path
, Some other error during sending the requested path
.), we do not transmit that information from Server to Client in order to inform the client that something failed.
This can be handled more gracefully. For example; if a path is not found; we can send a 404
from Server back to the Client with a proper message about what happened. This way; we can also further enhance the Client Grabbit Job Status API
to include such messages in case of job failures.
A client-server pull sync like what is implemented now usually suffices for a manual developer machine sync from a data warehouse or higher environment; However, the common need of syncing a set of environments with content from a single environment (such as DWH to clustered betas, or CI) would benefit from a server to client push sync in a one-to-many fashion. The alternative is synching each, one at a time, which can be time consuming; Especially for large data sets.
This would also give infrastructure to support future enhancements, such as a "transparent content sync from a DWH to subscribing developer machines on a network.", which would arguably help to alleviate content discrepancy issues in a CD implemented AEM project.
Implement a push mode that sends sync data on a network to subscribing "server group members." Consider placing protoc on top one of a number of IP multicast protocols (PGM, RUDP, UDT) that would support this need. JGroups is a popular reliable multicast API for Java.
jackrabbit-sessionImpl.log was created to mitigate confusing WARNING messages when writing content for Grabbit Client.
As the comments in the XML now suggest, the issue was supposedly fixed in AEM 6+. And I also confirmed that these WARNING messages are infact not an issue anymore at least in AEM 6. If that's the case for AEM 6.1 also, should we get rid of this logger for 3.x.x and 4.x.x releases?
The sheer volume of errors generated by the server not being ready to accept messages from the client makes it very easy to be confused what the problem really is. See #28.
When the client first tries to make the connection to the server it should cleanly "notice" that the server isn't there (i.e., that Grabbit is not installed on the server, as opposed to the server not being up or a network problem or the like). It should then give a clear error as to the cause ("Grabbit does not seem to be installed on xxxxxxxx") and stop.
Should this (at least the verification) be done synchronously with the PUT done to the client so that the caller can receive the error right away? Or should it be async with when the client actually tries to communicate with the server?
02.02.2015 21:30:13.471 *ERROR* [clientJobLauncherTaskExecutor-1] org.springframework.batch.core.step.AbstractStep Encountered an error executing step clientJcrNodes in job clientJob org.apache.http.TruncatedChunkException: Truncated chunk ( expected size: 32768; actual size: 16488)
at org.apache.http.impl.io.ChunkedInputStream.read(ChunkedInputStream.java:182)
at org.apache.http.conn.EofSensorInputStream.read(EofSensorInputStream.java:138)
.. happening on the client.
For example, currently an error message looks like this:
01.09.2015 21:39:59.542 *ERROR* [10.143.18.200 [1441143599540] GET /grabbit/job HTTP/1.1] org.apache.sling.engine.impl.SlingRequestProcessorImpl service: Uncaught Throwable javax.jcr.PathNotFoundException: /content/dam/VirtualAssistant
at org.apache.jackrabbit.core.ItemManager.getNode(ItemManager.java:577)
at org.apache.jackrabbit.core.session.SessionItemOperation$6.perform(SessionItemOperation.java:129)
The problem is, there's no (reasonable) way to know what job caused that, especially when there's lots of jobs and multiple clients.
We should try / catch
to add better context information such as the job id, possibly the IP of the client, etc.
Hi my name is Nicola I am an engineer at Infield Design working on OPS tasks involved with AEM. I'm currently trying to setup your Grabbit tool but I've stumbled on an error that I can't seem to resolve. I am trying to sync up content between a dev server and a local instance. Any help would very appreciated. Here is what I get in my error.log when I execute grabbit:
01.05.2015 08:16:31.381 WARN [0:0:0:0:0:0:0:1 [1430493391379] PUT /grabbit/job HTTP/1.1] com.twcable.grabbit.resources.GrabbitResourceProvider Unable to find resource for path: /grabbit.
01.05.2015 08:16:31.381 WARN [0:0:0:0:0:0:0:1 [1430493391379] PUT /grabbit/job HTTP/1.1] com.twcable.grabbit.GrabbitConfiguration Input doesn't contain deltaContent for a boolean value. Will default to false
01.05.2015 08:16:31.381 INFO [0:0:0:0:0:0:0:1 [1430493391379] PUT /grabbit/job HTTP/1.1] org.springframework.batch.core.launch.support.SimpleJobOperator Checking status of job with name=clientJob
01.05.2015 08:16:31.672 INFO [0:0:0:0:0:0:0:1 [1430493391379] PUT /grabbit/job HTTP/1.1] org.springframework.batch.core.launch.support.SimpleJobOperator Attempting to launch job with name=clientJob and parameters=timestamp=1430493391381,path=/content/someone/en_us,host=IPForServer,port=4502,username=usernameForServer,password=passwordForServer,workflowConfigIds=
01.05.2015 08:16:31.741 INFO [0:0:0:0:0:0:0:1 [1430493391379] PUT /grabbit/job HTTP/1.1] com.twcable.grabbit.servlets.GrabbitServlet Jobs started : [7697877024238993081]
01.05.2015 08:16:31.741 INFO [clientJobLauncherTaskExecutor-6] org.springframework.batch.core.launch.support.SimpleJobLauncher Job: [FlowJob: [name=clientJob]] launched with the following parameters: [{workflowConfigIds=, port=4502, password=passwordForServer, host=IPForServer, timestamp=1430493391381, path=/content/someone/en_us, username=usernameForServer}]
01.05.2015 08:16:33.564 INFO [clientJobLauncherTaskExecutor-6] org.springframework.batch.core.job.SimpleStepHandler Executing step: [clientPreprocessor]
01.05.2015 08:16:33.577 ERROR [clientJobLauncherTaskExecutor-6] org.springframework.batch.core.step.AbstractStep Encountered an error executing step clientPreprocessor in job clientJob
com.google.protobuf.InvalidProtocolBufferException: Protocol message end-group tag did not match expected tag.
at com.google.protobuf.InvalidProtocolBufferException.invalidEndTag(InvalidProtocolBufferException.java:73)
at com.google.protobuf.CodedInputStream.checkLastTagWas(CodedInputStream.java:124)
at com.google.protobuf.AbstractMessageLite$Builder.mergeFrom(AbstractMessageLite.java:213)
at com.google.protobuf.AbstractMessage$Builder.mergeFrom(AbstractMessage.java:746)
at com.google.protobuf.AbstractMessage$Builder.mergeFrom(AbstractMessage.java:238)
at com.google.protobuf.AbstractMessageLite$Builder.mergeDelimitedFrom(AbstractMessageLite.java:282)
at com.google.protobuf.AbstractMessage$Builder.mergeDelimitedFrom(AbstractMessage.java:760)
at com.google.protobuf.AbstractMessageLite$Builder.mergeDelimitedFrom(AbstractMessageLite.java:288)
at com.google.protobuf.AbstractMessage$Builder.mergeDelimitedFrom(AbstractMessage.java:752)
at com.twcable.grabbit.proto.PreProcessorProtos$Preprocessors.parseDelimitedFrom(PreProcessorProtos.java:149)
at com.twcable.grabbit.client.batch.steps.preprocessor.PreprocessTasklet.execute(PreprocessTasklet.groovy:53)
at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:395)
at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:130)
at org.springframework.batch.core.step.tasklet.TaskletStep$2.doInChunkContext(TaskletStep.java:267)
at org.springframework.batch.core.scope.context.StepContextRepeatCallback.doInIteration(StepContextRepeatCallback.java:77)
at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:368)
at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:215)
at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:144)
at org.springframework.batch.core.step.tasklet.TaskletStep.doExecute(TaskletStep.java:253)
at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:195)
at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:141)
at org.springframework.batch.core.job.flow.JobFlowExecutor.executeStep(JobFlowExecutor.java:64)
at org.springframework.batch.core.job.flow.support.state.StepState.handle(StepState.java:60)
at org.springframework.batch.core.job.flow.support.SimpleFlow.resume(SimpleFlow.java:151)
at org.springframework.batch.core.job.flow.support.SimpleFlow.start(SimpleFlow.java:130)
at org.springframework.batch.core.job.flow.FlowJob.doExecute(FlowJob.java:135)
at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:301)
at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:134)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
01.05.2015 08:16:33.617 INFO [clientJobLauncherTaskExecutor-6] org.springframework.batch.core.launch.support.SimpleJobLauncher Job: [FlowJob: [name=clientJob]] completed with the following parameters: [{workflowConfigIds=, port=4502, password=passwordForServer, host=IPForServer, timestamp=1430493391381, path=/content/someone/en_us, username=usernameForServer}] and the following status: [FAILED]
Since Adobe's public repo does not have functional 6.1 jars, can we either remove the need to use the workflow jar altogether or potentially compile against an older version so that CI works again?
There should be an easy way to start jobs from a pretty UI, as well as monitoring and management.
Nodes are failing with a NullPointerException or IllegalStateException on latest 6.1 branch recently merged with master.
Example node (author) on DWH server:
/content/dam/residential/specials-ola
Start of stack trace for NPE:
16.07.2015 18:16:17.044 ERROR [clientJobLauncherTaskExecutor-1] org.springframework.batch.core.step.AbstractStep Encountered an error executing step clientWorkflowOff in job clientJob
java.lang.NullPointerException: null
at com.twcable.grabbit.client.batch.workflows.impl.DefaultWorkFlowManager.processConfig(DefaultWorkFlowManager.groovy:122)
at com.twcable.grabbit.client.batch.workflows.impl.DefaultWorkFlowManager.access$0(DefaultWorkFlowManager.groovy)
at com.twcable.grabbit.client.batch.workflows.impl.DefaultWorkFlowManager$_turnOff_closure1.doCall(DefaultWorkFlowManager.groovy:77)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:324)
at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:278)
Stacktrace for IllegalStateException:
16.07.2015 19:01:54.886 ERROR [clientJobLauncherTaskExecutor-3] org.springframework.batch.core.step.AbstractStep Encountered an error executing step clientWorkflowOn in job clientJob
java.lang.IllegalStateException: launcherConfig Map value for /etc/workflow/launcher/config/dam_xmp_writeback cannot be null
at com.twcable.grabbit.client.batch.workflows.impl.DefaultWorkFlowManager$_turnOn_closure2.doCall(DefaultWorkFlowManager.groovy:94)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:324)
at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:278)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1016)
at groovy.lang.Closure.call(Closure.java:423)
at groovy.lang.Closure.call(Closure.java:439)
As the tool gets more sophisticated, the README is not going to be sufficient.
Possibly something like
DELETE /grabbit/job/<JobExecutionid>
Make sure there's no overlap between what Grabbit provides and what AEM 6.1 provides.
The Client UI has since been broken and needs to be redesigned. It should be pulled out of the codebase until it can be properly redeveloped.
Method of interest :
Server: JcrNodesProcessor#toProperty()
Grabbit is currently -- by design -- quite fragile. If there's any bad data, incomplete transmission of data, etc. it is blatantly obvious that something went wrong with no possibility of "silent" errors. Better to fail fast and spectacularly than to let issues hide.
That said, sometimes "99%" is good enough, especially when dealing with development systems and/or unreliable networks. There should be a way to say for a particular job that it should log any errors it gets, but otherwise just keep going.
After installing the Grabbit project onto CQ instances by running the gradle command:
"gradlew install"
The CQ instances that were installed to leave the Spring Batch Infrastructure bundle in the "Installed" state. Because Spring Batch is required to run Grabbit, Grabbit is unusable at this point.
The current work around is simply to restart the CQ instances and Spring Batch starts up correctly. However, this is not a long term solution and needs to be addressed.
The feature is "implemented" but it never got properly tested.
https://github.com/TWCable/grabbit/search?utf8=%E2%9C%93&q=deltaContent
It's based on last successful jobexecution "endTime" for a path on the client.
Needs cleanup, testing and documentation.
https://github.com/google/protobuf/releases/latest
We currently use 2.4.1 but the latest (as of this writing) is 2.6.1. Hoping it would help with some of the issues around large messages/streams (esp #2).
If clientJcrNodes
step fails for some reason, the step after it workflowOnTasklet
does not get executed and leaves the workflow configs in an inconsistent state.
We should either :
workflowOnTasklet
ALWAYS gets executedclientJcrNodes
and manually call the {{workflowOnTasklet}'s execute() method (seems hacky)clientJcrNodesStep
Running v4.0.0
*ERROR* [SimpleAsyncTaskExecutor-43] org.springframework.batch.core.step.AbstractStep Encountered an error executing step clientWorkflowOff in job clientJob
java.lang.NullPointerException: null
at com.twcable.grabbit.client.batch.workflows.impl.DefaultWorkFlowManager.processConfig(DefaultWorkFlowManager.groovy:122)
at com.twcable.grabbit.client.batch.workflows.impl.DefaultWorkFlowManager.access$0(DefaultWorkFlowManager.groovy)
at com.twcable.grabbit.client.batch.workflows.impl.DefaultWorkFlowManager$_turnOff_closure1.doCall(DefaultWorkFlowManager.groovy:77)
Between AEM 5.6.1 and 6.1, there was a change in the jcr:primaryType (cq:Tag to nt:folder) for the node /etc/tags/forums. If you try to copy this node, the job will fail and you'll get the following error:
*ERROR* [clientJobLauncherTaskExecutor-6] org.springframework.batch.core.step.AbstractStep Encountered an error executing step clientJcrNodes in job clientJob
javax.jcr.nodetype.ConstraintViolationException: No matching property definition: jcr:description =
at org.apache.jackrabbit.oak.jcr.delegate.NodeDelegate.setProperty(NodeDelegate.java:522)
In this case, the situation seems fairly innocuous, and just a warning that the server jcr:PrimaryType does not match the existing client and either doing a no op or doing the conversion for that node would seem to work. This would allow you to avoid having to work around the node.
If this isn't possible, or desired, just a clearer error message indicating the primaryType doesn't match may be helpful to a user of Grabbit.
Right now each client has to maintain its own JSON file(s) for defining the copy jobs, which is error-prone -- especially as authors change the "shape" of the JCR tree.
The server should be able to provide centrally managed configuration sets. For example, "Full", "Base" (enough to get a developer environment up and running quickly), sets for each major content area, etc.
This happens locally, and on CI. Need to figure out if the test is flawed, or if legitimately have multithreading issues.
Error in log:
27.03.2015 13:45:05.521 ERROR [0:0:0:0:0:0:0:1 [1427463905517] POST /system/console/bundles/354 HTTP/1.1] cqse-httpservice %bundles.pluginTitle: Cannot start (org.osgi.framework.BundleException: Uses constraint violation. Unable to resolve bundle revision org.springframework.batch.infrastructure [354.0] because it exports package 'org.springframework.batch.repeat' and is also exposed to it from bundle revision org.springframework.batch.infrastructure [327.0] via the following dependency chain:
org.springframework.batch.infrastructure [354.0]
import: (&(osgi.wiring.package=org.springframework.batch.core)(version>=2.0.0)(!(version>=3.0.0)))
|
export: osgi.wiring.package=org.springframework.batch.core; uses:=org.springframework.batch.repeat
org.springframework.batch.core [353.0]
import: (&(osgi.wiring.package=org.springframework.batch.repeat)(version>=2.2.0)(!(version>=3.0.0)))
|
export: osgi.wiring.package=org.springframework.batch.repeat
org.springframework.batch.infrastructure [327.0]) org.osgi.framework.BundleException: Uses constraint violation. Unable to resolve bundle revision org.springframework.batch.infrastructure [354.0] because it exports package 'org.springframework.batch.repeat' and is also exposed to it from bundle revision org.springframework.batch.infrastructure [327.0] via the following dependency chain:
org.springframework.batch.infrastructure [354.0]
import: (&(osgi.wiring.package=org.springframework.batch.core)(version>=2.0.0)(!(version>=3.0.0)))
|
export: osgi.wiring.package=org.springframework.batch.core; uses:=org.springframework.batch.repeat
org.springframework.batch.core [353.0]
import: (&(osgi.wiring.package=org.springframework.batch.repeat)(version>=2.2.0)(!(version>=3.0.0)))
|
export: osgi.wiring.package=org.springframework.batch.repeat
org.springframework.batch.infrastructure [327.0]
at org.apache.felix.framework.Felix.resolveBundleRevision(Felix.java:3968)
at org.apache.felix.framework.Felix.startBundle(Felix.java:2025)
at org.apache.felix.framework.BundleImpl.start(BundleImpl.java:955)
at org.apache.felix.framework.BundleImpl.start(BundleImpl.java:942)
at org.apache.felix.webconsole.internal.core.BundlesServlet.doPost(BundlesServlet.java:364)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:820)
at org.apache.felix.webconsole.internal.servlet.OsgiManager.service(OsgiManager.java:526)
at org.apache.felix.webconsole.internal.servlet.OsgiManager.service(OsgiManager.java:450)
at org.apache.felix.http.base.internal.handler.ServletHandler.doHandle(ServletHandler.java:96)
at org.apache.felix.http.base.internal.handler.ServletHandler.handle(ServletHandler.java:79)
at org.apache.felix.http.base.internal.dispatch.ServletPipeline.handle(ServletPipeline.java:42)
at org.apache.felix.http.base.internal.dispatch.InvocationFilterChain.doFilter(InvocationFilterChain.java:49)
at org.apache.felix.http.base.internal.dispatch.HttpFilterChain.doFilter(HttpFilterChain.java:33)
at org.apache.sling.i18n.impl.I18NFilter.doFilter(I18NFilter.java:127)
at org.apache.felix.http.base.internal.handler.FilterHandler.doHandle(FilterHandler.java:88)
at org.apache.felix.http.base.internal.handler.FilterHandler.handle(FilterHandler.java:76)
at org.apache.felix.http.base.internal.dispatch.InvocationFilterChain.doFilter(InvocationFilterChain.java:47)
at org.apache.felix.http.base.internal.dispatch.HttpFilterChain.doFilter(HttpFilterChain.java:33)
at org.apache.felix.http.sslfilter.internal.SslFilter.doFilter(SslFilter.java:55)
at org.apache.felix.http.base.internal.handler.FilterHandler.doHandle(FilterHandler.java:88)
at org.apache.felix.http.base.internal.handler.FilterHandler.handle(FilterHandler.java:76)
at org.apache.felix.http.base.internal.dispatch.InvocationFilterChain.doFilter(InvocationFilterChain.java:47)
at org.apache.felix.http.base.internal.dispatch.HttpFilterChain.doFilter(HttpFilterChain.java:33)
at com.adobe.granite.license.impl.LicenseCheckFilter.doFilter(LicenseCheckFilter.java:179)
at org.apache.felix.http.base.internal.handler.FilterHandler.doHandle(FilterHandler.java:88)
at org.apache.felix.http.base.internal.handler.FilterHandler.handle(FilterHandler.java:76)
at org.apache.felix.http.base.internal.dispatch.InvocationFilterChain.doFilter(InvocationFilterChain.java:47)
at org.apache.felix.http.base.internal.dispatch.HttpFilterChain.doFilter(HttpFilterChain.java:33)
at org.apache.sling.security.impl.ReferrerFilter.doFilter(ReferrerFilter.java:263)
at org.apache.felix.http.base.internal.handler.FilterHandler.doHandle(FilterHandler.java:88)
at org.apache.felix.http.base.internal.handler.FilterHandler.handle(FilterHandler.java:76)
at org.apache.felix.http.base.internal.dispatch.InvocationFilterChain.doFilter(InvocationFilterChain.java:47)
at org.apache.felix.http.base.internal.dispatch.HttpFilterChain.doFilter(HttpFilterChain.java:33)
at org.apache.sling.engine.impl.log.RequestLoggerFilter.doFilter(RequestLoggerFilter.java:75)
at org.apache.felix.http.base.internal.handler.FilterHandler.doHandle(FilterHandler.java:88)
at org.apache.felix.http.base.internal.handler.FilterHandler.handle(FilterHandler.java:76)
at org.apache.felix.http.base.internal.dispatch.InvocationFilterChain.doFilter(InvocationFilterChain.java:47)
at org.apache.felix.http.base.internal.dispatch.HttpFilterChain.doFilter(HttpFilterChain.java:33)
at org.apache.felix.http.base.internal.dispatch.FilterPipeline.dispatch(FilterPipeline.java:48)
at org.apache.felix.http.base.internal.dispatch.Dispatcher.dispatch(Dispatcher.java:39)
at org.apache.felix.http.base.internal.DispatcherServlet.service(DispatcherServlet.java:67)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:820)
at com.day.j2ee.servletengine.ServletRuntimeEnvironment.service(ServletRuntimeEnvironment.java:250)
at com.day.j2ee.servletengine.RequestDispatcherImpl.doFilter(RequestDispatcherImpl.java:321)
at com.day.j2ee.servletengine.RequestDispatcherImpl.service(RequestDispatcherImpl.java:340)
at com.day.j2ee.servletengine.RequestDispatcherImpl.service(RequestDispatcherImpl.java:383)
at com.day.j2ee.servletengine.ServletHandlerImpl.process(ServletHandlerImpl.java:335)
at com.day.j2ee.servletengine.HttpListener$Worker.run(HttpListener.java:644)
at java.lang.Thread.run(Thread.java:745)
When using workflowConfigIds with AEM 6.1, it appears the data transfer will fail if the node does not actually have workflow tied to it (typically a publish instance), with the error:
24.06.2015 12:34:23.999 ERROR [clientJobLauncherTaskExecutor-7] org.springframework.batch.core.step.AbstractStep Encountered an error executing step clientWorkflowOn in job clientJob
java.lang.IllegalStateException: launcherConfig Map value for /etc/workflow/launcher/config/dam_xmp_writeback cannot be null
at com.twcable.grabbit.client.batch.workflows.impl.DefaultWorkFlowManager$_turnOn_closure2.doCall(DefaultWorkFlowManager.groovy:90)
Example config:
{
"path" : "/content/dam/VirtualAssistant",
"workflowConfigIds" :
[
"/etc/workflow/launcher/config/update_asset_mod",
"/etc/workflow/launcher/config/update_asset_create",
"/etc/workflow/launcher/config/dam_xmp_nested_writeback",
"/etc/workflow/launcher/config/dam_xmp_writeback"
]
},
Move Grabbit Server to use JcrJobRepository
Currently, nt:file
is the only node that is explicitly handled (and that too incompletely). Grabbit currently only supports nt:file
with underlying jcr:content
of nt:resource
type. According to the JCR specification, the underlying jcr:content
node can be of ANY type.
Also, there are other hierarchy nodes that need to be handled / implemented.
Currently, travis-ci does not understand protoc
compiler and hence cannot build the project. Look into adding dependencies to travis-ci.
Something like
{
"path" : "/content/someContent",
"excludePaths" :
[
"subPath1",
"subPath2/xyz"
],
}
To keep things clear/simple, the excludePaths
should only allow relative paths to the path
for that block. For example the following would be illegal:
{
"path" : "/content/someContent",
"excludePaths" :
[
"/content/otherContent",
"/content/someContent/apath"
],
}
An open question: Should "." be legal?
Some of the configuration options would get cleaner if YAML were supported. (e.g., comments, reference support, reduced verbosity, etc.) Fortunately JSON is a subset of YAML, so existing configs would still work.
Encountered exception is as follows (on the client)
02.02.2015 22:08:07.101 [clientJobLauncherTaskExecutor-3] com.twcable.grabbit.client.batch.steps.jcrnodes.JcrNodesWriter *INFO* Encountered invalid mixin type while unmarshalling for Proto values : value {
stringValue: "mix:versionable"
}
02.02.2015 22:08:07.102 [clientJobLauncherTaskExecutor-3] com.twcable.grabbit.client.batch.steps.jcrnodes.JcrNodesWriter *INFO* Encountered invalid mixin type while unmarshalling for Proto values : value {
stringValue: "mix:lockable"
}
02.02.2015 22:08:07.103 [clientJobLauncherTaskExecutor-3] com.twcable.grabbit.client.batch.steps.jcrnodes.JcrNodesWriter *ERROR* Exception writing JCR Nodes to current JCR Session : session-admin-334713. javax.jcr.version.VersionException: Unable to perform operation. Node is checked-in.
at org.apache.jackrabbit.core.ItemValidator.checkCondition(ItemValidator.java:284)
at org.apache.jackrabbit.core.ItemValidator.checkModify(ItemValidator.java:248)
For starters, may be look at how filevault does it : https://github.com/apache/jackrabbit-filevault/blob/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/ImportInfoImpl.java#L228-L234 (using node.checkIn() )
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.