How to send email with Freemarker template in Spring Boot app? - spring-boot

I am trying to send email with Freemarker template.
Code:
public String geContentFromTemplate(Map<String, Object> model) throws IOException, TemplateException {
StringWriter stringWriter = new StringWriter();
fmConfiguration.getTemplate("email-template.ftlh").process(model, stringWriter);
return stringWriter.getBuffer().toString();
}
public void sendEmailWithTemplate(String to, String subject, User user) {
MimeMessage mimeMessage = mailSender.createMimeMessage();
try {
MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage, true);
mimeMessageHelper.setSubject(subject);
mimeMessageHelper.setFrom(emailFrom);
mimeMessageHelper.setTo(to);
Map<String, Object> model = new HashMap<>();
model.put("firstName", user.getFirstName());
model.put("lastName", user.getLastName());
String content = geContentFromTemplate(model);
mimeMessageHelper.setText(content, true);
mailSender.send(mimeMessageHelper.getMimeMessage());
} catch (MessagingException | IOException | TemplateException e) {
e.printStackTrace();
}
}
Freemarker Bean:
#Bean
public FreeMarkerConfigurationFactoryBean getFreeMarkerConfiguration() {
FreeMarkerConfigurationFactoryBean fmConfigFactoryBean = new FreeMarkerConfigurationFactoryBean();
fmConfigFactoryBean.setTemplateLoaderPath("classpath:templates/email-template.ftlh");
return fmConfigFactoryBean;
}
My template is located in Spring Boot application: resources/templates/email-template.ftlh
I receive this exception:
freemarker.template.TemplateNotFoundException: Template not found for name "email-template.ftlh". The name was interpreted by this TemplateLoader: org.springframework.ui.freemarker.SpringTemplateLoader#33cceeb3.

I fixed that by changing #Bean. I removed previous one and created another:
#Bean
public FreeMarkerConfigurer freeMarkerConfigurer(){
freemarker.template.Configuration configuration = new freemarker.template.Configuration(freemarker.template.Configuration.VERSION_2_3_19);
TemplateLoader templateLoader = new ClassTemplateLoader(this.getClass(), "/templates/");
configuration.setTemplateLoader(templateLoader);
FreeMarkerConfigurer freeMarkerConfigurer = new FreeMarkerConfigurer();
freeMarkerConfigurer.setConfiguration(configuration);
return freeMarkerConfigurer;
}
Also template loading implemented like that:
Template template = freeMarkerConfigurer.getConfiguration().getTemplate("email-template.ftlh");
String htmlBody = FreeMarkerTemplateUtils.processTemplateIntoString(template, model);

Related

How to redirect ftl in spring boot?

I have already created an e mail confirmation in spring boot it is working nicely, and also I created a link when a user click it should say "confirmed"but I did not figure it out how to do that?
E mail sender java class:
#Component
public class EmailSender {
#Autowired
JavaMailSender javaEmailSender;
public void sendEmail(String to, String subject, String text) throws MessagingException {
MimeMessage message = javaEmailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(message,
MimeMessageHelper.MULTIPART_MODE_MIXED_RELATED,
StandardCharsets.UTF_8.name());
helper.setTo(to);
helper.setSubject(subject);
helper.setText(text, true);
helper.addInline("logo.jpg", new ClassPathResource("./images/logo.jpg"));
javaEmailSender.send(message);
}
}
E mail template Loader:
#Component
public class EmailTemplateLoader {
#Autowired
private Configuration freemakerConfiguration;
public String getEmailBody(String name, String confirmationLink) throws TemplateException {
try {
Template template = freemakerConfiguration.getTemplate("EmailConfirmation.ftl");
Map<String, Object> data = new HashMap<String, Object>();
data.put("name", name);
data.put("confirmationLink", confirmationLink);
return FreeMarkerTemplateUtils.processTemplateIntoString(template, data);
} catch (IOException e) {
e.printStackTrace();
} catch (TemplateException e) {
e.printStackTrace();
}
return "";
}
}
My signup Resource :
#Autowired
private SignupService signupService;
#Autowired
private HttpServletRequest httpServletRequest;
#RequestMapping(value = "user/signup", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
#Transactional(rollbackFor = Exception.class)
public ResponseEntity<?> signup(#RequestBody UserType user) throws SignUpException {
URL requestUrl = null;
try {
requestUrl = new URL(httpServletRequest.getRequestURL().toString());
} catch (MalformedURLException e) {
logger.debug("Malformed Request Url");
}
logger.debug(requestUrl.toString());
signupService.signUp(user, requestUrl.getHost());
return new ResponseEntity<>(HttpStatus.OK);
}
#RequestMapping(value = "user/confirmation", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
#Transactional(rollbackFor = Exception.class)
public ResponseEntity<?> confirmSignUp(#RequestParam("u") String loginName, #RequestParam("p") String token) {
try {
signupService.emailConfirmation(loginName, token);
return new ResponseEntity<>(HttpStatus.OK);
} catch (SignUpException e) {
return new ResponseEntity<>(e.getMessage(), HttpStatus.BAD_REQUEST);
}
}
So, As I told I can send an email successfully, but I could not sort how I can write confirmation successfully

