jaxrs.ResteasyClient download file - client

Request a webAPI that gives me a ZIP file. Now my question:
How to download that file with jaxrs.ResteasyClient. Here is what I have but it does not work for me.
// In
Reader reader = client.target(url).request().get().readEntity(Reader.class);
BufferedReader bufferedReader = new BufferedReader(reader);
// Out
File out = new File("C:\\tmp\\test.zip");
FileWriter fileWriter = new FileWriter(out);
BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
String s = null;
while (true) {
s = bufferedReader.readLine();
if (s == null) {
break;
}
bufferedWriter.write(s);
}
bufferedWriter.flush();
bufferedWriter.close();
bufferedReader.close();
I have no idea if this makes sense, but I do not find any good documentation about reading a file instead of a bean object.

Resolved this issue by not using jaxrs.ResteasyClient. Apache HTTPClient was my friend!
private void getFileByURL(String url, String target) throws URISyntaxException, IOException {
HttpClientBuilder builder = HttpClients.custom().build();
CloseableHttpClient client = builder.build();
HttpResponse response = client.execute(new HttpGet(new URI(url)));
BufferedInputStream bufferedInputStream = new BufferedInputStream(response.getEntity().getContent());
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(new File(target)));
int inByte;
while ((inByte = bufferedInputStream.read()) != -1) {
bufferedOutputStream.write(inByte);
}
bufferedInputStream.close();
bufferedOutputStream.close();
EntityUtils.consume(response.getEntity());
}

Related

Using ByteArrayLengthHeaderSerializer with java.net.Socket client

