No suitable HttpMessageConverter found error while executing rest service that takes multipart parameters - spring-integration

I am using Spring Integration in my project. I am trying to execute a rest service which takes multipart/formdata input parameters. I am using int-http:outbound-gateway to execute rest service. The following is the code:
<int:channel id="PQcreateAttachment-Rest-Channel" />
<int:chain input-channel="PQcreateAttachment-Rest-Channel" output-channel="PQcreateAttachment-StoredProcedure-Router" >
<int:header-filter header-names="accept-encoding"/>
<int:service-activator ref="httpOutboundGatewayHandler" method="buildMultipartHttpOutboundGatewayRequest" />
<int-http:outbound-gateway url-expression="headers.restResourceUrl"
http-method-expression="headers.httpMethod"
extract-request-payload="true"
>
</int-http:outbound-gateway>
<int:service-activator ref="msgHandler" method="buildMessageFromExtSysResponse" />
</int:chain>
But I am getting the following error when I execute the above code.
Caused by: org.springframework.web.client.RestClientException: Could not write request: no suitable HttpMessageConverter found for request type [org.springframework.integration.message.GenericMessage] and content type [application/x-java-serialized-object]
at org.springframework.web.client.RestTemplate$HttpEntityRequestCallback.doWithRequest(RestTemplate.java:665)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:481)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:460)
at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:409)
at org.springframework.integration.http.outbound.HttpRequestExecutingMessageHandler.handleRequestMessage(HttpRequestExecutingMessageHandler.java:372)
... 121 more
Here is the java code that prepares my multipart request:
public Message<?> buildMultipartHttpOutboundGatewayRequest(Message<?> inMessage) throws Exception{
logger.debug(" ************** buildMultipartHttpOutboundGatewayRequest Start *************************");
String inMsgPayload = (String)inMessage.getPayload();
SOAXml soaXml = parseSOAXml(inMsgPayload);
String restURL = null;
String contentType = null;
String acceptHdr = null;
String userId = null;
String password = null;
String businessAreaName = null;
String typeName = null;
String attachmentLocation = null;
String httpMethod = null;
Message<?> outMessage = null;
MessageHeaders inMsgHdrs = null;
MessageBuilder<?> msgBuild = null;
String authorization = null;
//TODO: File location needs to be changed to standard one
String fileLocation = "C:\\source.xml";
//if we reach here means, it is AWD system
restURL = getAwdSOAService(soaXml);
Document document = XmlParserUtil.convertString2Document(inMsgPayload);
userId = XmlParserUtil.getNodeValue(document,"//userId");
password = XmlParserUtil.getNodeValue(document,"//PQcreateAttachment/password");
businessAreaName = XmlParserUtil.getNodeValue(document,"//businessAreaName");
typeName = XmlParserUtil.getNodeValue(document,"//typeName");
httpMethod = XmlParserUtil.getNodeValue(document,"//METHOD");
attachmentLocation = XmlParserUtil.getNodeValue(document,"//attachmentLocation");
//Construct source xml
//Creating document
Document sourceDocument = DocumentHelper.createDocument();
Element sourceInstance = sourceDocument.addElement("createSourceInstance");
sourceInstance.addAttribute("xmlns", "http://www.dsttechnologies.com/awd/rest/v1");
Element orderItem=sourceInstance.addElement("businessAreaName");
orderItem.setText("SAMPLEBA");
Element orderItemDesc=sourceInstance.addElement("typeName");
orderItemDesc.setText("SAMPLEST");
// create source xml file
XmlParserUtil.createXMLFileUsingDOM4J(sourceDocument, fileLocation);
authorization = getBasicAuthorization(userId,password);
Resource source = new ClassPathResource(fileLocation);
Resource attachment = new ClassPathResource(attachmentLocation);
Map<String, Object> multipartMap = new HashMap<String, Object>();
multipartMap.put("source", source);
multipartMap.put("attachment", attachment);
logger.info("Created multipart request: " + multipartMap);
inMessage = buildMessageForMultipart(multipartMap);
// contentType = csProps.getHttpAwdContentTypeValue();
acceptHdr = csProps.getHttpAwdAcceptTypeValue() ;
// authorization = getBasicAuthorization(soaXml.getUserid(),decriptPassword(soaXml.getPassword()));
inMsgHdrs = inMessage.getHeaders();
msgBuild = MessageBuilder.withPayload(inMessage).copyHeaders(inMsgHdrs);
msgBuild.removeHeader("Content-Encoding");
msgBuild.removeHeader("accept-encoding");
msgBuild.setHeader(csProps.getHttpUrlHdr(), restURL);
msgBuild.setHeader(csProps.getHttpMethodHdr(), httpMethod);
msgBuild.setHeader(csProps.getHttpAuthorizatonHdr(),authorization );
// msgBuild.setHeader(csProps.getHttpContentTypeHdr(), contentType);
// msgBuild.setHeader(csProps.getHttpAcceptTypeHdr(),acceptHdr);
outMessage = msgBuild.build();
logger.debug(" ************** buildHttpOutboundGatewayRequest End*************************");
logger.debug(outMessage);
logger.debug(" ************************************************************************");
return outMessage;
}
Any ideas on what's wrong here?

