email not send in spring - spring

I want to send an email with spring boot that's way I'm setting this configuration in my aplication.properties :
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.auth=true
spring.mail.host=xxxxx.hostgator.com
spring.mail.port=465
spring.mail.username=XXX#xxxx.com
spring.mail.password=XXXX
spring.mail.protocol=smtp
spring.mail.default-encoding=UTF-8
but the problem is when i test it with postman the request is always in the state "loading" :
when i test the function with an gmail account it works fin!
my fucntion :
public void sendPaimentEmail(String to, String subject, String text) {
MimeMessage message = emailSender.createMimeMessage();
try {
MimeMessageHelper helper = new MimeMessageHelper(message, true);
helper.setTo(to);
helper.setSubject(subject);
helper.setText(text, true);
FileSystemResource imageSignature = new FileSystemResource(new File(this.pathToSaveFile2 + "logo.png"));
if (null != imageSignature && imageSignature.exists()) {
helper.addInline("logo", imageSignature);
}
FileSystemResource file = new FileSystemResource(new File(this.pathToSaveFile2 + "historique.png"));
helper.addAttachment("Invoice", file);
this.emailSender.send(message);
} catch (Exception e) {
e.printStackTrace();
}
}

Related

Call RestApi endpoint resource from EJB

I have been looking around for sample code how to call a Restful service written in Spring boot (deployed in different server/ip) from an EJB client.
I couldn't find a simple example or reference to guide me on how to implement an EJB client that can call a restful service(deployed in different server/ip). Could you please point me to a document or example that shows or describe how the two can interface/talk to each other.
I need to call the endpoint by passing two header parameters for authentication, if authentication is success then only retrieve the details from Rest and send back the response to EJB client.
I use something like this, try
`public void calExternal() throws ProtocolException,
MalformedURLException,
IOException,
NoSuchAlgorithmException,
InvalidKeyException {
URL myurl = new URL("API END POINT URL");
ObjectMapper mapper = new ObjectMapper();
HttpURLConnection conn = (HttpURLConnection) myurl.openConnection();
conn.setUseCaches(false);
conn.setDoInput(true);
conn.setDoOutput(true);
String payLoad = mapper.writeValueAsString("your payload here");
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/json");
conn.setRequestProperty("AUTHORIZATION-TYPE", "HMAC");
try {
OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream());
wr.write(payLoad);
wr.flush();
InputStream in = null;
int responseCode = conn.getResponseCode();
if (responseCode == 200) {
in = conn.getInputStream();
} else {
in = conn.getErrorStream();
}
String encoding = conn.getContentEncoding() == null ? "UTF-8" : conn.getContentEncoding();
String response = IOUtils.toString(in, encoding);
} catch (Exception e) {
e.printStackTrace();
}
}

Add custom SoapHeader using SpringBoot

Using SoapUI I am able to send a request with a custom SOAP header like this:
<soap:Header>
<To xmlns="http://www.w3.org/2005/08/addressing">ws://xxx.com/PP/QM/GPMService/Vx</To>
<Action xmlns="http://www.w3.org/2005/08/addressing">http://xmldefs.xxx.com/PP/QM/GPMService/Vx/AbcService/GetServiceInfoRequest</Action>
<MessageID xmlns="http://www.w3.org/2005/08/addressing">ITEST-2018-04-16-0001</MessageID>
<Stage xmlns="http://xmldefs.xxx.com/Technical/Addressing/V1">ProdX</Stage>
</soap:Header>
and get a reasonable response.
I can't achieve this in my SpringBoot application.
I have a service extending WebServiceGatewaySupport:
#Service
public class AbcService extends WebServiceGatewaySupport{
private AbcConfiguration abcConfiguration;
#Autowired
public void setAbcConfiguration(final AbcConfiguration abcConfiguration) {
this.abcConfiguration = abcConfiguration;
}
public GetServiceInfoResponse GetServiceInfo() {
final String actionStr = "GetServiceInfo";
final ObjectFactory factory = new ObjectFactory();
GetServiceInfo getServiceInfo = factory.createGetServiceInfo();
JAXBElement<GetServiceInfo> gsiRequest = factory.createGetServiceInfo(getServiceInfo);
WebServiceTemplate wst = this.getWebServiceTemplate();
#SuppressWarnings("unchecked")
JAXBElement<GetServiceInfoResponse> gsiResponse = (JAXBElement<GetServiceInfoResponse>)wst
.marshalSendAndReceive("https://ws-gateway-cert.xxx.com/services/", gsiRequest, new WebServiceMessageCallback() {
#Override
public void doWithMessage(WebServiceMessage message) {
try {
SoapHeader soapHeader = ((SoapMessage) message).getSoapHeader();
SoapHeaderElement toElem = soapHeader.addHeaderElement(new QName("http://www.w3.org/2005/08/addressing", "To"));
toElem.setText("ws://xxx.com/PP/QM/GPMService/Vx");
...
} catch (Exception e) {
logger.error("Error during marshalling of the SOAP headers", e);
}
}
});
return gsiResponse.getValue();
}
}
What am I doing wrong? Can anybody tell me how I can do this?
Okay. I got it working so far and the SOAP XML looks as demanded and running the request (being generated form my SpringBoot app) in SoapUI I get the demanded result.
public GetServiceInfoResponse GetServiceInfo() {
final String actionStr = "GetServiceInfo";
final ObjectFactory factory = new ObjectFactory();
GetServiceInfo getServiceInfo = factory.createGetServiceInfo();
JAXBElement<GetServiceInfo> gsiRequest = factory.createGetServiceInfo(getServiceInfo);
WebServiceTemplate wst = this.getWebServiceTemplate();
#SuppressWarnings("unchecked")
JAXBElement<GetServiceInfoResponse> gsiResponse = (JAXBElement<GetServiceInfoResponse>)wst
.marshalSendAndReceive(kpmConfiguration.getEndpoint(), gsiRequest, new WebServiceMessageCallback() {
#Override
public void doWithMessage(WebServiceMessage message) {
System.out.println(message.toString());
try {
// get the header from the SOAP message
final SoapHeader soapHeader = ((SoapMessage) message).getSoapHeader();
final SaajSoapMessage ssMessage = (SaajSoapMessage)message;
final SOAPEnvelope envelope = ssMessage.getSaajMessage().getSOAPPart().getEnvelope();
System.out.println("envelope.getPrefix(): " + envelope.getPrefix());
envelope.removeNamespaceDeclaration("SOAP-ENV");
envelope.setPrefix(NAMESPACE_PREFIX_SOAP);
System.out.println("envelope.getPrefix(): " + envelope.getPrefix());
envelope.getBody().setPrefix(NAMESPACE_PREFIX_SOAP);
envelope.getHeader().setPrefix(NAMESPACE_PREFIX_SOAP);
envelope.addNamespaceDeclaration(NAMESPACE_PREFIX_SOAP, NAMESPACE_PREFIX_SOAP_DEF);
envelope.addNamespaceDeclaration(NAMESPACE_PREFIX_V2, NAMESPACE_PREFIX_V2_DEF);
envelope.addNamespaceDeclaration(NAMESPACE_PREFIX_WSSE, NAMESPACE_PREFIX_WSSE_DEF);
final SoapHeaderElement toElem = soapHeader.addHeaderElement(new QName(NAMESPACE_PREFIX_ADDRESSING, "To"));
toElem.setText(TO_VALUE);
final SoapHeaderElement actionElem = soapHeader.addHeaderElement(new QName(NAMESPACE_PREFIX_ADDRESSING, "Action"));
actionElem.setText(NAMESPACE_PREFIX_V2_DEF + "/AbcService/" + actionStr + "Request");
final SoapHeaderElement messageIdElem = soapHeader.addHeaderElement(new QName(NAMESPACE_PREFIX_ADDRESSING, "MessageID"));
messageIdElem.setText(MESSAGE_ID_VALUE + UUID.randomUUID());
final SoapHeaderElement stageElem = soapHeader.addHeaderElement(new QName(NAMESPACE_PREFIX_VWA, "Stage"));
stageElem.setText("Production");
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(actionStr));
se.setPrefix(NAMESPACE_PREFIX_V2);
final SOAPElement userAuthElem = se.addChildElement(new QName("UserAuthentification"));
final SOAPElement userIdElem = userAuthElem.addChildElement("UserId");
userIdElem.setTextContent(kpmConfiguration.getCredentials().getUsername());
System.out.println(userIdElem.getTextContent());
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.transform(ssMessage.getPayloadSource(), soapHeader.getResult());
} catch (Exception e) {
logger.error("Error during marshalling of the SOAP headers", e);
}
}
});
return gsiResponse.getValue();
}
However, when I submit the request from my SpringBoot app I always get an exception:
java.net.SocketException: Unexpected end of file from server
Am I missing something in the code?
See the answer to the original question above in the edited question.
Concerning the java.net.SocketException: Unexpected end of file from server it seemed to come from redirecting the request through Eclipse's TCP/IP Monitor. When sending the request directly to the server I get a meaningful response with:
INFO_001
Method compelted successfully
:-)

Java Exception getOutputStream() has already been called for this response while downloading file from backend

I have this code in order to download files from backend:
final File file = new File(filePath);
String fileType = Files.probeContentType(file.toPath());
response.setContentType(fileType);
response.setHeader("Content-disposition: attachment;", "filename=\"" + fileName + "\"");
response.setContentLength((int)new File(filePath).length());
final OutputStream os = response.getOutputStream();
IOUtils.copy(is, os);
response.flushBuffer();
os.flush();
os.close();
is.close();
and I get this exception in backend:
java.lang.IllegalStateException: getOutputStream() has already been called for this response
at org.apache.catalina.connector.Response.getWriter(Response.java:578)
at org.apache.catalina.connector.ResponseFacade.getWriter(ResponseFacade.java:212)
Does anyone know what I can do in order to prevent this exception?
As far as I know you shouldn't call flush and/or close on the response outputstream
Other way would be to delegate all to Spring controller
I always use this code and I never had problems
#RequestMapping(method = { RequestMethod.GET },
value = { "/file/{idFile}" })
public ResponseEntity<InputStreamResource> downloadCsv(
#PathVariable("idFile") String idFile) {
try {
File file = new File("yourFilePath");
HttpHeaders respHeaders = new HttpHeaders();
//Add your mediaType....mine was csv
MediaType mediaType = new MediaType("text","csv");
respHeaders.setContentType(mediaType);
respHeaders.setContentLength(file.length());
respHeaders.setContentDispositionFormData("attachment", file.getName());
InputStreamResource isr = new InputStreamResource(new FileInputStream(file));
return new ResponseEntity<InputStreamResource>(isr, respHeaders, HttpStatus.OK);
} catch (Exception e) {
String message = "Errore nel download del file "
+ idFile + ".csv; "
+ e.getMessage();
logger.error(message, e);
return new ResponseEntity<InputStreamResource>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
I hope this can be useful
Angelo

spring : get response as Multipart File from REST WebService

I am creating POC for RESTFUL Web service using Spring 4.0. Requirement is to receive MultipartFile as Response from REST WEB-Service.
REST Service Controller
#RequestMapping(value="/getcontent/file", method=RequestMapping.post)
public MultipartFile getMultipartAsFileAsObject() {
File file = new File("src/test/resources/input.docx");
FileInputStream input = new FileInputStream(file);
MultipartFile multipartFile = new MockMultipartFile("file",file.getName(),
"application/docx", IOUtils.toByteArray(input));
return multipartFile
}
I call this service using third party Clients and Apache Http Client as well. kindly have a look on output.
Using Third party REST client ie. Postman
output looks like Json -
{
"name" : "file",
"originalfilename" : "sample.docx",
"contentType" : "application/docx",
"content" : [
82,
101,
97,
100,
101,
32,
32,
.
.
.
.
.
]
}
Apache HTTP Client Sample code
private static void executeClient() {
HttpClient client = new DefaultHttpClient();
HttpPost postReqeust = new HttpPost(SERVER_URI);
try{
// Set Various Attributes
HttpResponse response = client.execute(postReqeust) ;
//Verify response if any
if (response != null)
{
InputStream inputStream = response.getEntity().getContent();
byte[] buffer = new byte[inputStream.available()];
inputStream.read(buffer);
OutputStream outputStream = new FileOutputStream
(new File("src/main/resource/sample.docx"));
outputStream.write(buffer);
outputStream.flush();
outputStream.close();
}
}
catch(Exception ex){
ex.printStackTrace();
}
Output of Apache Http client
file is getting Created but It is empty. (0 bytes).
I found some interesting answers from multiple stackoverflow questions.
Links are given below
file downloading in restful web services
what's the correct way to send a file from REST web service to client?
For Sending single file : (copied from above sources)
#GET
#Produces(MediaType.APPLICATION_OCTET_STREAM)
public Response getFile() {
File file = ... // Initialize this to the File path you want to serve.
return Response.ok(file, MediaType.APPLICATION_OCTET_STREAM)
.header("Content-Disposition", "attachment; filename=\"" + file.getName() + "\"" ) //optional
.build();
}
For Sending Zip file : (copied from above sources)
1) Approach First :
You can use above method to send any file / Zip.
private static final String FILE_PATH = "d:\\Test2.zip";
#GET
#Path("/get")
#Produces(MediaType.APPLICATION_OCTET_STREAM)
public Response getFile() {
File file = new File(FILE_PATH);
ResponseBuilder response = Response.ok((Object) file);
response.header("Content-Disposition", "attachment; filename=newfile.zip");
return response.build();
}
2) Approach Second :
#GET
#Path("/get")
#Produces(MediaType.APPLICATION_OCTET_STREAM)
public StreamingOutput helloWorldZip() throws Exception {
return new StreamingOutput(){
#Override
public void write(OutputStream arg0) throws IOException, WebApplicationException {
// TODO Auto-generated method stub
BufferedOutputStream bus = new BufferedOutputStream(arg0);
try {
Thread.currentThread().getContextClassLoader().getResource("");
File file = new File("d:\\Test1.zip");
FileInputStream fizip = new FileInputStream(file);
byte[] buffer2 = IOUtils.toByteArray(fizip);
bus.write(buffer2);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
}

How do I control Token Response Expiry time for google API access

I have problem extending the standard one hour for validity of google access token.
One part of my code is getting authorization from the user, using the GoogleAuthorizationCodeFlow as per Google recommendation. This works fine and gives me a TokenResponse that I persist to be used in an other part of the application where the user is not connected.
As per Google documentation, I thought that the "offline" access type in the flow would enable the TokenResponse to be usable as longer as the user doesnt revoke it. But apparently when I use this TokenReponse just after the user authorization, it works fine but when I use it after more than one hour, I get an "invalid credentials" sent back by Google.
Here is the code which creates the TokenResponse once the user has authorized it :
private HttpTransport HTTP_TRANSPORT;
private JacksonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
private static GoogleAuthorizationCodeFlow flow;
#PostConstruct
public void init() {
try {
HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();
} catch (GeneralSecurityException | IOException e) {
logger.info(String.format("Raised Exception while getting GoogleNetHttpTransport : %s", e.getMessage()));
e.printStackTrace();
}
flow = new GoogleAuthorizationCodeFlow.Builder(HTTP_TRANSPORT, JSON_FACTORY, APP_ID, APP_SECRET,
Collections.singleton(CalendarScopes.CALENDAR_READONLY)).setAccessType("offline").build();
}
#RequestMapping(value = Uris.GOOGLERD)
public ModelAndView googleCallBack(HttpServletRequest request, #RequestParam(value = "state", required = false) String state,
#RequestParam(value = "code", required = false) String code,
#RequestParam(value = "error", required = false) String error, Model model) {
DynSubscriber dynSubscriber = (DynSubscriber) request.getSession().getAttribute("dynSubscriber");
ModelAndView toReturn = new ModelAndView("confirmation");
toReturn.addObject("buttonLabel", "Accueil");
try {
AuthorizationCodeTokenRequest tokenRequest = flow.newTokenRequest(code);
TokenResponse tr = tokenRequest.setRedirectUri(request.getRequestURL().toString()).execute();
// Json Conversion of Token Response for future use
StringWriter jsonTrWriter = new StringWriter();
JsonGenerator generator = JSON_FACTORY.createJsonGenerator(jsonTrWriter);
generator.serialize(tr);
generator.flush();
generator.close();
//Persists google access info
dynSubOp.setSPConnexionInfo(dynSubscriber, jsonTrWriter.toString(), DynServiceProviderType.GOOGLECAL);
toReturn.addObject("message","Agenda Google autorisé");
} catch (IOException | DynServicesException e) {
logger.error(String.format("Exception raised in googleCallBack for subscriber %s : %s", dynSubscriber.buildFullName(), e.getMessage()),e);
toReturn.addObject("message", "Problème lors du processus d'autorisation google");
}
return toReturn;
}
}
And here is the offline code which uses this TokenReponse :
private com.google.api.services.calendar.Calendar calendarConnection;
public DynGoogleCalendarRetriever(String subid, String connectionInformation)
throws CalendarConnectionNotAuthorizedException {
TokenResponse tr;
try {
HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();
tr = JSON_FACTORY.fromString(connectionInformation, TokenResponse.class);
Credential c = new GoogleCredential().setFromTokenResponse(tr);
calendarConnection = new com.google.api.services.calendar.Calendar.Builder(HTTP_TRANSPORT, JSON_FACTORY, c)
.build();
} catch (IOException | GeneralSecurityException e) {
logger.error(String.format("Failure creating the credentials for subscriber id %s", subid), e);
throw new CalendarConnectionNotAuthorizedException(String.format(
"Failure creating the credentials for subscriber id %s", subid), e);
}
}
Looks like this was already answered in this other SO question.
To get the refresh token that enables what I want, I need to build the flow with a approval_prompt=force parameter (builder.setApprovalPrompt("force"))
As per the comment, this requires the offline access which is done in the flow initialization.
A complement however : the offline code in my question doesn't work as such although I copied and pasted it from google documentation (probably an older version). The Credential needs to use its Builder object.
Here is the fully functionnal offline code :
TokenResponse tr;
try {
HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();
tr = JSON_FACTORY.fromString(connectionInformation, TokenResponse.class);
Credential c = new GoogleCredential.Builder().setTransport(HTTP_TRANSPORT).setJsonFactory(JSON_FACTORY)
.setClientSecrets(APP_ID, APP_SECRET).build().setFromTokenResponse(tr);
calendarConnection = new com.google.api.services.calendar.Calendar.Builder(HTTP_TRANSPORT, JSON_FACTORY, c)
.build();
} catch (IOException | GeneralSecurityException e) {
logger.error(String.format("Failure creating the credentials for subscriber id %s", subid), e);
throw new CalendarConnectionNotAuthorizedException(String.format(
"Failure creating the credentials for subscriber id %s", subid), e);
}

Resources