How can I add information to a JAXBElement SOAP request?

I have a class generated with JAXB2 form a WSDL. The elements defined in the WSDL are NOT declared as XmlRootElement.
#Service
public class ProblemService extends WebServiceGatewaySupport {
public ProblemResponse addProblem(final Problem problem, final String aNumber) {
final String namespacePrefix = "soapenv";
final String action = "Problem";
final ObjectFactory factory = new ObjectFactory();
final JAXBElement<Problem> request = factory.createProblem(problem);
try {
StringResult result = new StringResult();
getMarshaller().marshal(request, result);
System.out.println(result.toString());
} catch (Exception e) {
e.printStackTrace(System.err);
}
final WebServiceTemplate wst = this.getWebServiceTemplate();
#SuppressWarnings("unchecked")
final JAXBElement<ProblemResponse> response = (JAXBElement<ProblemResponse>) wst
.marshalSendAndReceive(abcConfiguration.getEndpoint(), request, new WebServiceMessageCallback() {
#Override
public void doWithMessage(final WebServiceMessage message) {
try {
prepareSoapHeader(message, namespacePrefix, action);
final SaajSoapMessage ssMessage = (SaajSoapMessage) message;
final SOAPEnvelope envelope = ssMessage.getSaajMessage().getSOAPPart().getEnvelope();
envelope.getBody().setPrefix(namespacePrefix);
final NodeList nl = ssMessage.getSaajMessage().getSOAPPart().getEnvelope().getBody().getChildNodes();
ssMessage.getSaajMessage().getSOAPPart().getEnvelope().getBody().removeChild(nl.item(0));
final SOAPElement se = ssMessage.getSaajMessage().getSOAPPart().getEnvelope().getBody()
.addBodyElement(new QName(action));
se.setPrefix(NAMESPACE_PREFIX_V2);
addUserAuthentification(se);
try {
StringResult result = new StringResult();
getAbcConfiguration().marshaller().marshal(request, result);
System.out.println(result.toString());
} catch (Exception e) {
e.printStackTrace(System.err);
}
System.out.println();
} catch (SoapFaultClientException e) {
logger.error("Error on client side during marshalling of the SOAP request for {}.", action, e);
} catch (SOAPException e) {
logger.error("Error during marshalling of the SOAP request for {}.", action, e);
}
}
});
return response.getValue();
}
}
The generated StringResult looks quiet good but I need to replace some parts in the resulting XML (for instance the prefix) and I need to add some stuff into the SoapBody which are not part of the base class (Problem) before sending the SOAP request to the remote service.
Furthermore I want to modify the header part of the envelope...
How can I achieve this? My application is a SpringBoot application and in the configuration class being used in my service the un-/marshaller are defined this way:
#Bean
public Jaxb2Marshaller marshaller() {
final Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
//setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.setContextPath(contextPath);
//marshaller.afterPropertiesSet();
marshaller.setMarshallerProperties(new HashMap<String, Object>() {{
put(javax.xml.bind.Marshaller.JAXB_FORMATTED_OUTPUT, true);
}});
return marshaller;
}
#Bean
public ProblemService problemService(final Jaxb2Marshaller marshaller) throws Exception {
final ProblemService client = new ProblemService();
client.setDefaultUri(this.endpoint);
client.setMarshaller(marshaller);
client.setUnmarshaller(marshaller);
final HttpsUrlConnectionMessageSender msgSender = new HttpsUrlConnectionMessageSender();
client.setMessageSenders(new WebServiceMessageSender[] {msgSender, httpComponentsMessageSender()});
//client.setMessageSender(msgSender);
return client;
}
With this little piece of code I was able to add information to the SoapBody as demanded:
try {
getKpmConfiguration().marshaller().marshal(request, ssMessage.getPayloadResult());
ssMessage. writeTo(System.out);
} catch (/*JAXB*/Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}

