Trasferring files and data with Jersey - java

I'm trying to develop some rest services with Jersey to upload and download files (something like a file manager). If my services produce/consume only File class as "application/octet-stream", like in the code below, they work.
#GET
#Produces("application/octet-stream")
public File getFile(String id) {
try {
File file = new File(System.getProperty("user.home"), id);
return file;
} catch (FileNotFoundException ex) {
Logger.getLogger(GenericResource.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(GenericResource.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
But if I try to transfer a custom object that contains a File field and some other data (FileEnvelope in the sample) I obtain an error.
#GET
#Produces("application/octet-stream")
public FileEnvelope getXml(String id) {
try {
File file = new File(System.getProperty("user.home"), id);
FileEnvelope fileEnvelope = new FileEnvelope(file, "text");
return fileEnvelope;
} catch (FileNotFoundException ex) {
Logger.getLogger(GenericResource.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(GenericResource.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
The error is
Caused by: com.sun.jersey.api.MessageException: A message body writer for Java class com.mycompany.restdemo.FileEnvelope, and Java type class com.mycompany.restdemo.FileEnvelope, and MIME media type application/octet-stream was not found
Where I'm wrong? Is this the right way to manage this case? My client could not be a "Jersey client".

Jersey has no idea how to serialize your domain object into an octet-stream unless you tell it how. In this case if you want to include extra information beyond the file data you should consider how the client should be expected to read it. You could:
Embed the information directly in the octet stream by creating your own MessageBodyWriter. The client would need to know where to look for this information in the resulting file.
Include the information as part of the HTTP response header using ResponseBuilder. The client would just need to know which response headers to check for the information.

You can send different types of data in one message using multipart/* media types. For example this article shows how: http://aruld.info/handling-multiparts-in-restful-applications-using-jersey/

Related

How to find which type a exchange Body in camel is?

I create a processor to download some files from an external source.
I do it, like this:
CamelContext context = exchange.getContext();
ProducerTemplate template=context.createProducerTemplate();
Object answer=null;
try {
answer=template.requestBodyAndHeaders(
uri,
"",
headers);
} catch (Exception e) {
....
} finally {
template.stop();
}
if (answer != null) {
/* Here I need to know, if it is a file, or an error-message */
}
The problem is, the request can be an error-message (String), or it is a stream (when file is found).
How can I check this?
Thank you for any help
UPDATE:
Code of the Route is easy:
from("http://domain.de/getDoc?Id=123")
to("file:docs")
Maybe just "instanceof" checks will help?

JIRA REST API , java request/response

that's my first question on stackoverflow ; i need to make a post request (using an inputBean/pojo class for needed paramaters) and get a response (using an outputBean/pojo class to map the json response) using the jira rest api , currently i'm using jersey to do the unmarshallowing thing with json and for annotations, here's the code :
public Resource create(CreateIssueRequest createIssueRequest) {
//creating the issue builder with project key and issuetype
IssueInputBuilder issueBuilder = new IssueInputBuilder(
createIssueRequest.getFields().getProject().getKey()
,createIssueRequest.getFields().getIssueType().getCodeName());
//setting issue fields using the inputBean
issueBuilder.setSummary(createIssueRequest.getFields().getSummary());
issueBuilder.setDescription(createIssueRequest.getFields().getDescription());
//requesting the issue creation method , BasicIssue contains the same fields as my outputbean , this whole thing is the request
BasicIssue issue = jiraClient.getClient().getIssueClient().createIssue(issueBuilder.build()).claim();
//creating the output bean
CreateIssueResponse createIssueResponse = new CreateIssueResponse(
issue.getId(),
issue.getKey(),
issue.getSelf());
try {
jiraClient.getClient().getMetadataClient().getStatus(new URI("localhost:8080/rest/api/2/issue"));
} catch (URISyntaxException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
Resource resource = new Resource();
try {
jiraClient.getClient().close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
resource.setData(createIssueResponse);
return resource;
}
what i managed to achieve using this code is creating an issue and obtaining the corresponding outputbean , what i would like instead is getting a Response instance like a jersey one , which has more information attached to it like the status of that response + the entity response (using this code the only thing i get is the entity) ; i've looked for something similar in the jira rest api but i found nothing .
i might have been unclear , if enyone is willing to help me , i'll be glad to clarify any doubts
api:https://developer.atlassian.com/jiradev/jira-apis/jira-rest-apis/jira-rest-api-tutorials/jira-rest-api-example-create-issue
i solved surrounding the "post request" with a try catch (when the request doesnt return 201 it throws that exception witch holds some useful data like
try{
issue = jiraClient.getClient().getIssueClient().createIssue(issueBuilder.build()).claim();
}catch(RestClientException e){
ErrorResource error = new ErrorResource();
error.setStatus(e.getStatusCode().get());
error.setDetail(e.getLocalizedMessage());
error.setTitle("An error occurred while creating the issue");
resource.setErrors(new ArrayList<ErrorResource>());
resource.getErrors().add(error);
return resource;
}
As you can see, the official JIRA REST Client abstracts away the response and only gives you the object(s) returned from it.
If you want to keep using the client you need to create a filter or an interceptor or something that catches the response before it gets to the Client.

Azure blob SAS and Localized file name

I am using jclouds APIs to upload files to azure blob but I could not find any way to generate SAS using jClouds APIs so using Azure APIs to create SAS for specific blob.
Problem I am facing is the file which i am trying to upload has localized characters in its name e.g. "Jérôme" which I have to encode and decode at specific level while uploading, I am making sure that at the time of SAS generation i am passing decoded(actual) name of file but I am not able to access the same using generated SAS.
PS. I have tried different combinations of encoding and decoding string(file name) in upload and SAS generation but all in vain.
Error I am getting is "No such blob exist" and in some case "signature validation failure"
can anyone guide me with appropriate approach for the same?
Please let me know in case code snippet is required.
UPLOAD:
try (BlobStoreContext context = ContextBuilder.newBuilder("azureblob")
.credentials(this.storeName, this.storeKey)
.buildView(BlobStoreContext.class)) {
final BlobStore store = context.getBlobStore();
payload.getContentMetadata().setContentLength(blobSize);
final Blob blob = store.blobBuilder(URLEncoder.encode(blobName, StorageConstants.UNICODE_FORMAT)).payload(payload).build();
logger.debug("Uploading...");
store.putBlob(this.containerName, blob);
logger.debug("Uploaded...");
return true;
} catch (IOException e) {
logger.error("IOException while uploading file to azure blob", e);
return false;
} catch (Exception e) {
logger.error("Exception while uploading file to azure blob", e);
return false;
}
SAS Generation
String url = "";
try
{
final CloudBlobContainer container = getUploadContainer();
final CloudBlockBlob blob = container.getBlockBlobReference(blobName);
url = blob.getUri() +"?"+ blob.generateSharedAccessSignature(getPolicy(), null);
} catch (StorageException e) {
logger.error("Storage Exception was encounter in generateAttachmentSasUrl() :", e);
} catch (InvalidKeyException e) {
logger.error("Invalid Key Exception was encountered in generateAttachmentSasUrl() :", e);
} catch (URISyntaxException e) {
logger.error("Problems creating an URI was encounter in generateAttachmentSasUrl() : ", e);
}
Please test with jclouds 2.0.0-SNAPSHOT. Many issues with URL encoding were fixed as part of JCLOUDS-217.

Java how to find out if a URL is http or https?

I am writing a web crawler tool in Java. When I type the website name, how can I make it so that it connects to that site in http or https without me defining the protocol?
try {
Jsoup.connect("google.com").get();
} catch (IOException ex) {
Logger.getLogger(LinkGUI.class.getName()).log(Level.SEVERE, null, ex);
}
But I get the error:
java.lang.IllegalArgumentException: Malformed URL: google.com
What can I do? Are there any classes or libraries that do this?
What I'm trying to do is I have a list of 165 Courses, each with 65 - 71 html pages with links all throughout them. I am writing a Java program to test if the link is broken or not.
You can write your own simple method to try both protocols, like:
static boolean usesHttps(final String urlWithoutProtocol) throws IOException {
try {
Jsoup.connect("http://" + urlWithoutProtocol).get();
return false;
} catch (final IOException e) {
Jsoup.connect("https://" + urlWithoutProtocol).get();
return true;
}
}
Then, your original code can be:
try {
boolean shouldUseHttps = usesHttps("google.com");
} catch (final IOException ex) {
Logger.getLogger(LinkGUI.class.getName()).log(Level.SEVERE, null, ex);
}
Note: you should only use the usesHttps() method once per URL, to figure out which protocol to use. After you know that, you should connect using Jsoup.connect() directly. This will be more efficient.

retrieve openID-url using openid4java

Consider the following code excerpt:
String openIDProviderURL = "https://www.google.com/accounts/o8/id";
try {
URI loc = getUI().getPage().getLocation();
List discoveries = manager.discover(openIDProviderURL);
DiscoveryInformation discovered = manager.associate(discoveries);
getUI().getSession().setAttribute("openid-disc", discovered);
AuthRequest authReq = manager.authenticate(discovered, "http://"+loc.getHost()+":"+loc.getPort()+loc.getPath());
FetchRequest fetch = FetchRequest.createFetchRequest();
authReq.addExtension(fetch);
System.out.println("DEST URL: "+authReq.getDestinationUrl(true));
getUI().getPage().setLocation(authReq.getDestinationUrl(true));
} catch (DiscoveryException ex) {
Logger.getLogger(NavigatorUI.class.getName()).log(Level.SEVERE, null, ex);
} catch (MessageException ex) {
Logger.getLogger(NavigatorUI.class.getName()).log(Level.SEVERE, null, ex);
} catch (ConsumerException ex) {
Logger.getLogger(NavigatorUI.class.getName()).log(Level.SEVERE, null, ex);
}
}
Authentication with Google works, however, can anyone tell me how to extract the actual openID-identifier-URL from the objects I'm using here? When the authentication succeeds, it lets me now by writing "INFO: Verification succeeded for: https://www.google.com/accounts/o8/id?blablabla", but so far, I haven't found a way to access this very URL in the program. Could someone help me out please?
PS: I have been going through older posts dealing with openID4java. However, they all deal with failed authentication and the likes, which for me isn't the problem. If this very question has been asked before, I apologise.

Categories

Resources