Email Template Custom Parameter for template property - alfresco

I'm implementing a simple mail triggering service to notify about workflow tasks to user. I have used the following code under user task and the mail is getting trigerred as expected, but is there a way to access template from S3 bucket URL/link rather than Data dictionary.
Following is my current code
var mail = actions.create("mail");
mail.parameters.to = "xyx#gmail.com";
mail.parameters.subject="Hello";
mail.parameters.text="blablabla";
mail.parameters.template = companyhome.childByNamePath('Data Dictionary/Email Templates/Workflow Notification/File.html.ftl');
var templateArgs = new Array();
templateArgs['workflowTitle'] = "Page";
templateArgs['workflowDescription'] = "Task Assigned";
templateArgs['workflowId'] = "11111";
var templateModel = new Array();
templateModel['args'] = templateArgs;
mail.parameters.template_model = templateModel;
mail.execute(bpm_package);

If you are using the S3 Connector, then all of the objects in your Alfresco repository reside in S3, including freemarker templates.
If you are not using the S3 Connector there is really no easy, out-of-the-box way to pull a template in from S3 or any other source.
You could always write it yourself. You can invoke external REST endpoints from JavaScript controllers of web scripts. You can also write a Java controller that could do it.
Essentially your web script would fetch the template then do your own merge then send the result of the merge as the body of the email.
Not sure how bad you want to store your templates in S3, but that's essentially how you'd do it.
You could also consider writing a scheduled action that would just synchronize objects stored in S3 with nodes in the repo, then your action would work unchanged.

Related

How to reuse KafkaListenerContainerFactory with a custom message converter for batch listeners and non-batch/record listeners?

The spring-kafka documentation mentions:
Starting with version 2.8, you can override the factory’s batchListener propery using the batch property on the #KafkaListener annotation. This, together with the changes to Container Error Handlers allows the same factory to be used for both record and batch listeners.
I want to use it like this. So reuse the same factory for record and batch listeners. The factory is provided by an internal library that is used by multiple services.
However, I also need to define a custom MessageConverter.
But I found out that for batch listeners I need to wrap my message converter in BatchMessagingMessageConverter otherwise the message converter will not be used correctly and the wrong type will be supplied to my batch listener.
So: Is there a simple way to reuse KafkaListenerContainerFactory with a custom messageConverter for batch listeners and non-batch/record listeners?
My current workaround looks like this, but I do not like it as it depends on how spring-kafka internally sets up its configuration, so it might break in future updates:
factory.setContainerCustomizer(container -> {
var messageListener = container.getContainerProperties().getMessageListener();
if (messageListener instanceof FilteringBatchMessageListenerAdapter) {
var meessageListenerDelegate =
((FilteringBatchMessageListenerAdapter<?, ?>) messageListener).getDelegate();
if (meessageListenerDelegate instanceof BatchMessagingMessageListenerAdapter) {
((BatchMessagingMessageListenerAdapter<?, ?>) meessageListenerDelegate).setBatchMessageConverter(
new BatchMessagingMessageConverter(messageConverter));
}
}
});
Another option is to create a separate factory for batch listeners. With this, I am afraid that someone might use #KafkaListener(batch="true") without supplying the correct library, which only works partly.
Currently, I am using version 2.8.9 of spring-kafka.
It is not currently possible; please open a new feature suggestion on GitHub to allow provisioning both types of converter on the factory.

Symfony. Using transactions with 2+ repositories