Your problem is because you wrap one message to another.
What your buildMessageForMultipart(multipartMap); does?
I'm sure the simple map as payload and those header would be enough.
Not sure what is the point to wrap one message to another.

Related

How add some content to Mockito mocked Pageable class?

I want testing pagination.
I want add some fake content to my Page mocked class.
How can I?
This is my test (refactoring it from a previous test), I'm using Junit5 and of course I get that No valut at JSON path $.content.lenght() and so on (of course, Page is empty):
/**
* index
*/
#WithMockUser("username")
#Test
void testCanIndex() throws Exception {
var transaction01 = BankAccountTransactionsControllerTest.validBankAccountTransactionsEntity(1L,
new BigDecimal(99.99), "First Transaction");
var transaction02 = BankAccountTransactionsControllerTest.validBankAccountTransactionsEntity(2L,
new BigDecimal(150.00), "Second Transaction");
var result = new ArrayList<BankAccountTransactionsEntity>();
result.add(transaction01);
result.add(transaction02);
Page<BankAccountTransactionsEntity> items = mock(Page.class);
when(bankAccountTransactionsService.index(0, 1, "id", "desc")).thenReturn(items);
mvc.perform(get("/api/v1/bank-account-transactions/")).andExpect(status().isOk())
.andExpect(jsonPath("$.content.length()", is(2))).andExpect(jsonPath("$[0].id", is(1)))
.andExpect(jsonPath("$.content[1].id", is(2))).andExpect(jsonPath("$[0].amount", is(new BigDecimal(99.99))))
.andExpect(jsonPath("$.content[1].amount", is(150)))
.andExpect(jsonPath("$.content[0].purpose", is("First Transaction")))
.andExpect(jsonPath("$.content[1].purpose", is("Second Transaction")))
.andExpect(jsonPath("$.content[0]", Matchers.hasKey("transactionDate")))
.andExpect(jsonPath("$.content[1]", Matchers.hasKey("transactionDate")));
}
Edit
I made a change, calling directly a PageImpl
#Test
void testCanIndex() throws Exception {
var transaction01 = BankAccountTransactionsControllerTest.validBankAccountTransactionsEntity(1L,
new BigDecimal(99.99), "First Transaction");
var transaction02 = BankAccountTransactionsControllerTest.validBankAccountTransactionsEntity(2L,
new BigDecimal(150.00), "Second Transaction");
var result = new ArrayList<BankAccountTransactionsEntity>();
result.add(transaction01);
result.add(transaction02);
Page<BankAccountTransactionsEntity> items = new PageImpl<>(result);
when(bankAccountTransactionsService.index(0, 1, "id", "desc")).thenReturn(items);
mvc.perform(get("/api/v1/bank-account-transactions/")).andExpect(status().isOk())
.andExpect(jsonPath("$.content.length()", is(2)));
}
But body returned is empty
MockHttpServletRequest:
HTTP Method = GET
Request URI = /api/v1/bank-account-transactions/
Parameters = {}
Headers = []
Body = null
Session Attrs = {}
Handler:
Type = com.bitbank.controllers.BankAccountTransactionsController
Method = com.bitbank.controllers.BankAccountTransactionsController#index(Integer, Integer, String, String)
Async:
Async started = false
Async result = null
Resolved Exception:
Type = null
ModelAndView:
View name = null
View = null
Model = null
FlashMap:
Attributes = null
MockHttpServletResponse:
Status = 200
Error message = null
Headers = [Vary:"Origin", "Access-Control-Request-Method", "Access-Control-Request-Headers", X-Content-Type-Options:"nosniff", X-XSS-Protection:"1; mode=block", Cache-Control:"no-cache, no-store, max-age=0, must-revalidate", Pragma:"no-cache", Expires:"0", X-Frame-Options:"DENY"]
Content type = null
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []

