Fetch Thymeleaf Templates from Remote Location - thymeleaf

I want to fetch the email Template from GITHUB and use the template in my Thymeleaf configuration to send email. I don't want to save my Template inside my JAR running at PCF. It should be on fly.
I was successful in fetching the HTML file from GITHUB
Now the HTML file is maintained as InputStream
Now the question is how use this Inputstream at TemplateResolver and set my variables and create the String value of the HTML content to send Email ?

You can process a String template like this:
SpringTemplateEngine templateEngine = new SpringTemplateEngine();
Context ctx = new Context();
ctx.setVariable("variable", "value");
String processedTemplate = templateEngine.process("<html><div th:text='${variable}' /></html>", ctx);
System.out.println(processedTemplate);

Related

Add password protection to PDF using Rotativa.MVC

Does Rotativa.MVC support pdf encryption with password? I wasn't able to find any reference about it.
There is no option to add a password in Rotativa.MVC.
You need to generate your pdf via html and add owner password, user password after that.
Basically you will need another piece of software to encrypt that pdf file or to develop that piece of software by yourself.
Using something like: https://github.com/itextsharper/iTextSharp-4.1.6/blob/master/iTextSharp/text/pdf/PdfEncryptor.cs you'll be able to do the following:
Encrypt(PdfReader reader, Stream os, byte[] userPassword, byte[] ownerPassword, int permissions, bool strength128Bits, Hashtable newInfo)
using (var input = new FileStream("rotativa_generated.pdf", FileMode.Open, FileAccess.Read, FileShare.Read))
using (var output = new FileStream("rotativa_generated_encrypted.pdf", FileMode.Create, FileAccess.Write, FileShare.None))
{
var reader = new PdfReader(input);
PdfEncryptor.Encrypt(reader, output, true, "userPassword", "ownerPassword", PdfWriter.ALLOW_PRINTING);
}
Users need only userPassword to get access.
Or you can migrate to something like https://github.com/mstamy2/PyPDF2 just for encryption. (free for commercial use as far as i know)

MultiLingual Email template with grails