Could not read freemarker template

My file is under
src/main/resources/freemarker/email_notification.txt
I am not able to read the freemaker file, that is email_notification.txt, which contain html file.
My Reference is from here: http://websystique.com/spring/spring-4-email-using-velocity-freemaker-template-library/
I have tried the velocity method but there is strikethrough in some of the words, thus i choose freemarker method instead.
#Transactional
#Service("EmailService")
public class EmailService{
#Autowired
JavaMailSender mailSender;
#Autowired
Configuration freemarkerConfiguration;
public void sendEmail(Map<String, Object> params) {
MimeMessagePreparator preparator = getMessagePreparator(params);
try {
mailSender.send(preparator);
System.out.println("Message has been sent.............................");
}
catch (MailException ex) {
System.err.println(ex.getMessage());
}
}
private MimeMessagePreparator getMessagePreparator(final Map<String, Object> params){
MimeMessagePreparator preparator = new MimeMessagePreparator() {
public void prepare(MimeMessage mimeMessage) throws Exception {
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
helper.setSubject(params.get("trnmaster").toString());
helper.setFrom("XXXXX#gmail.com");
helper.setTo("XXXXXX#hotmail.com");
String text = geFreeMarkerTemplateContent(params);//Use Freemarker or Velocity
System.out.println("Template content : "+text);
helper.setText(text, true);
}
};
return preparator;
}
public String geFreeMarkerTemplateContent(Map<String, Object> model){
StringBuffer content = new StringBuffer();
try{
content.append(FreeMarkerTemplateUtils.processTemplateIntoString(
freemarkerConfiguration.getTemplate("/email_notification.txt"),model));
return content.toString();
}catch(Exception e){
System.out.println("Exception occured while processing fmtemplate:"+e.getMessage());
}
return "";
}
}
part of the config file
#Bean
public FreeMarkerConfigurationFactoryBean getFreeMarkerConfiguration() {
FreeMarkerConfigurationFactoryBean bean = new FreeMarkerConfigurationFactoryBean();
bean.setTemplateLoaderPath("classpath:/freemarker/");
return bean;
}
Where you configure FreeMarker, you should use: bean.setTemplateLoaderPath("classpath:/freemarker/");
Also that example is quite strange. Why's the file extension txt? It should be ftlh for a HTML template (was ftl in older projects). Also I would definitely overwrite FreeMarkerConfigurationFactoryBean.postProcessConfiguration and do the recommended setup according to https://freemarker.apache.org/docs/pgui_quickstart_createconfiguration.html, except that you must not call setDirectoryForTemplateLoading, and maybe setDefaultEncoding is already set by Spring as well. It's important to ensure that you get automatic HTML escaping (incompatibleImprovements set to 2.3.24 or higher and the ftlh file extension does that).

Too many connection for Spring Boot Application and Apache storm