accessing data from service bus

I am trying to connect to servicebus and getting data from it, it seems since I've got the token I must reuse it evertime I make a request what's wrong with this code?here is the error I've got at the last
line The remote server returned an error: (401) Unauthorized.
//sample usage string mydata1 = string.Format(Constants.myData, brfId);
public static readonly myData= "https://sdgsdg.servicebus.windows.net/sgsdg/gdgsg/{0}";
//sample usage - string agendaByBriefingDetailIdURI = string.Format(Constants.myData2 BriefingID, accessCode);
public static readonly string myData2= "https://sdgsg.servicebus.windows.net/sdg/dgsg/{0}/{1}";
string SCOPE = "http://lalalalala.servicebus.windows.net/";
string WRAP_PASSWORD = "lalalalalala"
string WRAP_USERNAME = "lalalala";
string ACS_NAMESPACE = "lalalalala";
WebClient client = new WebClient();
client.BaseAddress = string.Format("https://{0}.accesscontrol.windows.net", ACS_NAMESPACE);
NameValueCollection values = new NameValueCollection();
values.Add("wrap_name", WRAP_USERNAME);
values.Add("wrap_password", WRAP_PASSWORD);
values.Add("wrap_scope", SCOPE);
// WebClient takes care of the URL Encoding
byte[] responseBytes = client.UploadValues("WRAPv0.9", "POST", values);
// the raw response from ACS
string response = Encoding.UTF8.GetString(responseBytes);
string token = response.Split('&').Single(x => x.StartsWith("wrap_access_token=", StringComparison.OrdinalIgnoreCase)).Split('=')[1];
string decodedToken = HttpUtility.UrlDecode(token);
string.Format("WRAP access_token=\"{0}\"", HttpUtility.UrlDecode(token));
WebClient webClient = new WebClient();
webClient.Headers["Authorization"] = string.Format("WRAP access_token=\"{0}\"", HttpUtility.UrlDecode(token));
string returnString = webClient.DownloadString(string.Format(mystaticre, 10));

ibm connections assigning file to folder