I am trying to connect a simple java.net.Socket TCP client to a Spring Integration TCP server using a ByteArrayLengthHeaderSerializer.
Here is the relevant client code snippet:
Socket socket = null;
OutputStream out = null;
InputStream in = null;
try {
socket = new Socket(host, port);
out = new BufferedOutputStream(socket.getOutputStream());
in = new BufferedInputStream(socket.getInputStream());
byte[] lengthBuf = new byte[4];
int size = in.read(lengthBuf, 0, lengthBuf.length);
ByteArrayInputStream bis = new ByteArrayInputStream(lengthBuf);
ObjectInputStream ois = new ObjectInputStream(bis);
int dataSize = ois.readInt();
System.out.println("Got size: " + dataSize);
byte[] dataBuffer = new byte[dataSize];
int dataRead = in.read(dataBuffer, 0, dataBuffer.length);
bis = new ByteArrayInputStream(dataBuffer);
ois = new ObjectInputStream(bis);
String data = (String) ois.readObject();
System.out.println("read " + dataRead + " bytes, got data: " + data);
Here is the server side configuration:
#MessagingGateway(defaultRequestChannel="toTcp")
public interface Gateway {
void send(#Payload byte[] data, #Header(IpHeaders.CONNECTION_ID) String connectionId);
}
#Bean
public AbstractServerConnectionFactory serverFactory() {
AbstractServerConnectionFactory connectionFactory = new TcpNetServerConnectionFactory(port);
ByteArrayLengthHeaderSerializer serDeser = new ByteArrayLengthHeaderSerializer();
connectionFactory.setSerializer(serDeser);
connectionFactory.setDeserializer(serDeser);
return connectionFactory;
}
#Bean
public TcpReceivingChannelAdapter inboundAdapter(AbstractServerConnectionFactory connectionFactory) {
TcpReceivingChannelAdapter inbound = new TcpReceivingChannelAdapter();
inbound.setConnectionFactory(connectionFactory);
inbound.setOutputChannel(fromTcp());
return inbound;
}
and the calling code:
public void send(String data, String header) throws IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try (ObjectOutputStream oos = new ObjectOutputStream(bos)) {
System.out.println("data.length is " + data.length());
oos.writeObject(data);
byte[] bytes = bos.toByteArray();
gateway.send(bytes, header);
}
}
When I send the data (e.g. 'abc') I get (on the client side) this error:
invalid stream header: 0000000A
On the server side I get:
SoftEndOfStreamException: Stream closed between payloads
What am I doing wrong?
No - an ObjectOutputStream serializes java objects (and the input stream deserializes). You don't need a length header deserializer for that, just use a DefaultSerializer and DefaultDeserializer (from Spring Core) and don't add the header.
You are getting the error because the serialization adds more stuff at the beginning.
Or, if you are only sending a String, you can use String.getBytes() and send the length (4 bytes) followed by the byte[].

Adding InclusiveNamespaces with WSS4J

In a WS-Security header, I'd like to add InclusiveNamespaces like this but I do not know how:
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
<InclusiveNamespaces PrefixList="wsse oas soapenv urn urn1 urn2 urn3 urn4" xmlns="http://www.w3.org/2001/10/xml-exc-c14n#"/>
</ds:Transform>
Here is my code that creates the security header, how do I add the InclusiveNamespaces with WSS4J as seen in above XML snippet?
public static SOAPMessage signSoapMessage(SOAPMessage message,
String keystorePassword, String irsPrivateKeyPassword,
char[] passphrase) throws WSSecurityException {
PrivateKeyEntry privateKeyEntry = getPrivateKeyEntry(keystorePassword,
irsPrivateKeyPassword);
PrivateKey signingKey = privateKeyEntry.getPrivateKey();
X509Certificate signingCert = (X509Certificate) privateKeyEntry
.getCertificate();
final String alias = "signingKey";
final int signatureValidityTime = 3600; // 1hour in seconds
WSSConfig config = new WSSConfig();
config.setWsiBSPCompliant(false);
WSSecSignature builder = new WSSecSignature(config);
builder.setX509Certificate(signingCert);
builder.setUserInfo(alias, new String(passphrase));
builder.setUseSingleCertificate(true);
builder.setKeyIdentifierType(WSConstants.X509_KEY_IDENTIFIER);
builder.setDigestAlgo(WSConstants.SHA1);
builder.setSignatureAlgorithm(WSConstants.RSA_SHA1);
builder.setSigCanonicalization(WSConstants.C14N_EXCL_WITH_COMMENTS);
try {
Document document = toDocument(message);
WSSecHeader secHeader = new WSSecHeader();
//secHeader.setMustUnderstand(true);
secHeader.insertSecurityHeader(document);
WSSecTimestamp timestamp = new WSSecTimestamp();
timestamp.setTimeToLive(signatureValidityTime);
document = timestamp.build(document, secHeader);
List<WSEncryptionPart> parts = new ArrayList<WSEncryptionPart>();
WSEncryptionPart timestampPart = new WSEncryptionPart("Timestamp",
WSConstants.WSU_NS, "");
WSEncryptionPart aCATransmitterManifestReqDtlPart = new WSEncryptionPart(
"ACATransmitterManifestReqDtl",
"urn:us:gov:treasury:irs:ext:aca:air:7.0", "");
WSEncryptionPart aCABusinessHeaderPart = new WSEncryptionPart(
"ACABusinessHeader",
"urn:us:gov:treasury:irs:msg:acabusinessheader", "");
parts.add(timestampPart);
parts.add(aCATransmitterManifestReqDtlPart);
parts.add(aCABusinessHeaderPart);
builder.setParts(parts);
Properties properties = new Properties();
properties.setProperty("org.apache.ws.security.crypto.provider",
"org.apache.ws.security.components.crypto.Merlin");
Crypto crypto = CryptoFactory.getInstance(properties);
KeyStore keystore = KeyStore.getInstance("JKS");
keystore.load(null, passphrase);
keystore.setKeyEntry(alias, signingKey, passphrase,
new Certificate[] { signingCert });
((Merlin) crypto).setKeyStore(keystore);
crypto.loadCertificate(new ByteArrayInputStream(signingCert
.getEncoded()));
document = builder.build(document, crypto, secHeader);
updateSOAPMessage(document, message);
} catch (Exception e) {
// throw new
// WSSecurityException(WSSecurityException.Reason.SIGNING_ISSUE, e);
e.printStackTrace();
}
return message;
}
private static Document toDocument(SOAPMessage soapMsg)
throws TransformerConfigurationException, TransformerException,
SOAPException, IOException {
Source src = soapMsg.getSOAPPart().getContent();
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
DOMResult result = new DOMResult();
transformer.transform(src, result);
return (Document) result.getNode();
}
//https://svn.apache.org/repos/asf/webservices/wss4j/branches/WSS4J_1_1_0_FINAL/test/wssec/SOAPUtil.java
private static SOAPMessage updateSOAPMessage(Document doc,
SOAPMessage message)
throws Exception {
DOMSource domSource = new DOMSource(doc);
message.getSOAPPart().setContent(domSource);
return message;
}
EDIT WITH ANSWER
The above code is for v1.6.x of WSS4J and so the solution to above code is
WSSConfig config = new WSSConfig();
config.setWsiBSPCompliant(true);

Https request not working for android Application

Https request not waking on my machine for an android app while HTTP is working fine.
I did lot of goggling but can't find success.
public static String requestWithPostMethod(String url, String jsonData)
* throws
* ClientProtocolException, IOException
*/
{
//HttpURLConnection urlConnection;
String result = null;
try {
// Connect
URL newurl = new URL(url);
HttpURLConnection urlConnection = (HttpURLConnection) newurl.openConnection();
// urlConnection = createConnection(url);
urlConnection.setRequestMethod("POST");
urlConnection
.setRequestProperty("Content-Type", "application/json");
urlConnection.setRequestProperty("Accept", "application/json");
urlConnection.connect(); //here it return null exception
// Write
OutputStream outputStream = urlConnection.getOutputStream();
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(
outputStream, "UTF-8"));
writer.write(jsonData);
writer.close();
outputStream.close();
// Read
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(urlConnection.getInputStream(),
"UTF-8"));
String line = null;
StringBuilder sb = new StringBuilder();
while ((line = bufferedReader.readLine()) != null) {
sb.append(line);
}
bufferedReader.close();
// {"success":true,"result":[],"error":"","error_key":"email_validation_code"}
result = sb.toString();
} catch (UnsupportedEncodingException e) {
if (e != null) {
e.printStackTrace();
}
} catch (IOException e) {
if (e != null) {
e.printStackTrace();
}
}
return result;
}
It might be the issue with Server Certificates.

