Java class
package voteHandler.Org.RSPSVote;
/*
* Author: Sieu Phan
* Website: RSPS Vote
* Data: 5/7/2014
* Version: 1.1
*/
import java.io.IOException;
import java.net.URL;
import org.apache.commons.io.IOUtils;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;
import org.json.simple.parser.ParseException;
public class voteHandler {
private static String SERVER = "";
private static String API_KEY = "";
public voteHandler(String SERVER_TO_SET, String API_KEY_TO_SET)
{
SERVER = SERVER_TO_SET;
API_KEY = API_KEY_TO_SET;
}
/*
Sends a GET request to RSPS Vote API.
RETURNS: a boolean
*/
public static boolean authenticate(String AUTH)
{
String url = generateURL(AUTH);
try {
String getJSON = IOUtils.toString(new URL(url));
JSONObject message = (JSONObject) JSONValue.parseWithException(getJSON);
String messageData = (String) message.get("MESSAGE");
System.out.println(messageData);
int responseData = Integer.parseInt((String) message.get("RESPONSE"));
System.out.println(responseData);
if(responseData == 5)
return true;
} catch (IOException | ParseException e) {
e.printStackTrace();
}
return false;
}
public static boolean getReward(String AUTH)
{
String url = generateURL(AUTH);
return false;
}
/*
Generates the url to the API
RETURNS: a String
*/
private static String generateURL(String AUTH)
{
String URL = "http://rspsvote.com/widget/api.php?"
+ "action=check"
+ "&server=" + SERVER
+ "&key=" + API_KEY
+ "&auth=" + AUTH;
return URL;
}
}
Testing class
import voteHandler.Org.RSPSVote.voteHandler;
public class testing {
public static void main(String args[])
{
voteHandler vote = new voteHandler("l6DZw", "ELWXQ-MI4BC-3K1RT-VUKPT-DGL2U");
vote.authenticate("Ptpz1n");
}
}
what's wrong with this JSON format being returned from the site?
http://rspsvote.com/widget/api.php?key=ELWXQ-MI4BC-3K1RT-VUKPT-DGL2U&action=check&auth=Ptpz1n&server=l6DZw
Also this is the error I get from eclipse:
Unexpected character (<) at position 63.
at org.json.simple.parser.Yylex.yylex(Yylex.java:610)
at org.json.simple.parser.JSONParser.nextToken(JSONParser.java:269)
at org.json.simple.parser.JSONParser.parse(JSONParser.java:118)
at org.json.simple.parser.JSONParser.parse(JSONParser.java:81)
at org.json.simple.parser.JSONParser.parse(JSONParser.java:75)
at org.json.simple.JSONValue.parseWithException(JSONValue.java:78)
at voteHandler.Org.RSPSVote.voteHandler.authenticate(voteHandler.java:34)
at testing.main(testing.java:8)
what's wrong with this JSON format being returned from the site?
It doesn't return JSON. The response's content type is text/html and the body contains
{"RESPONSE":"7","MESSAGE":"AUTHENTICATION WAS UNSUCCESSFUL."}
<!-- Hosting24 Analytics Code -->
<script type="text/javascript" src="http://stats.hosting24.com/count.php"></script>
<!-- End Of Analytics Code -->
You'll need to get rid of the XML or stop parsing after the JSON.
Related
Hi All i have created a global exception handler in my spring boot app and writing the exception occurred in AWS cloudwatch below code working fine i am able to write the exception in cloudwatch but the challenge is i am unable to get the Restcontroller name and service path from where the the particular exception happened.
Sample java service
#GetMapping(value = "DynamoDb/deleteTable")
public String deleteTable(#RequestParam String TableName) throws InterruptedException {
Table table = dynamoDB.getTable(TableName);
try {
table.delete();
table.waitForDelete();
} catch (Exception e) {
throw e;
}
return "Success";
}
When ever exception occurred it control transferred to controlleradvice global exception handler
Here is my code
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.cloudwatchlogs.CloudWatchLogsClient;
import software.amazon.awssdk.services.cloudwatchlogs.model.DescribeLogStreamsRequest;
import software.amazon.awssdk.services.cloudwatchlogs.model.DescribeLogStreamsResponse;
import software.amazon.awssdk.services.cloudwatchlogs.model.InputLogEvent;
import software.amazon.awssdk.services.cloudwatchlogs.model.PutLogEventsRequest;
import java.util.Arrays;
#ControllerAdvice
public class ExceptionControllerAdvice {
#ExceptionHandler(Exception.class)
public ResponseEntity<ErrorResponse> exceptionHandler(Exception ex) {
ErrorResponse error = new ErrorResponse();
error.setErrorCode(HttpStatus.INTERNAL_SERVER_ERROR.value());
error.setMessage(ex.getMessage());
error.setController(ex.getMessage());
error.setService(ex.getMessage());
error.setTimestamp(System.currentTimeMillis());
PutLogEvents(error);
return new ResponseEntity<ErrorResponse>(error, HttpStatus.OK);
}
public static void PutLogEvents(ErrorResponse Er)
{
String regionId = "us-east-1";
String logGroupName = "xxxxxxx";
String logStreamName = "xxxxxxx";
CloudWatchLogsClient logsClient = CloudWatchLogsClient.builder().region(Region.of(regionId)).build();
// A sequence token is required to put a log event in an existing stream.
// Look up the stream to find its sequence token.
String sequenceToken = getNextSequenceToken(logsClient, logGroupName, logStreamName);
// Build a JSON log using the EmbeddedMetricFormat.
String message = "[{" +
" \"Timestamp\": " + Er.getTimestamp() + "," +
" \"ErrorCode\": " + Er.getErrorCode() + "," +
" \"ControllerName\": " + Er.getErrorCode() + "," +
" \"ServiceName\": " + Er.getErrorCode() + "," +
" \"ErrorMsg\": " + Er.getErrorCode() + "" +
"}]";
InputLogEvent inputLogEvent = InputLogEvent.builder()
.message(message)
.timestamp(Er.getTimestamp())
.build();
// Specify the request parameters.
PutLogEventsRequest putLogEventsRequest = PutLogEventsRequest.builder()
.logEvents(Arrays.asList(inputLogEvent))
.logGroupName(logGroupName)
.logStreamName(logStreamName)
// Sequence token is required so that the log can be written to the
// latest location in the stream.
.sequenceToken(sequenceToken)
.build();
logsClient.putLogEvents(putLogEventsRequest);
}
private static String getNextSequenceToken(CloudWatchLogsClient logsClient, String logGroupName, String logStreamName) {
DescribeLogStreamsRequest logStreamRequest = DescribeLogStreamsRequest.builder()
.logGroupName(logGroupName)
.logStreamNamePrefix(logStreamName)
.build();
DescribeLogStreamsResponse describeLogStreamsResponse = logsClient.describeLogStreams(logStreamRequest);
// Assume that a single stream is returned since a specific stream name was
// specified in the previous request.
return describeLogStreamsResponse.logStreams().get(0).uploadSequenceToken();
}
}
Errorresponse.class
public class ErrorResponse {
private int errorCode;
private String message;
private String Controller;
private String Service;
private String ProjectName;
private long Timestamp;
public ErrorResponse(int errorCode, String message, String controller, String service, String projectName, long timestamp) {
this.errorCode = errorCode;
this.message = message;
Controller = controller;
Service = service;
ProjectName = projectName;
Timestamp = timestamp;
}
public ErrorResponse() {
}
#Override
public String toString() {
return "ErrorResponse{" +
"errorCode=" + errorCode +
", message='" + message + '\'' +
", Controller='" + Controller + '\'' +
", Service='" + Service + '\'' +
", ProjectName='" + ProjectName + '\'' +
", Timestamp=" + Timestamp +
'}';
}
public int getErrorCode() {
return errorCode;
}
public void setErrorCode(int errorCode) {
this.errorCode = errorCode;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public String getController() {
return Controller;
}
public void setController(String controller) {
Controller = controller;
}
public String getService() {
return Service;
}
public void setService(String service) {
Service = service;
}
public String getProjectName() {
return ProjectName;
}
public void setProjectName(String projectName) {
ProjectName = projectName;
}
public long getTimestamp() {
return Timestamp;
}
public void setTimestamp(long timestamp) {
Timestamp = timestamp;
}
}
Could any one please help me how can i get the Restcontroller name and service path in Global exception handler?
Hi All Thanks to all by using below code i am able to get the result as suggested by client. Hope this may help some one. Thanks
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.MethodParameter;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.method.HandlerMethod;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.cloudwatchlogs.CloudWatchLogsClient;
import software.amazon.awssdk.services.cloudwatchlogs.model.DescribeLogStreamsRequest;
import software.amazon.awssdk.services.cloudwatchlogs.model.DescribeLogStreamsResponse;
import software.amazon.awssdk.services.cloudwatchlogs.model.InputLogEvent;
import software.amazon.awssdk.services.cloudwatchlogs.model.PutLogEventsRequest;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.AnnotatedType;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Arrays;
#ControllerAdvice
public class ExceptionControllerAdvice {
private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MMM-dd HH:mm:ss");
#Value("${application.name}")
private String applicationName;
#Value("${aws.logGroupName}")
private String logGroupName;
#Value("${aws.logStreamName}")
private String logStreamName;
#ExceptionHandler(Exception.class)
public ResponseEntity<ErrorResponse> exceptionHandler(Exception ex, HandlerMethod handlerMethod, HttpServletRequest request) throws JsonProcessingException {
Class ControllerName = handlerMethod.getMethod().getDeclaringClass();
String MethodName = handlerMethod.getMethod().getName();
ErrorResponse error = new ErrorResponse();
error.setErrorCode(HttpStatus.INTERNAL_SERVER_ERROR.value());
error.setErrorMessage(ex.getMessage());
error.setControllerName(ControllerName.toString());
error.setServiceName(MethodName.toString());
error.setTimeStamp(sdf.format(System.currentTimeMillis()));
error.setProjectName(applicationName);
error.setServicePath(request.getRequestURL().toString());
PutLogEvents(error);
return new ResponseEntity<ErrorResponse>(error, HttpStatus.OK);
}
public void PutLogEvents(ErrorResponse Er) throws JsonProcessingException {
String regionId = "xxxxx";
String logGroupName = "xxxxx";
String logStreamName = "xxxxx";
CloudWatchLogsClient logsClient = CloudWatchLogsClient.builder().region(Region.of(regionId)).build();
// A sequence token is required to put a log event in an existing stream.
// Look up the stream to find its sequence token.
String sequenceToken = getNextSequenceToken(logsClient, logGroupName, logStreamName);
// Build a JSON log using the EmbeddedMetricFormat.
ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter();
String json = ow.writeValueAsString(Er);
String message =json;
InputLogEvent inputLogEvent = InputLogEvent.builder()
.message(message)
.timestamp(System.currentTimeMillis())
.build();
// Specify the request parameters.
PutLogEventsRequest putLogEventsRequest = PutLogEventsRequest.builder()
.logEvents(Arrays.asList(inputLogEvent))
.logGroupName(logGroupName)
.logStreamName(logStreamName)
// Sequence token is required so that the log can be written to the
// latest location in the stream.
.sequenceToken(sequenceToken)
.build();
logsClient.putLogEvents(putLogEventsRequest);
}
private static String getNextSequenceToken(CloudWatchLogsClient logsClient, String logGroupName, String logStreamName) {
DescribeLogStreamsRequest logStreamRequest = DescribeLogStreamsRequest.builder()
.logGroupName(logGroupName)
.logStreamNamePrefix(logStreamName)
.build();
DescribeLogStreamsResponse describeLogStreamsResponse = logsClient.describeLogStreams(logStreamRequest);
// Assume that a single stream is returned since a specific stream name was
// specified in the previous request.
return describeLogStreamsResponse.logStreams().get(0).uploadSequenceToken();
}
}
Result should be like this
{
"errorMessage": "Table already exists: ProductFgh (Service: AmazonDynamoDBv2; Status Code: 400; Error Code: ResourceInUseException; Request ID: 6S14VS0E6ESUMG55DL937IC42JVV4KQNSO5AEMVJF66Q9ASUAAJG)",
"timeStamp": "2020-Jan-22 11:53:58",
"errorCode": 500,
"projectName": "DynamoDB",
"servicePath": "http://localhost:8090/DynamoDb/createTable",
"controllerName": "class com.example.DynamoDB.DynamoDBController",
"serviceName": "createExampleTable"
}
As of now i have achieved this through above code if any better approach is available let me know. Thanks to all
You can get the class name from which the exception was thrown as follows:
ex.getStackTrace()[0].getClassName();
I'm parsing XML files and adding a new field named <description> to each file with value crawled from the GoodReads.com website using its API. The code successfully crawls book details (when ISBN matches at GoodReads.com). Using the developer key (provided by GoodReads.com) I am allowed to crawl 1000 books a day but the service does not allow me to download these at one time. Normally, after crawling 20 or more books, it stops allowing to access books by returning 404 or 403 status. Please help!
I have already contacted GoodReads.com developer team to allow me more than 1000 books for the dataset I am using in my research experiments but they haven't responded yet. But here, the problem is, even I cannot crawl 1000 books simultaneously.
Here is the code I am using to crawl books (by calling from the main program):
import java.io.BufferedReader;
import java.io.InputStreamReader;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
public class GoodReadsCrawler {
private static final String API_KEY = "some key";
private static final String ISBN_TO_ID_URL = "https://www.goodreads.com/book/isbn_to_id?key=" + API_KEY;
private static final String BOOK_DETAILS_URL = "https://www.goodreads.com/book/show/";
public static void main(String[] args) {
// TODO: Change "1856058387" to any valid ISBN 1933705000
// String bookId = isbnToId("1856058387");
// String bookId = isbnToId("1933705000");
// print("Book Id: " + bookId);
// String bookData = getBookDescription(bookId);
// print("Description tag: " + bookData);
}
private static void print(String msg) {
System.out.println(msg);
}
// private static String isbnToId(String isbn) {
public static String isbnToId(String isbn) {
try {
print("Getting id of " + isbn);
String requestUrl = ISBN_TO_ID_URL + "&isbn=" + isbn;
HttpClient client = new DefaultHttpClient();
HttpGet getRequest = new HttpGet(requestUrl);
HttpResponse response = client.execute(getRequest);
BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
StringBuffer result = new StringBuffer();
String line = "";
while ((line = rd.readLine()) != null) {
result.append(line);
}
return result.toString();
} catch (Exception e) {
e.printStackTrace();
return "";
}
}
// private static String getBookDescription(String bookId) {
public static String getBookDescription(String bookId) {
try {
print("Getting book data...");
String bookUrl = BOOK_DETAILS_URL + bookId;
Document documment = Jsoup.connect(bookUrl).get();
Element descriptionTag = documment.getElementById("description");
return descriptionTag.getElementsByTag("span").last().text();
} catch (Exception e) {
e.printStackTrace();
return "Error: " + e.getMessage();
}
}
}
I am trying to use Eventful API to get a list of events nearby but wasn't able to get any result with the request.
Does anyone know what is the problem here?
This is my JSON request: String url_request = "http://eventful.com/json/events?q=music&l=Singapore&api_key=" + API_KEY;
This is my current output :
{"sponsored_search_data":null,"location":{"geo_ip_fail":"0","location_type":null,"location_id":null,"geo_ip_guess":null,"meta_name":"Worldwide","pretty_name":"Worldwide"},"localized_base_url":"http://eventful.com","is_default_eventful_site":"1","facebook_app_namespace":"eventful","home_url":"/"}
package EventTest.EventTest;
import java.io.IOException;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.Response;
public class App
{
private static final String API_KEY = "my_api_key";
OkHttpClient client = new OkHttpClient();
public static void main( String[] args ) throws IOException
{
App request = new App();
String url_request = "http://eventful.com/json/events?q=music&l=Singapore&api_key=" + API_KEY;
String response = request.run(url_request);
System.out.println(response);
}
public String run(String url) throws IOException {
Request request = new Request.Builder().url(url).build();
Response response = client.newCall(request).execute();
return response.body().string();
}
}
Manage to obtain desired result by changing the JSON request :
String url_request =
"http://api.eventful.com/json/events/search?keywords=music&location=Singapore&app_key=my_app_key";
I am building a CXF (version 2.7.4) client that calls a WS-Security enabled web service. It uses BinarySecurityToken, encryption and signing. I got CXF working for the "regular" SOAP calls, but when the response comes back as MTOM, I end up getting weird errors in the client:
org.apache.cxf.binding.soap.SoapFault: The signature or decryption was invalid
at org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor.createSoapFault(WSS4JInInterceptor.java:778)
at org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor.handleMessage(WSS4JInInterceptor.java:334)
at org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor.handleMessage(WSS4JInInterceptor.java:96)
...
Caused by: org.apache.xml.security.encryption.XMLEncryptionException: Could not find a resolver for URI cid:urn%3Auuid%3AD62B819A5C8E77D41B1391208838268#apache.org and Base null
Original Exception was org.apache.xml.security.utils.resolver.ResourceResolverException: Could not find a resolver for URI cid:urn%3Auuid%3AD62B819A5C8E77D41B1391208838268#apache.org and Base null
at org.apache.xml.security.encryption.XMLCipherInput.getDecryptBytes(XMLCipherInput.java:134)
at org.apache.xml.security.encryption.XMLCipherInput.getBytes(XMLCipherInput.java:103)
... 46 more
Caused by: org.apache.xml.security.utils.resolver.ResourceResolverException: Could not find a resolver for URI cid:urn%3Auuid%3AD62B819A5C8E77D41B1391208838268#apache.org and Base null
at org.apache.xml.security.utils.resolver.ResourceResolver.internalGetInstance(ResourceResolver.java:130)
at org.apache.xml.security.utils.resolver.ResourceResolver.getInstance(ResourceResolver.java:87)
at org.apache.xml.security.encryption.XMLCipherInput.getDecryptBytes(XMLCipherInput.java:130)
... 51 more
I tried calling setMTOMEnabled(true) on the binding provider, setting SAAjInInterceptor, AttachmentInInterceptor but still no luck. Any ideas on how to fix it?
It all traces back to the fact that CXF doesn't work with MTOM when WSS is enabled :(
CXF Mailing List One
After struggling a bit more with this problem, it looks like one way to resolve that might be including a custom resource resolver and a transformation.
So I added a custom resolver so that WSS know where to find attachment content:
package org.integration.client;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.Collection;
import org.apache.cxf.message.Attachment;
import org.apache.log4j.Logger;
import org.apache.xml.security.signature.XMLSignatureInput;
import org.apache.xml.security.utils.resolver.ResourceResolverContext;
import org.apache.xml.security.utils.resolver.ResourceResolverException;
import org.apache.xml.security.utils.resolver.ResourceResolverSpi;
public class AttachmentResolverSpi extends ResourceResolverSpi {
private static final String SUPPORTED_URI_PREFIX = "cid:urn";
private static final String ATTACHMENT_PREFIX = "cid:";
private static Logger logger = Logger.getLogger(AttachmentResolverSpi.class);
private Collection<Attachment> attachments;
#Override
public boolean engineIsThreadSafe() {
return false;
}
#Override
public boolean engineCanResolveURI(ResourceResolverContext context) {
if (context.uriToResolve == null) {
return false;
}
return context.uriToResolve.startsWith(SUPPORTED_URI_PREFIX);
}
#Override
public XMLSignatureInput engineResolveURI(ResourceResolverContext context)
throws ResourceResolverException {
String resourceId = getResourceId(context);
if (logger.isInfoEnabled()) {
logger.info("Looking up: " + resourceId);
}
Attachment attachment = getAttachment(resourceId);
if (attachment == null) {
logger.error("Unable to resolve attachment for " + resourceId);
throw new ResourceResolverException(context.uriToResolve, context.attr, context.baseUri);
}
if (logger.isInfoEnabled()) {
logger.info("Found attachment: " + attachment);
}
XMLSignatureInput result;
try {
result = new XMLSignatureInput(attachment.getDataHandler().getInputStream());
} catch (IOException e) {
logger.error("Unable to create xml signature input", e);
throw new ResourceResolverException(context.uriToResolve, context.attr, context.baseUri);
}
return result;
}
private String getResourceId(ResourceResolverContext context) {
String resourceId = context.uriToResolve;
try {
resourceId = URLDecoder.decode(resourceId, "UTF-8");
} catch (UnsupportedEncodingException e1) {
throw new RuntimeException("Unable to decode", e1);
}
if (resourceId.startsWith(ATTACHMENT_PREFIX)) {
resourceId = resourceId.substring(ATTACHMENT_PREFIX.length());
}
return resourceId;
}
private Attachment getAttachment(String resourceId) {
Collection<Attachment> attachments = getAttachments();
if (attachments == null) {
return null;
}
for(Attachment a : attachments) {
if (logger.isDebugEnabled()) {
logger.debug("Comparing " + a.getId() + " with " + resourceId);
}
if (a.getId().equals(resourceId)) {
return a;
}
}
return null;
}
protected Collection<Attachment> getAttachments() {
if (attachments == null) {
attachments = AttachmentCachingSaajInInterceptor.getAttachments();
}
return attachments;
}
}
Now, additional tweak is to tell CXF how to get the signature value for this content:
package org.integration.client;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.OutputStream;
import javax.xml.parsers.ParserConfigurationException;
import org.apache.xml.security.c14n.CanonicalizationException;
import org.apache.xml.security.c14n.InvalidCanonicalizerException;
import org.apache.xml.security.exceptions.Base64DecodingException;
import org.apache.xml.security.signature.XMLSignatureInput;
import org.apache.xml.security.transforms.Transform;
import org.apache.xml.security.transforms.TransformSpi;
import org.apache.xml.security.transforms.TransformationException;
import org.xml.sax.SAXException;
public class TransformAttachmentCiphertext extends TransformSpi {
public static final String TRANSFORM_ATTACHMENT_CIPHERTEXT =
"http://docs.oasis-open.org/wss/oasis-wss-SwAProfile-1.1#Attachment-Ciphertext-Transform";
/**
* #see org.apache.xml.security.transforms.TransformSpi#engineGetURI()
*/
#Override
public String engineGetURI() {
return TRANSFORM_ATTACHMENT_CIPHERTEXT;
}
/**
* #see org.apache.xml.security.transforms.TransformSpi#enginePerformTransform(org.apache.xml.security.signature.XMLSignatureInput,
* java.io.OutputStream, org.apache.xml.security.transforms.Transform)
*/
#Override
protected XMLSignatureInput enginePerformTransform(XMLSignatureInput input,
OutputStream os, Transform transformObject) throws IOException,
CanonicalizationException, InvalidCanonicalizerException,
TransformationException, ParserConfigurationException, SAXException {
if (input.isOctetStream() || input.isNodeSet()) {
if (os == null) {
byte[] contentBytes = input.getBytes();
XMLSignatureInput output = new XMLSignatureInput(contentBytes);
return output;
}
if (input.isByteArray() || input.isNodeSet()) {
os.write(input.getBytes());
} else {
try {
org.apache.xml.security.utils.Base64.decode(new BufferedInputStream(input.getOctetStreamReal()), os);
} catch (Base64DecodingException e) {
throw new IOException("Unable to decode real octet stream", e);
}
}
XMLSignatureInput output = new XMLSignatureInput(new byte[] {});
output.setOutputStream(os);
return output;
}
return input;
}
}
Finally, those two elements need to be registered with CXF:
import org.apache.xml.security.utils.resolver.ResourceResolver;
...
ResourceResolver.register(AttachmentResolverSpi.class, true);
org.apache.xml.security.transforms.Transform.register(TransformAttachmentCiphertext.TRANSFORM_ATTACHMENT_CIPHERTEXT, TransformAttachmentCiphertext.class);
Please don't ask me how, but CXF starts decrypting SOAP messages with Attachments after these manipulations. But that's not a complete solution as it still doesn't work with MTOM attachments... What happens is that CXF attempts to update the DOM model with the attachment content. This approach doesn't work for two reasons. First the binary attachments are don't usually make well-formed XML elements. Second, the Attachment instances on the SOAP message are not updated. To fix that, and finally produce a working solution, I had to hack DocumentSerializer (resolves problem 1 by base64 encoding the content if it can't be parsed) and XMLCipher (resolves problem 2 by replacing the Attachment instances).
The application published by hmkcode.com takes some data from user and parse & convert, and send to a java servlet called jsonservlet. I changed the input values parsed but I'm receiving everytime NullPointerException.
java.lang.NullPointerException
java.io.StringReader.<init>(StringReader.java:50)
com.fasterxml.jackson.core.JsonFactory.createParser(JsonFactory.java:796)
com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2034)
iaau.uimsmobile.getData.getDataServlet.doPost(getDataServlet.java:48)
iaau.uimsmobile.getData.getDataServlet.doGet(getDataServlet.java:65)
javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)
LogCat trace
02-01 10:31:38.232 424-424/com.iaaum D/dalvikvm﹕ GC_EXTERNAL_ALLOC freed 81K, 52% free 2630K/5379K, external 904K/1038K, paused 72ms
02-01 10:32:03.392 424-424/com.iaaum W/KeyCharacterMap﹕ No keyboard for id 0
02-01 10:32:03.392 424-424/com.iaaum W/KeyCharacterMap﹕ Using default keymap: /system/usr/keychars/qwerty.kcm.bin
02-01 10:32:08.962 424-433/com.iaaum D/InputStream﹕ Connection to http://localhost:8080 refused
02-01 10:34:28.142 424-434/com.iaaum D/InputStream﹕ Connection to http://localhost:8080 refused
At last, I changed the strings in JSON format inside the toString() methods in both sides. The failure what #SotiriosDelimanolis talked about is appeared.
com.fasterxml.jackson.databind.JsonMappingException: No content to map due to end-of-input
at [Source: java.io.StringReader#30b3b5; line: 1, column: 1]
com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:164)
com.fasterxml.jackson.databind.ObjectMapper._initForReading(ObjectMapper.java:2931)
com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:2873)
com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2034)
iaau.uimsmobile.getData.getDataServlet.doPost(getDataServlet.java:48)
iaau.uimsmobile.getData.getDataServlet.doGet(getDataServlet.java:65)
javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)
Client side --> User.java
public class User{
private String IDnumber;
private String Password;
public String getIDnumber() {
return IDnumber;
}
public void setIDnumber(String IDnumber) {
this.IDnumber = IDnumber;
}
public String getPassword() {
return Password;
}
public void setPassword(String password) {
Password = password;
}
#Override
public String toString()
{
// { "IDnumber":"" , "Password":"" }
return "{\"IDnumber\":"+"\""+IDnumber+"\""+",\"Password\":"+"\""+Password+"\"}";
}
}
Client side --> LoginActivity.java
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.util.Log;
import android.widget.Toast;
import com.iaaum.user.User;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
public class LoginActivity extends Activity implements OnClickListener
{
TextView IsConnected;
EditText id_number;
EditText password;
Button sign_button;
User current_user;
public String urlAddress = "http://192.168.1.101:8080/UIMSMobile/getDataServlet";
//public String urlAddress = "http://127.0.0.1:8080/UIMSMobile/getDataServlet";
//public String urlAddress = "http://localhost:8080/UIMSMobile/getDataServlet";
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_login);
// get reference to the views
IsConnected = (TextView) findViewById(R.id.isConnected);
id_number = (EditText) findViewById(R.id.id_number);
password = (EditText) findViewById(R.id.password);
sign_button= (Button) findViewById(R.id.sign_in_button);
// check if you are connected or not
if(IsConnectedMethod())
{
IsConnected.setBackgroundColor(0xFF00CC00);
IsConnected.setText("You are connected");
}
else{
IsConnected.setText("You are NOT connected");
}
// add click listener to Button "POST"
sign_button.setOnClickListener(this);
}
#Override
public void onClick(View view)
{
switch(view.getId()){
case R.id.sign_in_button:
if(!validate())
Toast.makeText(getBaseContext(), "Enter some data!", Toast.LENGTH_LONG).show();
// call AsyncTask to perform network operation on separate thread
new HttpAsyncTask().execute(urlAddress);
break;
}
}
public boolean IsConnectedMethod()
{
ConnectivityManager connMgr = (ConnectivityManager) getSystemService(Activity.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
return networkInfo != null && networkInfo.isConnected();
}
public static String Post(String url, User current_user)
{
InputStream inputStream = null;
String result = "";
try
{
// 1. create HttpClient
HttpClient httpclient = new DefaultHttpClient();
// 2. make POST request to the given URL
HttpPost httpPost = new HttpPost(url);
String json = "";
// 3. build jsonObject
JSONObject jsonObject = new JSONObject();
jsonObject.accumulate("IDnumber", current_user.getIDnumber());
jsonObject.accumulate("Password", current_user.getPassword());
// 4. convert JSONObject to JSON in String
json = jsonObject.toString();
// ** Alternative way to convert Person object to JSON string using Jackson Lib
// ObjectMapper mapper = new ObjectMapper();
// json = mapper.writeValueAsString(person);
// 5. set json to StringEntity
StringEntity se = new StringEntity(json);
// 6. set httpPost Entity
httpPost.setEntity(se);
// 7. Set some headers to inform server about the type of the content
httpPost.setHeader("Accept", "application/json");
httpPost.setHeader("Content-type", "application/json");
// 8. Execute POST request to the given URL
HttpResponse httpResponse = httpclient.execute(httpPost);
// 9. receive response as inputStream
inputStream = httpResponse.getEntity().getContent();
// 10. convert inputstream to string
if(inputStream != null)
result = convertInputStreamToString(inputStream);
else
result = "Did not work!";
} catch (Exception e) {
Log.d("InputStream", e.getLocalizedMessage());
}
// 11. return result
return result;
}
private class HttpAsyncTask extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... urls)
{
current_user = new User();
current_user.setIDnumber(id_number.getText().toString());
current_user.setPassword(password.getText().toString());
return Post(urls[0], current_user);
}
// onPostExecute displays the results of the AsyncTask.
#Override
protected void onPostExecute(String result) {
Toast.makeText(getBaseContext(), "Data Sent!", Toast.LENGTH_LONG).show();
}
}
private boolean validate()
{
if(id_number.getText().toString().trim().equals(""))
return false;
else return !password.getText().toString().trim().equals("");
}
private static String convertInputStreamToString(InputStream inputStream) throws IOException {
BufferedReader bufferedReader = new BufferedReader( new InputStreamReader(inputStream));
String line = "";
String result = "";
while((line = bufferedReader.readLine()) != null)
result += line;
inputStream.close();
return result;
}
}
Client side --> AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.iaaum" >
<uses-sdk
android:minSdkVersion="8"
android:maxSdkVersion="19"
/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET"/>
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="com.iaaum.LoginActivity"
android:label="#string/title_activity_login" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Server side --> User.java
public class User
{
private String idnumber;
private String password;
public User(String idnumber, String password) {
this.idnumber = idnumber;
this.password = password;
}
public String getIDnumber() {
return idnumber;
}
public void setIDnumber(String idnumber) {
this.idnumber = idnumber;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
#Override
public String toString()
{
return "{\"IDnumber\":"+"\""+idnumber+"\""+",\"Password\":"+"\""+password+"\"}";
}
}
Server side --> getDataServlet.java
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.fasterxml.jackson.databind.ObjectMapper;
public class getDataServlet extends HttpServlet
{
private static final long serialVersionUID = 1L;
// This will store all received articles
List<User> _users = new LinkedList<User>();
/***************************************************
* URL: /getDataServlet
* doPost(): receives JSON data, parse it, map it and send back as JSON
* #param request
* #param response
* #throws javax.servlet.ServletException
* #throws java.io.IOException
****************************************************/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
// 1. get received JSON data from request
BufferedReader br = new BufferedReader(new InputStreamReader(request.getInputStream()));
String json = "";
if(br.readLine() != null)
{
json = br.readLine();
}
// 2. initiate jackson mapper
ObjectMapper mapper = new ObjectMapper();
// 3. Convert received JSON to User
User _user = mapper.readValue(json, User.class);
// 4. Set response type to JSON
response.setContentType("application/json");
// 5. Add article to List<Article>
_users.add(_user);
// 6. Send List<Article> as JSON to client
mapper.writeValue(response.getOutputStream(), _users);
}
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
doPost(request, response);
}
#Override
public String getServletInfo()
{
return "Short description";
}
}
The only way that exception could be thrown is if the String json you pass in
mapper.readValue(json, User.class);
is null.
You're doing something wrong here
if(br != null)
{
json = br.readLine();
}
br could never be null there. Maybe you meant
String temp;
if ((temp = br.readLine()) != null)
{
json = temp;
}
Or even better, pass the stream directly to one of the ObjectMapper's overloaded readValue(..) methods and handle any errors.
In any case, it seems you aren't sending anything in the body of the request, so readLine() returns null which you assign to json and that causes a failure in the ObjectMapper.
Your doGet() is delegating to your doPost(). Is it possible you are sending GET requests?
By handling your suggessions, I made some changes in codes and the application is working now. Here is the changes:
Server Side ---> getDataServlet.java
package com.****;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.****.dao.User;
public class getDataServlet extends HttpServlet
{
private static final long serialVersionUID = 1L;
List<User> users = new LinkedList<User>();
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
BufferedReader br = new BufferedReader(new InputStreamReader(request.getInputStream()));
String json = "";
if(br != null){
json = br.readLine();}
ObjectMapper mapper = new ObjectMapper();
User user = mapper.readValue(json, User.class);
response.setContentType("application/json");
if(users.size() > 20){
users.remove(0);}
users.add(user);
mapper.writeValue(response.getOutputStream(), users);
}
#Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
{
ObjectMapper mapper = new ObjectMapper();
resp.setContentType("application/json");
mapper.writeValue(resp.getOutputStream(), users);
}
}
Server Side --> User.java
package com.*****.dao;
public class User {
private String idnumber;
private String password;
public String getIdnumber() {
return idnumber;
}
public void setIdnumber(String idnumber) {
this.idnumber = idnumber;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
#Override
public String toString() {
return "User [idnumber=" + idnumber + ", password=" + password + "]";
}
}
Client Side ---> MainActivity.java
JSONObject jsonObject = new JSONObject();
jsonObject.accumulate("idnumber", user.getIdnumber());
jsonObject.accumulate("password", user.getPassword());
Client Side ---> User.java
#Override
public String toString()
{
return "User [idnumber=" + idnumber + ", password=" + password + "]";
}
And after post data output appeared:
[{"idnumber":"987654321 ","password":"123456789"}]
Solution 1:
May be its problem of you given URL, if you working on localhost then use your IP Address instead of localhost
you can check your IP in command prompt using ipconfig command.
Solution 2:
In your User.java You may have to use JSONObject and JSONArray to create JSON String in toString() method.