I have a problem when I try to assign a file with folder, the file and folder exist in the system but when I use the method for upload the folder of the file the response it's success but the file not figure into the folder.
I use the method
POST /basic/api/collection/{collection-id}/feed
in the collection-id I change for the folder UUID but don't works.
you know how assign a file to folder?
System.out.println("Uploading " + fileName + " in " + parentFolderName);
Abdera abdera = new Abdera();
Factory factory = abdera.getFactory();
Entry entry = factory.newEntry();
//Entry
entry.setTitle(parentFolderName);
entry.setId(parentFolderUUID);
InputStream in = req.getInputStream();
entry.setContent("application/pdf");
entry.setLanguage("en");
AbderaClient abderaClient = new AbderaClient(abdera);
abderaClient.addCredentials(Utils.configJson.getString("connectionsServerURL"), null, null, new UsernamePasswordCredentials(connectionsUser, connectionsPassword));
//Nonce
String nonceUrl = "https://connectionsww.demos.ibm.com/files/basic/api/nonce";
ClientResponse respNonce = abderaClient.get(nonceUrl);
StringWriter writerNonce = new StringWriter();
IOUtils.copy(respNonce.getInputStream(), writerNonce, "UTF-8");
String nonce = writerNonce.toString();
//Multipart-post options
RequestOptions options = abderaClient.getDefaultRequestOptions();
options.setSlug(parentFolderUUID);
options.setContentType("multipart/mixed");
options.setAcceptLanguage("en");
options.setHeader("X-Update-Nonce", nonce);
fileURL = fileURL + "?X-Update-Nonce=" + nonce;
ClientResponse resp = abderaClient.post(fileURL, entry);
based on the method signature, I think you are missing two items:
One
Content-Type header should be
Content-Type: application/atom+xml
Two payload of itemid (the id there is the id of the file I want in the folder/collection).
<feed xmlns="http://www.w3.org/2005/Atom">
<entry>
<itemId xmlns="urn:ibm.com/td">aca70bd1-0925-42c1-8196-b1c3042178a6</itemId>
</entry>
</feed>
I found the solution for the answer of #Paul, the final code it's there.
Abdera abdera = new Abdera();
Factory factory = abdera.getFactory();
Entry entry = factory.newEntry();
//Entry
entry.setUpdated(new java.util.Date());
entry.setTitle(parentFolderName);
entry.setId(parentFolderUUID);
InputStream in = req.getInputStream();
entry.setContent("application/atom+xml");
entry.setLanguage("en");
AbderaClient abderaClient = new AbderaClient(abdera);
abderaClient.addCredentials(Utils.configJson.getString("connectionsServerURL"), null, null, new UsernamePasswordCredentials(connectionsUser, connectionsPassword));
System.out.println("added abdera client credentials");
//Nonce
String nonceUrl = "https://connectionsww.demos.ibm.com/files/basic/api/nonce";
ClientResponse respNonce = abderaClient.get(nonceUrl);
StringWriter writerNonce = new StringWriter();
IOUtils.copy(respNonce.getInputStream(), writerNonce, "UTF-8");
String nonce = writerNonce.toString();
//Multipart-post options
RequestOptions options = abderaClient.getDefaultRequestOptions();
options.setSlug(parentFolderUUID);
options.setContentType("application/atom+xml");
options.setAcceptLanguage("en");
options.setHeader("itemId", docUUID);
fileURL = fileURL + "?itemId="+docUUID;
System.out.println("fileURL+++++: " + fileURL);
ClientResponse resp = abderaClient.post(fileURL, entry, options);

What is the PostFileWithRequest equivalent in ServiceStack's 'New API'?