zoho books api: list items not working - java

when I call this list Item API in zoho books:
https://www.zoho.com/invoice/api/v3/settings/items/#list-items , the response is:
{"code":4,"message":"Invalid value passed for JSONString"}
How does API work
HTTP verbs are used to access the resources - GET, POST, PUT and DELETE. All parameters in the request should be form-urlencoded. For all the APIs you need to pass authtoken and organization_id. Input JSON string should be passed using JSONString parameter.
private void testZoho() {
JSONObject JSONString = new JSONObject();
JSONString.put("sort_column", "name");
String urlParameters ="authtoken=xxxxxx&organization_id=xxxxx";
urlParameters += "&JSONString=" + JSONString.toJSONString();
System.out.println("retJson1:\n" + urlParameters);
HttpURLConnection httpcon;
String url = "https://books.zoho.com/api/v3/items";
String data = urlParameters;
String result = null;
try{
//Connect
httpcon = (HttpURLConnection) ((new URL (url).openConnection()));
httpcon.setDoOutput(true);
String charset = "UTF-8";
httpcon.setRequestProperty("Accept-Charset", charset);
httpcon.setRequestProperty("Content-Type", "application/json;charset=" + charset);
httpcon.setRequestMethod("GET");
httpcon.connect();
//Write
OutputStream os = httpcon.getOutputStream();
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os, "UTF-8"));
writer.write(data);
writer.close();
os.close();
//Read
BufferedReader br = new BufferedReader(new InputStreamReader(httpcon.getInputStream(),"UTF-8"));
String line = null;
StringBuilder sb = new StringBuilder();
while ((line = br.readLine()) != null) {
sb.append(line);
}
br.close();
result = sb.toString();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("retJson1:\n" + result);
}
You need to pass all parameter as url parameter instead of writing in the stream. I have modified your code:
private void testZoho()
{
HttpURLConnection httpcon;
String url = "https://books.zoho.com/api/v3/items?authtoken=xxxx&organization_id=xxx&sort_column=name";
String result = null;
try
{
//Connect
httpcon = (HttpURLConnection) ((new URL(url).openConnection()));
httpcon.setDoOutput(true);
String charset = "UTF-8";
httpcon.setRequestProperty("Accept-Charset", charset);
httpcon.setRequestProperty("Content-Type", "application/json;charset=" + charset);
httpcon.setRequestMethod("GET");
httpcon.connect();
//Read
BufferedReader br = new BufferedReader(new InputStreamReader(httpcon.getInputStream(), "UTF-8"));
String line = null;
StringBuilder sb = new StringBuilder();
while((line = br.readLine()) != null)
{
sb.append(line);
}
br.close();
result = sb.toString();
}
catch(UnsupportedEncodingException e)
{
e.printStackTrace();
}
catch(IOException e)
{
e.printStackTrace();
}
System.out.println("retJson1:\n" + result);
}