I am trying to send emails from grails and the mail template should be multilingual.
I found that we can render GSP as a string or even in the grails mail plugin we can render the GSP.
In the GSP now I read the static messages from messages.properties assuming that I would define for each languages and my emails would go multi lingual.
Now here is the problem that I am facing
In the template the language is always set to en_US. I am using the below API to get the string of the template. I am not using mail plugin directly as I need to store the send message as string into the database as well
def contents = groovyPageRenderer.render(template:"/layouts/emailparse", model:[mailObj: mailObj])
I also read on other post on forum about setting the language using lang parameter but still the language is set to en_US only.
Would the above method call support specifying language?
Is there an option to use velocity template to do this kind of multilingual mails?
If you're sending the mail from within a request handling thread (e.g. from a controller action) then it should pick up the right locale from the request automatically. If you're sending from a background thread then it won't know what locale to use because there's no "current request" context.
If you have another way to know the correct language to use (e.g. if you store each user's preferred language in the database) then you could reset the LocaleContextHolder
def savedContext = LocaleContextHolder.getLocaleContext()
LocaleContextHolder.setLocale(correctLocaleForThisUser)
try {
def contents = groovyPageRenderer.render(template:"/layouts/emailparse", model:[mailObj: mailObj])
// etc. etc.
} finally {
LocaleContextHolder.setLocaleContext(savedContext)
}
Exactly how you determine the correctLocaleForThisUser depends on your application. You could store each user's preferred language as a property of the User domain object in the database, or if you're using something like the executor plugin's runAsync from a controller action then you could save the request locale while you have access to it and then re-use that in the async task:
// SomeController.groovy
def sendEmail() {
// get locale from the thread-local request and save it in a local variable
// that the runAsync closure can see
Locale localeFromRequest = LocaleContextHolder.getLocale()
runAsync {
def savedContext = LocaleContextHolder.getLocaleContext()
// inject the locale extracted from the request
LocaleContextHolder.setLocale(localeFromRequest)
try {
def contents = groovyPageRenderer.render(template:"/layouts/emailparse", model:[mailObj: mailObj])
// etc. etc.
} finally {
LocaleContextHolder.setLocaleContext(savedContext)
}
}
}
Can you work around this by creating a model containing a list with the correct translations?
For example:
def messages = [:]
messages['hello.world'] = messageSource.getMessage(
"hello.world",
null,
new Locale("nb")
)
def template = groovyPageRenderer.render(
template: '/mail/email',
model:[messages:messages]
)
And then in the view you just write:
<html>
<head>
<title>${messages['hello.world']}</title>
</head>
<body>
</body>
</html>

XSSFWorkbook#write() results in empty response

I'm trying to get my JSF to export a spreadsheet for download. I'm using Apache's POI library for the Excel document writing. I get the following error in an alert box when the code runs:
emptyResponse: An empty response was received from the server.
The method generating the spreadsheet and exporting to the OutputStream is below (I have renamed classes, methods etc for simplicity sake).
private void generateSpreadsheet(Object object) throws Exception {
FacesContext context = FacesContext.getCurrentInstance();
HttpServletResponse response = (HttpServletResponse)context.getExternalContext().getResponse();
String fileName = object.getProperty() + ".xlsx";
response.setContentType("application/vnd.ms-excel");
response.setHeader("Content-Disposition", "attachment;filename=\"" + fileName +"\"");
OutputStream os = response.getOutputStream();
Workbook wb = new XSSFWorkbook();
Sheet sheet = wb.createSheet("Sheet 1");
Row row = sheet.createRow(0);
Cell cell = row.createCell(0);
cell.setCellValue("test");
wb.write(os);
os.flush();
os.close();
FacesContext.getCurrentInstance().responseComplete();
}
Any advice much appreciated, thanks.
If it makes a difference, I'm using AJAX (<f:ajax> tag) on the form submit that calls this method.
It makes definitely difference. You can not download files by Ajax. Ajax is executed by JavaScript code. But JavaScript has no facilities to force a Save As dialogue or to execute the platform default application associated with the file's mime type (thankfully; that would have been a major security/intrusion problem). Further, the JSF Ajax API expects a XML response in a specified structure conform the JSF specs. When you send a complete Excel file instead, the whole Ajax response would be ignored as ununderstandable garbage by the JSF Ajax API.
You need to send a normal synchronous request. Remove the <f:ajax> tag from the command link/button. The current page will remain the same anyway if the download is sent as an attachment.

How to get an instance of the current HttpRequestBase outside of a Controller or View's context

What I'm doing:
I am creating an email mailing engine that takes html templates, replaces tokens with data and then sends off the mail to an SMTP server. Eventually we'll want a CMS UI on top of this to allow them to add/remove file templates or update the content in them via a CMS UI. Anyway I am putting the .htm files for the email templates inside my MVC web project and need to read their contents and get the string of HTML back to work with. If I move all this code out of my MVC project into like a utility C# project layer, the problem is then I have to worry about maintaining physical paths ("C:...\theMVCWebSiteFolder...\Email\Templates\SomeTemplate.htm") and that to me would have to be hard coded I think to keep track if you were to move the site to a different server, different hard drive partition, etc. So I'd like to be able to work with the files using the current application's context unless there's a way to do this agnostic to my MVC app and still not have to worry about having to ever change the location of the physical root every time we move folders.
I've got the following utility method I created in a utility class that sits in a folder somewhere in my ASP.NET MVC web project in just a folder (a folder outside of any view folders:
public static string GetFileData(string filePath)
{
if (!File.Exists(HttpContext.Current.Request.PhysicalApplicationPath + filePath))
throw new FileNotFoundException(String.Format("the file {0} was not found", filePath));
string text;
FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.None);
using(StreamReader read = new StreamReader(fileStream))
text = read.ReadToEnd();
return text;
}
I'm trying to figure out why the context is turning up null here. I originally tried HttpContext.Current but current is coming up null so it can't find the current context in my Utility.cs method that sits in my MVC web project.
UPDATE:
Ok so the consensus is to use HttpRequestBase object and not the HttpContext.Current object. I still find it weird that the HttpContext.Current is null. But moving on, if my Utility.cs is outside any context of a controller or view, then how the heck do I get an instance of the current request (HttpRequestBase) to work with and send an instance that implements HttpRequestBase (I do not know what object that would be if I want to do this in the "MVC way" outside a controller or view) to this utility method?
No idea why this returns null but since it is a bad idea to tie your business layers with ASP.NET specifics I'd recommend you the following change to your method:
public static string GetFileData(string filePath)
{
if (!File.Exists(filePath))
throw new FileNotFoundException(String.Format("the file {0} was not found", filePath));
return File.ReadAllText(filePath);
}
and then when you need to consume it from a web application:
public ActionResult Foo()
{
var result = MyClass.GetFileData(Server.MapPath("~/foo/bar.txt"));
...
}
and when you need to consume it in a WinForms application:
protected void Button1_Click(object sender, EventArgs e)
{
var filePath = Path.Combine(Environment.CurrentDirectory, "bar.txt");
var result = MyClass.GetFileData(filePath);
...
}
In a utility class I would remove the dependency on any web-related stuff.
For a path relative to the application root I would use:
Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, fileName)
which will give you what you probably want (a path relative to the web root directory in a web application; relative to the path containing the executable in a WinForms app, ...)
If want to rewrite that method in asp.net mvc way, you could rewrite it this way and remove coupling with HttpContext class
public static string GetFileData(HttpRequestBase request, string filePath)
{
if (!File.Exists(request.PhysicalApplicationPath + filePath))
throw new FileNotFoundException(String.Format("the file {0} was not found", filePath));
string text;
FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.None);
using(StreamReader read = new StreamReader(fileStream))
text = read.ReadToEnd();
return text;
}
And generally in MVC HttpContext, HttpRequest and HttpResponse are abstracted into HttpContextBase, HttpRequestBase and HttpResponseBase accordingly