I want to post some request values alongside the multipart-formdata file contents. In the old API you could use PostFileWithRequest:
[Test]
public void Can_POST_upload_file_using_ServiceClient_with_request()
{
IServiceClient client = new JsonServiceClient(ListeningOn);
var uploadFile = new FileInfo("~/TestExistingDir/upload.html".MapProjectPath());
var request = new FileUpload{CustomerId = 123, CustomerName = "Foo"};
var response = client.PostFileWithRequest<FileUploadResponse>(ListeningOn + "/fileuploads", uploadFile, request);
var expectedContents = new StreamReader(uploadFile.OpenRead()).ReadToEnd();
Assert.That(response.FileName, Is.EqualTo(uploadFile.Name));
Assert.That(response.ContentLength, Is.EqualTo(uploadFile.Length));
Assert.That(response.Contents, Is.EqualTo(expectedContents));
Assert.That(response.CustomerName, Is.EqualTo("Foo"));
Assert.That(response.CustomerId, Is.EqualTo(123));
}
I can't find any such method in the new API, nor any overrides on client.Post() which suggest that this is still possible. Does anyone know if this is a feature that was dropped?
Update
As #Mythz points out, the feature wasn't dropped. I had made the mistake of not casting the client:
private IRestClient CreateRestClient()
{
return new JsonServiceClient(WebServiceHostUrl);
}
[Test]
public void Can_WebRequest_POST_upload_binary_file_to_save_new_file()
{
var restClient = (JsonServiceClient)CreateRestClient(); // this cast was missing
var fileToUpload = new FileInfo(#"D:/test/test.avi");
var beforeHash = this.Hash(fileToUpload);
var response = restClient.PostFileWithRequest<FilesResponse>("files/UploadedFiles/", fileToUpload, new TestRequest() { Echo = "Test"});
var uploadedFile = new FileInfo(FilesRootDir + "UploadedFiles/test.avi");
var afterHash = this.Hash(uploadedFile);
Assert.That(beforeHas, Is.EqualTo(afterHash));
}
private string Hash(FileInfo file)
{
using (var md5 = MD5.Create())
{
using (var stream = file.OpenRead())
{
var bytes = md5.ComputeHash(stream);
return BitConverter.ToString(md5.ComputeHash(stream)).Replace("-", "").ToLower();
}
}
}
None of the old API was removed from the C# Service Clients, only new API's were added.
The way you process an uploaded file inside a service also hasn't changed.

Retrieve Image from Picture Library - REST

I am looking for some suggestion or sample around retrieving images (actual file, not URL), from a picture library using REST API.
Thanks for any input.
Task 1: Getting a List of Image libs on a given site
public static XmlNode GetPicLibListingXML(string imagingServiceURL)
{
Imaging wsImaging = new Imaging();
wsImaging.UseDefaultCredentials = true;
wsImaging.Url = imagingServiceURL;
XmlNode xnPicLibs = wsImaging.ListPictureLibrary();
return xnPicLibs;
}
Sample return XML:
<Library name="{3C1D52F5-5387-490A-9A2D-A9C99A208C00}" title="Tech Images" guid="3c1d52f5-5387-490a-9a2d-a9c99a208c00" url="Tech Images" xmlns="http://schemas.microsoft.com/sharepoint/soap/ois/" />
Task 2: Listing Images in a given library
public static XmlNode GetImageFileListing(string imagingServiceURL, string imageFileLibraryName)
{
Imaging wsImaging = new Imaging();
ImageInfo curImageInfo = new ImageInfo();
wsImaging.UseDefaultCredentials = true;
wsImaging.Url = imagingServiceURL;
XmlNode xnListItems = wsImaging.GetListItems(imageFileLibraryName, "");
return xnListItems;
}
Task 3: Download Image(s)
private const string ATTR_FILENAME = "name";
private const string FILENAMESPACEURI = "http://schemas.microsoft.com/sharepoint/soap/ois/";
public static bool DownloadImageFiles(string imagingServiceURL, string imageFileLibraryName, string[] fileNames, string saveToFolder)
{
Imaging wsImaging = new Imaging();
wsImaging.UseDefaultCredentials = true;
wsImaging.Url = imagingServiceURL;
XmlElement parent = (XmlElement)wsImaging.Download(imageFileLibraryName, string.Empty, fileNames, 0, true);
XmlNodeList files = parent.GetElementsByTagName("File", FILENAMESPACEURI);
foreach (XmlNode file in files)
{
if (Directory.Exists(saveToFolder) == false)
{
Directory.CreateDirectory(saveToFolder);
}
byte[] fileBytes = Convert.FromBase64String(file.InnerText);
using (FileStream fs = File.OpenWrite(saveToFolder + file.Attributes[ATTR_FILENAME].Value))
{
BinaryWriter writer = new BinaryWriter(fs);
writer.Write(fileBytes);
writer.Close();
}
}
return true;
}
Note:
Imaging() class is a web reference to imagining.asmx
The Download call natively returns XML so yo uneed to run it through a conversion to byte
If you need to get a reference on the Imagine web service check this on out on MSDN:
http://msdn.microsoft.com/en-us/library/imaging.imaging.aspx
source:
http://gourangaland.wordpress.com/2008/05/30/using-the-moss-imaging-web-service-to-download-imagesimaging-asmx/

Resources