AEM6.2
I have a Osgi Service where in org.apache.sling.event.jobs.JobManager referenced and job is added to it.
The code is something like:
Map dataSourceMap = new HashMap<String, DataSource>
dataSourceMap.put(fileName, new ByteArrayDataSource(byte[], mimeTypeOfFile))
final Map<String, Object> props = new HashMap<String, Object>();
props.put("item1", "/something");
props.put("count", 5);
props.put("files", dataSourceMap)
jobManager.addJob("my/special/jobtopic", props);
When this job gets executed it shows some error
org.apache.sling.api.resource.PersistenceException: Value can't be stored in the repository: {<<filename>>=org.apache.commons.mail.ByteArrayDataSource#3f0f234c}
Question: Is there any solution to this exception? Or am I doing something wrong? can we add a ByteArrayInputStream to the jobmanager?
Thank you !
Just a info, If I remove the line props.put("files", dataSourceMap), it works fine.
Please let me know if you need more info on it.
Sling will store the job as a node in the repository and it looks like it only supports the "standard" types like String, Boolean, Integer etc. and not files/blobs.
I can not think of a way to add a file to the job, but what you could do is to create temporary node in the repository yourself, which contains the files/blobs.
Sling stores jobs here:
/var/eventing/jobs
You might do something similar:
/var/<project-name>/jobs
And the payload of the Sling job then contains the path to this job node.
Further to Jens' comment, the job will indeed store data as node properties in the JCR. You could likely explore the possibility of storing data as Binary to the jcr:data property, but I have not tested this myself.
As a quick and likely not very optimized workaround, why not serialize your byte[] to a String or even encode it to a Base64 string?
Sample: Base64 Java encode and decode a string [duplicate]
Related
I know, but we really need it.
We have a clear division of labor.
They create templates, I fill them in runtime according to some rules.
Can't teach my business to insert something like this and be sure they really did it ok(so can't move any logic to templates):
$P{risk_types}.get($F{risk_type}) ?: "UNDEFINED"
Also can not fill from files hardcoded in some adapter hadwritten by god-knows-who and unchangeable in runtime. It's a web app. Best option is to find a way to replace that file source from adapter to a ByteArrayStream.
SO:
Need to substitute contents of parameters(also default ones) at runtime.
example:
need to set JSON_INPUT_STREAM
Like this unsolved thread.
https://community.jaspersoft.com/questions/516611/changing-parameter-scriptlet
Really hope not to work on xml level, but xml also can't solve my problem as far as I tried.
Thank you!
The easiest and cleanest way we did this(bypassing usage of tons of deprecated documentation and unfinished bugged undocumented static antipatterned new features):
Create context with repository extension
SimpleJasperReportsContext jasperReportsContext = new SimpleJasperReportsContext();
jasperReportsContext.setExtensions(RepositoryService.class, Collections.singletonList(new MyRepositoryService(jasperReportsContext, yourOptionalParams)));
Fill this way(after compile and other usual actions)
JasperPrint print = JasperFillManager.getInstance(jasperReportsContext).fill(compiled, new HashMap<>());
Now your repository must extend default one to be hack-injected(cause of hodgie coded "isAssignableFrom") successfully
public class PrintFormsRepositoryService extends DefaultRepositoryService {
#Override
public InputStream getInputStream(RepositoryContext context, String uri) {
// return here your own good simple poj inputStream even from memory if you found source
// or pass to another repository service(default one probably)
return null;
}
}
I'm trying to store binary data in JCR, which is created on the fly. My problem is that the only way provided by the JCR API is via an InputStream:
Session session = request.getResourceResolver().adaptTo(Session.class);
ValueFactory valueFactory = session.getValueFactory();
Binary bin = valueFactory.createBinary(is);
As CQ/Sling is RESTful I can see why this is the case as you usually get a form post or an httprequest to another source, where you always have an InputStream to use. But in my case I am creating the binary on the fly which usually is represented as an OutputStream.
Is there any other way I overlooked in the JCR API where I could create an OutputStream directly on the nt:file node, just like a FileOutputStream?
If no, is there an easy way to have an OutpuStream transformed to an InputStream?
I know the other way is available from the Apache Commons IOUtils.copy(). I've seen some examples on SO where they just use the ByteArrayOutputStream.toByteArray() to create an InputStream. But as the data could get rather large, this is not a good solution. Besides I tried it and somehow the stream was incomplete, so it seems there is a buffer limmit. The next approach was with piped streams, but there I have other problems to which I opened another question: Multiple quotes cause PipedOutputStream/OutputStreamWriter to fail
EDIT:
Removed PipedStream code example as I posted the issue with it in another question. So here I am still just looking for an easy way to create an nt:file where the input is not an InputStream.
Pipes are good solution here. However, in order to implement them properly, you have to use two threads: first should write data into the PipedOutputStream and the second should create a Binary from PipedInputStream and save it into JCR:
final PipedInputStream pis = new PipedInputStream();
final PipedOutputStream pos = new PipedOutputStream(pis);
Executors.newSingleThreadExecutor().submit(new Runnable() {
#Override
public void run() {
try {
OutputStreamWriter writer = new OutputStreamWriter(pos);
writer.append("append here some data");
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
});
Binary binary = session.getValueFactory().createBinary(pis);
session.getNode("/content/myNode").setProperty("xyz", binary);
session.save();
The symmetrical solution, in which you handle the JCR in the new thread would be also good.
Have you tried on of the methods described here?
http://ostermiller.org/convert_java_outputstream_inputstream.html
I think the easiest methods would be using an array:
ByteArrayOutputStream out = new ByteArrayOutputStream();
//alternatively, get the outputstream of your binary file generator
(...) //put data into out
InputStream is = new ByteArrayInputStream(out.toByteArray())
I want to link to a method that has the following signature:
public SomeResponse getSomeObjects(#RequestParam(value = "foo", defaultValue = "bar") Foo fooValue)
Now I want the link to look like this:
http://myhost/api/someobjects
I tried using methodOn from Spring HATEOAS's ControllerLinkBuilder as seen below:
discoverResponse.add(linkTo(methodOn(SomeController.class).getSomeObjects(null)).withRel("someobjects"))
But it doesn't lead to the desired link because a ?foo is added at its end. How can I achieve the above objective?
Since backward compatibility is such an issue for you, you could always manually construct your Link objects like so:
discoverResponse.add(new Link(baseUri() + "/someobjects", "someobjects"));
The other option would be to fork Spring HATEOAS on GitHub, build the project yourself, and change the way defaults are handled in ControllerLinkBuilder. I don't really know how you'd expect an out-of-context Link builder to be able to differentiate between whether it should advertise an optional parameter. In the HATEOAS world, if the parameter isn't included, the client doesn't know about it. So why even have the optional parameter?
I know there are 7 years gone now, but I had a similar problem today which lead me here. In spring hateoas 1.1.0 the behavior is slightly different, instead it will generate URI-Templates by default for non-required #RequestParams:
http://myhost/api/someobjects{?foo}
If you don't want them in your link, you can just expand it
Map<String, Object> parameters = new HashMap<>();
parameters.put("foo", null);
link = link.expand(parameters);
It will result in the desired URL
http://myhost/api/someobjects
I have created an application using this
http://msdn.microsoft.com/en-us/magazine/ff646977.aspx
What i need to do is callWorkflow instances store dynamically
i.e before
string message = "";
string result = client.EvaluateMortgage();
I should be able to specify the sqlworkflowinstancestore i.e where the workflow data is
Any help will be appreciated.
I think you can do like this,
SqlWorkflowInstanceStore store = new SqlWorkflowInstanceStore(connectionString);
More info
Here you can find several ways of configuring /using it
I am getting files from Oracle UCM via RIDC. I am using DataBinder as follows :
IdcClient client =getUCMConnection();
DataBinder dataBinder = client.createBinder ();
dataBinder.putLocal ("IdcService", "GET_FILE");
dataBinder.putLocal ("dID", dID);
IdcContext userContext = new IdcContext(username);
ServiceResponse response = client.sendRequest (userContext, dataBinder);
InputStream fstream = response.getResponseStream ();
....... etc.
I want to ask, how can I get "ALL VERSIONS" of a document instead of latest released one?
First you have to call the service DOC_INFO, you can get the result set of the revision by using the REVISION_HISTORY set.
You will get specific dID for each version, you iterate them and use GET_FILE with dID as a parameter for each one of them
I can't test it right now but I think the service you are looking for is GET_INFO, try it and check all the resultsets you get I'm pretty sure one of them has the info for all the document's revisions.
You can use the service REV_HISTORY to get the result set REVISIONS which contains info of all the revisions.