call birt report from action class

I am developing a project in Java EE Struts 2 and Hibernate for airline reservations. Now my all work is done and I have to generate a ticket. Instead of generating a simple JSP or HTML ticket, I want to generate a downloadable report (like Crystal Reports in Java). I have my entire ticket info in a session that (as on internet) I can get on BIRT report using script.
I am totally new to BIRT and wanted to know how I can generate a BIRT report or maybe call its execution engine from one of my action classes. Any ready example will be a great help.
I guess you're trying to send PDF ticket to customers. Please create your template and pass parameters using these lines:
ReportAdminServiceRemote birtAdmService = (ReportAdminServiceRemote)MXServer.getMXServer().lookup(“BIRTREPORT”);
byte[] abyte0 = birtAdmService .runReport(userInfo, reportName, appName, parameterData, filename, “pdf”);
Once you have the bytes generated you can do this way:
public String actionDownload() throws Exception{
response.setHeader("Cache-Control", "no-cache");
response.setHeader("Content-Disposition","attachment; filename=\"" + example.pdf+ "\"");
response.setHeader("Expires", "0");
response.setHeader("Cache-Control","must-revalidate, post-check=0, pre-check=0");
response.setHeader("Pragma", "public");
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ByteArrayInputStream bis = new ByteArrayInputStream(abyte0);
inputStream = bis;
return SUCCESS;
}
All the credits goes to authors on these pages:
http://www.maximonews.com/?p=65
http://www.coderanch.com/t/432713/Struts/Struts-Files-DownLoad-Streaming-as

Resources