In a certain controller I need to do several inserts/updates in the database. I'm using 4 repositories of 4 entities for that, but I need this to be done in a unit of work.
I know that I can do these inserts/updates directly on the controller and use $em->getConnection()->beginTransaction(), $em->getConnection()->rollBack() and $em->getConnection()->commit() to ensure that all or none are done. But this goes against symfony best practices, so I'd like to use repositories.
I've seen this tutorial for Doctrine 1, but it seems like a very complex solution to something that is supposed to be simpler.
Any idea?
Thank you in advance.
edit, I'm using Symfony 3.3.5.
edit2, I add an example of what I want to do. The whole process is to add a message written by a worker to the rest of his department mates, all within a company. The message may or may not have attachments (let's say it does). These files should appear as department and company files, so that even if the department is deleted, the files continue to appear as belonging to the company.
I haven't included error handling in the code to make it simpler.
// New Files
$file1 = new File(); // AppBundle\Entity\File
$file1->setName("name1");
$file2 = new File();
$file2->setName("name2");
$em->getRepository('AppBundle:File')->insert($file1);
$em->getRepository('AppBundle:File')->insert($file2);
// New Post
$post = new Post(); // AppBundle\Entity\Post
$post->setContent($some_text)
->setAuthor($some_user) // AppBundle\Entity\User
->addFile($file1)
->addFile($file2);
$em->getRepository('AppBundle:Post')->insert($post);
// Getting company and department
$company = $em->getRepository('AppBundle:Company')->findOneByCode($some_company_code);
$department = $em->getRepository('AppBundle:Department')->findOneByCode($some_dept_code);
$company->addFile($file1)->addFile($file2);
$department->addFile($file1)->addFile($file2);
$em->getRepository('AppBundle:Company')->update($company);
$em->getRepository('AppBundle:Department')->update($department);
// Notifications
$notif = new Notification(); // AppBundle\Entity\Notification
$notif->setText("Text")
->setPost($post)
->addAddressee($some_dept_member)
->addAddressee($other_dept_member);
$notif = $em->getRepository('AppBundle:Notification')->insert($notif);
In repositories you should only fetch entities or execute queries with DQL that retrieve some data.
Every time you need to create a new row in your db, you have to inform the entity manager that you want to persist the entity, calling $em->persist($myNewEntity). This inform the entity manager that that entity should be persisted to dB.
Once you have created (and persisted) all your entities and/or modified your fetched entities, you can call $em->persist() just once: the entity manager will do all the needed insert/update/delete in a single transaction to your dB.
If you also need to retrieve/fetch data in the same transaction you should consider including all your code in a callback function and pass it to the entity manager, like this
$myCallback=function($em) {
//Do all here: access repositories, create new entities, edit entities
//...
//no need to call $em->flush(), it will be called by Doctrine after the execution of the callback
};
$em->transactional($myCallback) ;

could not be mapped to a JSON object in Logansquare

i am trying to fetch data from Realm and sending it to server using retrofit and for parsing and serializing i am using LoganSquare
client = new Retrofit.Builder()
.baseUrl(REST_ENDPOINT)
.client(okHttpClient)
.addConverterFactory(LoganSquareConverterFactory.create())
.build();
this is how i am accessing record
Appointment appointments = DB.getInstance(mContext).selectNotSyncAppointmentsData();
RestApi.AppointmentsDataApi service = getAppointmentsDataApi();
Call<APResponse> call = service.createUpdateAppointmentsData(appointments);
i am getting following error
createUpdateAppointmentData : onFailure Class io.realm.AppointmentRealmProxy could not be mapped to a JSON object. Perhaps it hasn't been annotated with #JsonObject?
I am not familiar with how LoganSquare works, but be aware that Realm works with something called proxy classes that extend all your model classes. You can recognise these as they are called <ModelClass>RealmProxy. It looks like you somehow have to find a way to configure LoganSquare to recognise these sub-classes.
Alternatively you can use realm.copyFromRealm(appointments). That will give you an in-memory copy of all the data which are of the correct class.

Is there a way to access the FlashBag from outside Symfony?

I'm working in app that interacts with a Symfony app, and renders a template from the Symfony app that uses the FlashBag. What I have so far:
use Symfony\Component\HttpFoundation\Session\Flash\FlashBag;
/*snipped code that creates a Symfony container*/
$container->enterScope('request');
$container->set('request', new \Symfony\Component\HttpFoundation\Request(), 'request');
$twig = $container->get('twig');
$twig->addGlobal('app', array('session' => array('flashbag' => new FlashBag())));
echo $twig->render('AdminBundle::flashMessages.html.twig');
The problem is the FlashBag object I've created does not pick up the Flash messages that are in the session, so while technically the twig template does render, it never actually displays the flash messages.
An additional point of difficulty is that the outside app makes use of session, so just creating a Symfony session object also causes problems.
I discovered that all of Symfony's flash messages are stored in $_SESSION['_sf2_flashes']. After I create the FlashBag, I call initialize and pass the flash messages in $_SESSION, like so, before adding flashBag as a global to Twig:
$flashMessages = isset($_SESSION['_sf2_flashes']) ? $_SESSION['_sf2_flashes'] : array();
$flash->initialize($flashMessages);
I also found that when done this way, the flash messages don't seem to get consumed from $_SESSION like when you access them the normal way, so I also had to call:
unset($_SESSION['_sf2_flashes']);
You need to use Request::createFromGlobals() to populate your Request object. Then you can use that request object to get the flash messages.

Getting progress on POST using HTTPService in Flex/AS3

I'm using HTTPService with a POST operation to submit a Base64 encoded file (taken from bitmap data within the app) but I could really do with getting some idea of the progress of the POST operation (e.g. like the FileReference.upload()).
I don't think this is possible, but it would be awesome if it is (via any means, I'm willing to change my setup to get this).
Do not use HTTPService. Use URLRequest, URLLoader, and URLVariables.
If your using an HTTPService tag, get ride of it and replace it with a Script tag filled with something like ...
private function forYou() : void{
var req : URLRequest = new URLRequest("PUT YOUR URL HERE")
var loader : URLLoader = new URLLoader();
var params : URLVariables = new URLVariables();
params.WHATEVER = WHATEVER YOU WANT IT TO BE;
req.data = params;
req.method = URLRequestMethod.POST;
loader.addEventListener(ProgressEvent.PROGRESS, YOUR LISTENER FUNCTION NAME);
loader.load(req);
}
Assign this function name to the creationComplete attribute of the root tag.
If your not using an HTTPService tag, just get ride of the HTTPService object in your actionscript and use the above code.
This worked well for me to consume a REST web service:
http://code.google.com/p/as3httpclient/wiki/Links
Example
This isn't possible with HTTPService. Its only events are result, fault, and invoke (other than the non-relevant inherited events of activate and deactivate).
To get progress information on an upload process, the server would have to provide the information, which would require a means of communication between the server and the client during the operation, which isn't there for a regular HTTP POST operation.
One option might be to create an object on the server that would be instantiated whenever the server began receiving POST data from your client. It would then keep track of the progress and expose that data to the rest of your server-side application. Your client could then initiate a polling system that would request the value of that particular variable.
Seems like kind of a far-fetched option, though...

Resources