I am using spring boot application for websocket and in my storm project i am calling the spring boot application everytime to publish real time sensor data i,e per 5 minutes it is establishing 5000 connection so how to avoid this problem?
Is there any way to do connection pooling for spring boot connection in the Apache storm project?
String boot application controller class:
private static Logger logger=Logger.getLogger(GreetingController.class);
#MessageMapping("/hello")
#SendTo("/topic/greetings")
public Greeting greeting(HelloMessage message) throws Exception {
//logger.info("+++++++Sending Greetinge+++++++" + message);
//Thread.sleep(3000); // simulated delay
return new Greeting("Hello greetings, " + message.getName() + "!");
}
#MessageMapping("/orignal")
#SendTo("/topic/orignal")
public Map<String, Object> orignal(Map<String, Object> orignal) throws Exception {
// logger.info("+++++++Sending orignale+++++++" + orignal);
//System.out.println("Sending orignal");
//Thread.sleep(3000); // simulated delay
return orignal;
}
#MessageMapping("/tupple")
#SendTo("/topic/tupple")
public Map<String, Object> tupple(Map<String, Object> tupple) throws Exception {
logger.info("+++++++Sending tupple+++++++" + tupple);
//System.out.println("Sending tupple");
//Thread.sleep(3000); // simulated delay
//String company_name=(String) tupple.get("company_name");
/*Map<String, Object> companyMap=new HashMap<String, Object>();
companyMap.put("success", true);
companyMap.put("message", "company created successfully");*/
return tupple;
}
#MessageMapping("/websocket")
#SendTo("/topic/websocket")
public Map<String, Object> websocket(Map<String, Object> websocket) throws Exception {
logger.info("+++++++Sending websocket+++++++" + websocket);
//System.out.println("Sending websocket");
//Thread.sleep(3000); // simulated delay
return websocket;
}
In storm project making connection to spring boot application:
private final static WebSocketHttpHeaders headers = new WebSocketHttpHeaders();
public ListenableFuture<StompSession> connect(String endpoint) {
Transport webSocketTransport = new WebSocketTransport(new StandardWebSocketClient());
List<Transport> transports = Collections.singletonList(webSocketTransport);
SockJsClient sockJsClient = new SockJsClient(transports);
sockJsClient.setMessageCodec(new Jackson2SockJsMessageCodec());
WebSocketStompClient stompClient = new WebSocketStompClient(sockJsClient);
/*String url = "ws://{host}:{port}/"+endpoint;
return stompClient.connect(url, headers, new MyHandler(), "10.0.0.6", 8080);*/
String url = "ws://*************/IoTWebSocketServer-1.2.5.RELEASE/"+endpoint;
return stompClient.connect(url, headers, new MyHandler());
}
public void subscribeGreetings(String topic,StompSession stompSession) throws ExecutionException, InterruptedException {
stompSession.subscribe(topic, new StompFrameHandler() {
public Type getPayloadType(StompHeaders stompHeaders) {
return byte[].class;
}
public void handleFrame(StompHeaders stompHeaders, Object o) {
}
});
}
public void sendHello(StompSession stompSession,String message) {
String jsonHello = "{ \"name\" : \""+message+"\" }";
stompSession.send("/app/hello", jsonHello.getBytes());
}
private class MyHandler extends StompSessionHandlerAdapter {
public void afterConnected(StompSession stompSession, StompHeaders stompHeaders) {
}
}
public static void main(String[] args) throws Exception {
HelloClient helloClient = new HelloClient();
String endPoint = "hello";
ListenableFuture<StompSession> f = helloClient.connect(endPoint);
StompSession stompSession = f.get();
String topic= "/topic/greetings";
helloClient.subscribeGreetings(topic,stompSession);
String message = "hieeeeeeeeeeeeeeee message";
helloClient.sendHello(stompSession,message);
HelloClient helloClienttupple = new HelloClient();
String endPointtupple = "tupple";
ListenableFuture<StompSession> ftupple = helloClient.connect(endPointtupple);
StompSession stompSessiontupple = ftupple.get();
String topictupple= "/topic/tupple";
helloClient.subscribeGreetings(topictupple,stompSessiontupple);
String messagetupple = "hieeeeeeeeeeeeeeee tupple";
helloClienttupple.sendHello(stompSessiontupple,messagetupple);
JSONObject companyMap = new JSONObject();
companyMap.put("name", "Mahabali");
companyMap.put("num", new Integer(100));
companyMap.put("balance", new Double(1000.21));
companyMap.put("is_vip", new Boolean(true));
System.out.println(companyMap.toString());
stompSessiontupple.send("/app/tupple", companyMap.toString().getBytes());
//Thread.sleep(60000);
}
This the connection establishing code:
t
ry{
logger.info("++++Websocket Gateway packet++++" + topicId);
JSONObject jsonObject=new JSONObject();
JSONObject jsonObject1=new JSONObject();
JSONArray array=new JSONArray();
jsonObject.put("MAC_IMEI", topicId);
jsonObject.put("TIME", eventTime);
jsonObject.put("DEVICE", "GATEWAY");
jsonObject.put("GATEWAY", nJsonArray);
array.put(jsonObject);
jsonObject1.put("GATEWAY", array);
HelloClient helloClientwebsocket = new HelloClient();
String endPointwebsocket = "websocket";
ListenableFuture<StompSession> fwebsocket = helloClientwebsocket.connect(endPointwebsocket);
StompSession stompSessionwebsocket = fwebsocket.get();
String topicwebsocket= "/topic/websocket";
helloClientwebsocket.subscribeGreetings(topicwebsocket,stompSessionwebsocket);
stompSessionwebsocket.send("/app/websocket", jsonObject.toString().getBytes());
}
catch(Exception e)
{
logger.info("Gateway exception");
logger.error("++++Exception caught during sending the sensor details in the new websocket server++++"+e);
}