httpclient garbling extended characters

I'm using httpclient to retrieve remote urls and need to grab things such as titles.
In some cases, I get garbled extended characters as in the case of this url
http://olhardigital.uol.com.br/noticia/bilionaria-mais-jovem-da-historia-quer-revolucionar-exames-de-sangue/43586
I've tried playing around with all sorts of settings, to no avail. Any suggestions? My config is as follows:
private CloseableHttpClient httpclient = RemotePageUtils.getThreadSafeClient();
public String processMethod(String url, OutputStream out) throws IOException, IllegalArgumentException{
[...]
BufferedReader in = null;
HttpEntity entity = null;
HttpGet httpget = null;
CloseableHttpResponse resp = null;
try {
httpget = new HttpGet(url);
resp = httpclient.execute(httpget);
entity = resp.getEntity();
String inLine;
in = new BufferedReader(new InputStreamReader(entity.getContent(),"UTF-8"));
while ((inLine = in.readLine()) != null) {
out.write(inLine.getBytes("UTF-8"));
}
} finally {
[...]
}
return null;
}
private static CloseableHttpClient getThreadSafeClient() {
SocketConfig socketConfig = SocketConfig.custom()
.setTcpNoDelay(true)
.build();
RequestConfig config = RequestConfig.custom()
.setConnectTimeout(3000)
.setSocketTimeout(7000)
.setStaleConnectionCheckEnabled(false)
.build();
List<Header> headers = new ArrayList<Header>();
headers.add(new BasicHeader("Accept-Charset","ISO-8859-1,US-ASCII,UTF-8,UTF-16;q=0.7,*;q=0.7"));
//accept gzipped
headers.add(new BasicHeader("Accept-Encoding","gzip,x-gzip,deflate,sdch"));
CloseableHttpClient client = HttpClientBuilder.create()
.setDefaultHeaders(headers)
.setDefaultRequestConfig(config)
.setDefaultSocketConfig(socketConfig)
.build();
return client;
}
You are blindly interpreting all downloaded pages as UTF-8, but the example link you gave is not in UTF-8, but ISO-8859-1.
An accented letter in ISO-8859-1 is one byte >=128, where in UTF-8 such bytes have to follow specific patterns, in other case they are treated as damaged.
But why are you decoding bytes you have downloaded, just to write bytes to a file?
Instead of:
in = new BufferedReader(new InputStreamReader(entity.getContent(),"UTF-8"));
while ((inLine = in.readLine()) != null) {
out.write(inLine.getBytes("UTF-8"));
}
and converting bytes to strings and back, you should just copy the bytes.
You can do it with Apache Commons IO:
import org.apache.commons.io.IOUtils;
IOUtils.copy(entity.getContent(), out);
or manually, with pure Java:
byte[] buf = new byte[16 * 1024];
int len = 0;
InputStream in = entity.getContent();
while ((len = in.read(buf)) >= 0) {
out.write(buf, 0, len);
}

Resources