java.io.IOException With Restful Web Service

I have a weird problem with my project. When i run main method in Client to create a User after send to Server then occur fllowing error:
Exception in thread "main" java.io.IOException: Server returned HTTP
response code: 400 for URL: http://localhost:8080/rest/user/create at
sun.net.www.protocol.http.HttpURLConnection.getInputStream0(Unknown
Source) at
sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown
Source) at
edu.java.spring.service.client.RestClientTest.createUser(RestClientTest.java:72)
at
edu.java.spring.service.client.RestClientTest.main(RestClientTest.java:30)
Here file RestClientTest.java
public class RestClientTest {
public static void main(String[] args) throws IOException{
// System.out.println("Rest Response" + loadUser("quypham"));
User user = new User();
user.setUserName("datpham");
user.setPassWord("12345");
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.YEAR,1960);
user.setBirthDay(calendar.getTime());
user.setAge(12);
createUser(user);
System.out.println("Rest Response" + loadUser("datpham"));
}
public static String createUser(User user) throws IOException{
URL url = new URL("http://localhost:8080/rest/user/create");
HttpURLConnection httpConnection = (HttpURLConnection) url.openConnection();
httpConnection.setRequestMethod("POST");
httpConnection.addRequestProperty("Content-Type","application/json");
httpConnection.addRequestProperty("Accept","application/json");
httpConnection.setDoOutput(true);
DataOutputStream wr = new DataOutputStream(httpConnection.getOutputStream());
ObjectMapper mapper = new ObjectMapper();
StringWriter writer = new StringWriter();
mapper.writeValue(writer,user);
wr.writeBytes(writer.getBuffer().toString());
wr.flush();
wr.close();
return readInputStream(httpConnection.getInputStream());
}
public static String readInputStream(InputStream stream) throws IOException{
StringWriter writer = new StringWriter();
try {
int read;
byte[] bytes = new byte[4*1024];
while ((read = stream.read(bytes))!=-1) {
writer.write(new String(bytes,0,read));
}
} finally {
// TODO: handle finally clause
stream.close();
writer.close();
}
return writer.getBuffer().toString();
}
Here file UserRestServiceController.java
#Controller
public class UserRestServiceController {
#Autowired
public UserDao userDao;
#RequestMapping(value = "/rest/user/create",method = RequestMethod.POST,consumes = MediaType.APPLICATION_JSON_VALUE)
#ResponseStatus(HttpStatus.CREATED)
public void addUser(#RequestBody User user){
userDao.save(user);
}

Resources