Spring AbstractRequestLoggingFilter fails with OOM on big requests - spring

If I enable setIncludePayload(true) and I send a large request to servlet, application fails with OOM error.
I use Spring 3.2.8.
What can be wrong?

The problem is that this filter is not suitable for production. It caches everything in byte array buffer which give OOM with large requests like file uploads.
I altered source code so that this problem is avoided, see below.
Note: payload is only accessible in afterRequest method, because otherwice we would need to save request body to temporal file.
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;
/**
* org.springframework.web.filter.AbstractRequestLoggingFilter will fail with OOM on large file upload. We fix it with limited size of byte buffer
*/
public abstract class AbstractRequestLoggingWithMaxSizeCheckFilter extends OncePerRequestFilter {
public static final String DEFAULT_BEFORE_MESSAGE_PREFIX = "Before request [";
public static final String DEFAULT_BEFORE_MESSAGE_SUFFIX = "]";
public static final String DEFAULT_AFTER_MESSAGE_PREFIX = "After request [";
public static final String DEFAULT_AFTER_MESSAGE_SUFFIX = "]";
private static final int DEFAULT_MAX_PAYLOAD_LENGTH = 50;
private boolean includeQueryString = false;
private boolean includeClientInfo = false;
private boolean includePayload = false;
private int maxPayloadLength = 50;
private String beforeMessagePrefix = "Before request [";
private String beforeMessageSuffix = "]";
private String afterMessagePrefix = "After request [";
private String afterMessageSuffix = "]";
public AbstractRequestLoggingWithMaxSizeCheckFilter() {
}
public void setIncludeQueryString(boolean includeQueryString) {
this.includeQueryString = includeQueryString;
}
protected boolean isIncludeQueryString() {
return this.includeQueryString;
}
public void setIncludeClientInfo(boolean includeClientInfo) {
this.includeClientInfo = includeClientInfo;
}
protected boolean isIncludeClientInfo() {
return this.includeClientInfo;
}
public void setIncludePayload(boolean includePayload) {
this.includePayload = includePayload;
}
protected boolean isIncludePayload() {
return this.includePayload;
}
public void setMaxPayloadLength(int maxPayloadLength) {
Assert.isTrue(maxPayloadLength >= 0, "'maxPayloadLength' should be larger than or equal to 0");
this.maxPayloadLength = maxPayloadLength;
}
protected int getMaxPayloadLength() {
return this.maxPayloadLength;
}
public void setBeforeMessagePrefix(String beforeMessagePrefix) {
this.beforeMessagePrefix = beforeMessagePrefix;
}
public void setBeforeMessageSuffix(String beforeMessageSuffix) {
this.beforeMessageSuffix = beforeMessageSuffix;
}
public void setAfterMessagePrefix(String afterMessagePrefix) {
this.afterMessagePrefix = afterMessagePrefix;
}
public void setAfterMessageSuffix(String afterMessageSuffix) {
this.afterMessageSuffix = afterMessageSuffix;
}
protected boolean shouldNotFilterAsyncDispatch() {
return false;
}
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
boolean isFirstRequest = !this.isAsyncDispatch((HttpServletRequest) request);
if (this.isIncludePayload() && isFirstRequest) {
request = new AbstractRequestLoggingWithMaxSizeCheckFilter.RequestCachingRequestWrapper((HttpServletRequest) request, maxPayloadLength);
}
if (isFirstRequest) {
this.beforeRequest((HttpServletRequest) request, this.getBeforeMessage((HttpServletRequest) request));
}
try {
filterChain.doFilter((ServletRequest) request, response);
} finally {
if (!this.isAsyncStarted((HttpServletRequest) request)) {
this.afterRequest((HttpServletRequest) request, this.getAfterMessage((HttpServletRequest) request));
}
}
}
private String getBeforeMessage(HttpServletRequest request) {
return this.createMessage(request, this.beforeMessagePrefix, this.beforeMessageSuffix);
}
private String getAfterMessage(HttpServletRequest request) {
return this.createMessage(request, this.afterMessagePrefix, this.afterMessageSuffix);
}
protected String createMessage(HttpServletRequest request, String prefix, String suffix) {
StringBuilder msg = new StringBuilder();
msg.append(prefix);
msg.append("uri=").append(request.getRequestURI());
if (this.isIncludeQueryString()) {
msg.append('?').append(request.getQueryString());
}
if (this.isIncludeClientInfo()) {
String client = request.getRemoteAddr();
if (StringUtils.hasLength(client)) {
msg.append(";client=").append(client);
}
HttpSession session = request.getSession(false);
if (session != null) {
msg.append(";session=").append(session.getId());
}
String user = request.getRemoteUser();
if (user != null) {
msg.append(";user=").append(user);
}
}
if (this.isIncludePayload() && request instanceof AbstractRequestLoggingWithMaxSizeCheckFilter.RequestCachingRequestWrapper) {
AbstractRequestLoggingWithMaxSizeCheckFilter.RequestCachingRequestWrapper wrapper = (AbstractRequestLoggingWithMaxSizeCheckFilter.RequestCachingRequestWrapper) request;
byte[] buf = wrapper.toByteArray();
if (buf.length > 0) {
String payload;
try {
payload = new String(buf, wrapper.getCharacterEncoding());
} catch (UnsupportedEncodingException var10) {
payload = "[unknown]";
}
msg.append(";payload=").append(payload);
}
}
msg.append(suffix);
return msg.toString();
}
protected abstract void beforeRequest(HttpServletRequest var1, String var2);
protected abstract void afterRequest(HttpServletRequest var1, String var2);
private static class RequestCachingRequestWrapper extends HttpServletRequestWrapper {
private final ByteArrayOutputStream bos;
private final ServletInputStream inputStream;
private BufferedReader reader;
private int maxPayloadLength;
private boolean capped;
private RequestCachingRequestWrapper(HttpServletRequest request, int maxPayloadLength) throws IOException {
super(request);
this.bos = new ByteArrayOutputStream();
this.inputStream = new AbstractRequestLoggingWithMaxSizeCheckFilter.RequestCachingRequestWrapper.RequestCachingInputStream(request.getInputStream());
this.maxPayloadLength = maxPayloadLength;
}
public ServletInputStream getInputStream() throws IOException {
return this.inputStream;
}
public String getCharacterEncoding() {
return super.getCharacterEncoding() != null ? super.getCharacterEncoding() : "ISO-8859-1";
}
public BufferedReader getReader() throws IOException {
if (this.reader == null) {
this.reader = new BufferedReader(new InputStreamReader(this.inputStream, this.getCharacterEncoding()));
}
return this.reader;
}
private byte[] toByteArray() {
return this.bos.toByteArray();
}
private class RequestCachingInputStream extends ServletInputStream {
private final ServletInputStream is;
private RequestCachingInputStream(ServletInputStream is) {
this.is = is;
}
public int read() throws IOException {
int ch = this.is.read();
if (ch != -1) {
if (!capped) {
AbstractRequestLoggingWithMaxSizeCheckFilter.RequestCachingRequestWrapper.this.bos.write(ch);
if (AbstractRequestLoggingWithMaxSizeCheckFilter.RequestCachingRequestWrapper.this.bos.size() >= maxPayloadLength) {
AbstractRequestLoggingWithMaxSizeCheckFilter.RequestCachingRequestWrapper.this.bos.write("...(truncated)".getBytes("UTF-8"));
capped = true;
}
}
}
return ch;
}
}
}
}

Related

How To validate Jwt Token for Apple Login (Backend validation). How to generate RSA Public key from modulus and exponent (n,e) in Java

I'm looking for a way to validate apple's login token.
The validation must be done on backend side so i'm sure that i can add a new account safely.
Onother issue is that i need to convert the key https://appleid.apple.com/auth/keys in xml format to Public Key pem format.
I have found a possible solution that I will post below.
The code is implemented in Java
public static void main(String...args) throws Exception {
String jwtAppleToken = ""; //copy here the token from apple
//copied from https://appleid.apple.com/auth/keys
final String base64UrlEncodedModulus = "lxrwmuYSAsTfn-lUu4goZSXBD9ackM9OJuwUVQHmbZo6GW4Fu_auUdN5zI7Y1dEDfgt7m7QXWbHuMD01HLnD4eRtY-RNwCWdjNfEaY_esUPY3OVMrNDI15Ns13xspWS3q-13kdGv9jHI28P87RvMpjz_JCpQ5IM44oSyRnYtVJO-320SB8E2Bw92pmrenbp67KRUzTEVfGU4-obP5RZ09OxvCr1io4KJvEOjDJuuoClF66AT72WymtoMdwzUmhINjR0XSqK6H0MdWsjw7ysyd_JhmqX5CAaT9Pgi0J8lU_pcl215oANqjy7Ob-VMhug9eGyxAWVfu_1u6QJKePlE-w";
final String base64UrlEncodedExp = "AQAB";
String publicKey = getPemPublicKeyFromBase64UrlEncodedXMLRSAKey(base64UrlEncodedModulus, base64UrlEncodedExp);
System.out.println(verify(jwtAppleToken, publicKey));
System.out.println("-----BEGIN PUBLIC KEY-----");
System.out.println(publicKey);
System.out.println("-----END PUBLIC KEY-----");
}
The same solution with Jose4 lib,
This HttpsJwksVerificationKeyResolver will pick the public key based on key id from the list. so we don't have to deal with it.
import org.jose4j.jwk.HttpsJwks;
import org.jose4j.jwt.JwtClaims;
import org.jose4j.jwt.consumer.JwtConsumer;
import org.jose4j.jwt.consumer.JwtConsumerBuilder;
import org.jose4j.keys.resolvers.HttpsJwksVerificationKeyResolver;
HttpsJwks httpsJkws = new HttpsJwks("https://appleid.apple.com/auth/keys");
HttpsJwksVerificationKeyResolver httpsJwksKeyResolver = new HttpsJwksVerificationKeyResolver(httpsJkws);
JwtConsumer jwtConsumer = new JwtConsumerBuilder()
.setVerificationKeyResolver(httpsJwksKeyResolver)
.setExpectedIssuer("https://appleid.apple.com")
.setExpectedAudience(<clientId>)
.build();
JwtClaims jwtClaims = jwtConsumer.processToClaims(<idToken>);
processToClaims will throw appropriate exceptions, just catch and act accordingly.
Hope this keeps simple and makes more readable for other developers.
This is a possible solution for the validation of the apple login token.
The implementation uses the Apple public key published on --> https://appleid.apple.com/auth/keys
The keys are converted in PEM format from XML format (https://appleid.apple.com/auth/keys) and than the token is validated.
Some of the code can be used to convert modulus and exponent in string format to RSA Public key in PEM Format
import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.RSAPublicKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import org.springframework.security.jwt.JwtHelper;
import org.springframework.security.jwt.crypto.sign.RsaVerifier;
public class VerifyAppleToken {
public static void main(String...args) throws Exception {
String jwtAppleToken = ""; //copy here the token from apple
System.out.println("THE TOKEN IS VERIFIED FOR ONE OF APPLE KEYS:"+verify(jwtAppleToken));
//copied from https://appleid.apple.com/auth/keys
final String base64UrlEncodedModulus = "lxrwmuYSAsTfn-lUu4goZSXBD9ackM9OJuwUVQHmbZo6GW4Fu_auUdN5zI7Y1dEDfgt7m7QXWbHuMD01HLnD4eRtY-RNwCWdjNfEaY_esUPY3OVMrNDI15Ns13xspWS3q-13kdGv9jHI28P87RvMpjz_JCpQ5IM44oSyRnYtVJO-320SB8E2Bw92pmrenbp67KRUzTEVfGU4-obP5RZ09OxvCr1io4KJvEOjDJuuoClF66AT72WymtoMdwzUmhINjR0XSqK6H0MdWsjw7ysyd_JhmqX5CAaT9Pgi0J8lU_pcl215oANqjy7Ob-VMhug9eGyxAWVfu_1u6QJKePlE-w";
final String base64UrlEncodedExp = "AQAB";
String publicKey = getPemPublicKeyFromBase64UrlEncodedXMLRSAKey(base64UrlEncodedModulus, base64UrlEncodedExp);
System.out.println(verify(jwtAppleToken, publicKey));
//copied from and converted to base64 from base64UrlEncoded https://appleid.apple.com/auth/keys on
// 07/02/2020
final String base64EncodedModulus = "lxrwmuYSAsTfn+lUu4goZSXBD9ackM9OJuwUVQHmbZo6GW4Fu/auUdN5zI7Y1dEDfgt7m7QXWbHuMD01HLnD4eRtY+RNwCWdjNfEaY/esUPY3OVMrNDI15Ns13xspWS3q+13kdGv9jHI28P87RvMpjz/JCpQ5IM44oSyRnYtVJO+320SB8E2Bw92pmrenbp67KRUzTEVfGU4+obP5RZ09OxvCr1io4KJvEOjDJuuoClF66AT72WymtoMdwzUmhINjR0XSqK6H0MdWsjw7ysyd/JhmqX5CAaT9Pgi0J8lU/pcl215oANqjy7Ob+VMhug9eGyxAWVfu/1u6QJKePlE+w==";
final String base64EncodedExp = "AQAB";
System.out.println("-----BEGIN PUBLIC KEY-----");
System.out.println(getPemPublicKeyFromBase64XMLRSAKey(base64EncodedModulus, base64EncodedExp));
System.out.println("-----END PUBLIC KEY-----");
}
private static boolean verify(String jwtAppleToken) throws NoSuchAlgorithmException, InvalidKeySpecException {
AppleKeysRetrieverService retriver = new AppleKeysRetrieverService();
AppleKeysResponse res = retriver.sendRetriveRequest("https://appleid.apple.com/auth/keys");
List<AppleKeyDTO> appleKeys = res.getKeys();
for (AppleKeyDTO appleKeyDTO : appleKeys) {
final String base64UrlEncodedModulus = appleKeyDTO.getN();
final String base64UrlEncodedExp = appleKeyDTO.getE();
String publicKey1 = getPemPublicKeyFromBase64UrlEncodedXMLRSAKey(base64UrlEncodedModulus, base64UrlEncodedExp);
if(verify(jwtAppleToken, publicKey1)) {
return true;
}
}
return false;
}
public static boolean verify(String jwtToken, String publicKey) {
try {
JwtHelper.decodeAndVerify(jwtToken, new RsaVerifier(getRSAPublicKey(publicKey)));
} catch (Exception e) {
return false;
}
return true;
}
private static RSAPublicKey getRSAPublicKey(String publicKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
KeyFactory keyFactory = java.security.KeyFactory.getInstance("RSA");
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(java.util.Base64.getDecoder().decode(publicKey));
return (RSAPublicKey) keyFactory.generatePublic(keySpec);
}
private static String getPemPublicKeyFromBase64UrlEncodedXMLRSAKey(String urlBase64Modulus, String urlBase64Exp) throws NoSuchAlgorithmException, InvalidKeySpecException {
byte[] e = Base64.getUrlDecoder().decode(urlBase64Exp);
byte[] n = Base64.getUrlDecoder().decode(urlBase64Modulus);
BigInteger exponent = new BigInteger(1, e);
BigInteger modulus = new BigInteger(1, n);
return getPemPublicKey(modulus, exponent);
}
private static String getPemPublicKeyFromBase64XMLRSAKey(String base64Modulus, String base64Exp) throws NoSuchAlgorithmException, InvalidKeySpecException {
byte[] e = Base64.getDecoder().decode(base64Exp);
byte[] n = Base64.getDecoder().decode(base64Modulus);
BigInteger exponent = new BigInteger(1, e);
BigInteger modulus = (new BigInteger(1, n));
return getPemPublicKey(modulus, exponent);
}
private static String getPemPublicKey(BigInteger modulus, BigInteger exponent) throws NoSuchAlgorithmException, InvalidKeySpecException {
RSAPublicKeySpec publicKeySpec = new java.security.spec.RSAPublicKeySpec(modulus, exponent);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey myPublicKey = keyFactory.generatePublic(publicKeySpec);
byte[] park = Base64.getEncoder().encode(myPublicKey.getEncoded());
return new String(park);
}
}
RETRIVE APPLE KEYS:
public class AppleKeysRetrieverService {
public AppleKeysResponse sendRetriveRequest(String retriveAppleKeysUrl) {
RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters()
.add(0, new StringHttpMessageConverter(StandardCharsets.UTF_8));
String appleKeysResponse = restTemplate
.getForObject(retriveAppleKeysUrl, String.class);
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(
DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
AppleKeysResponse res = null;
try {
res = objectMapper.readValue(appleKeysResponse, AppleKeysResponse.class);
return res;
}catch(Exception e) {
return null;
}
}
}
public class AppleKeyDTO {
public String kty;
public String kid;
public String sig;
public String alg;
public String n;
public String e;
public String getKty() {
return kty;
}
public void setKty(String kty) {
this.kty = kty;
}
public String getKid() {
return kid;
}
public void setKid(String kid) {
this.kid = kid;
}
public String getSig() {
return sig;
}
public void setSig(String sig) {
this.sig = sig;
}
public String getAlg() {
return alg;
}
public void setAlg(String alg) {
this.alg = alg;
}
public String getN() {
return n;
}
public void setN(String n) {
this.n = n;
}
public String getE() {
return e;
}
public void setE(String e) {
this.e = e;
}
}
public class AppleKeysResponse {
private List<AppleKeyDTO> keys;
public List<AppleKeyDTO> getKeys() {
return keys;
}
public void setKeys(List<AppleKeyDTO> keys) {
this.keys = keys;
}
}

NiFI "unable to find flowfile content"

I am using nifi 1.6 and get the following errors when trying to modify a clone of an incoming flowFile:
[1]"unable to find content for FlowFile: ... MissingFlowFileException
...
Caused by ContentNotFoundException: Could not find contetn for StandardClaim
...
Caused by java.io.EOFException: null"
[2]"FlowFileHandlingException: StandardFlowFileRecord... is not known in this session"
The first error occurs when trying to access the contents of the flow file, the second when removing the flow file from the session (within a catch of the first). This process is known to have worked under nifi 0.7.
The basic process is:
Clone the incoming flow file
Write to the clone
Write to the clone again (some additional formatting)
Repeat 1-3
The error occurs on the second iteration step 3.
An interesting point is that if immediately after the clone is performed, a session.read of the clone is done everything works fine. The read seems to reset some pointer.
I have created unit tests for this processor, but they do not fail in either case.
Below is code simplified from the actual version in use that demonstrates the issue. (The development system is not connected so I had to copy the code. Please forgive any typos - it should be close. This is also why a full stack trace is not provided.) The processor doing the work has a property to determine if an immediate read should be done, or not. So both scenarios can be performed easily. To set it up, all that is needed is a GetFile processor to supply the input and terminators for the output from the SampleCloningProcessor. A sample input file is included as well. The meat of the code is in the onTrigger and manipulate methods. The manipulation in this simplified version really don't do anything but copy the input to the output.
Any insights into why this is happening and suggestions for corrections will be appreciated - thanks.
SampleCloningProcessor.java
processor sample.package.cloning
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.Reader;
import java.util.Arrays;
import java.util.Hashset;
import java.util.List;
import java.util.Scanner;
import java.util.Set;
import org.apache.commons.compress.utils.IOUtils;
import org.apache.nifi.annotation.documentaion.CapabilityDescription;
import org.apache.nifi.annotation.documentaion.Tags;
import org.apache.nifi.componets.PropertyDescriptor;
import org.apache.nifi.flowfile.FlowFile;
import org.apache.nifi.processor.AbstractProcessor;
import org.apache.nifi.processor.ProcessorContext;
import org.apache.nifi.processor.ProcessorSession;
import org.apache.nifi.processor.ProcessorInitioalizationContext;
import org.apache.nifi.processor.Relationship;
import org.apache.nifi.processor.exception.ProcessException;
import org.apache.nifi.processor.io.InputStreamCalback;
import org.apache.nifi.processor.io.OutputStreamCalback;
import org.apache.nifi.processor.io.StreamCalback;
import org.apache.nifi.processor.util.StandardValidators;
import com.google.gson.Gson;
#Tags({"example", "clone"})
#CapabilityDescription("Demonsrates cloning of flowfile failure.")
public class SampleCloningProcessor extend AbstractProcessor {
/* Determines if an immediate read is performed after cloning of inoming flowfile. */
public static final PropertyDescriptor IMMEDIATE_READ = new PropertyDescriptor.Builder()
.name("immediateRead")
.description("Determines if processor runs successfully. If a read is done immediatly "
+ "after the clone of the incoming flowFile, then the processor should run successfully.")
.required(true)
.allowableValues("true", "false")
.defaultValue("true")
.addValidator(StandardValidators.BOLLEAN_VALIDATOR)
.build();
public static final Relationship SUCCESS = new Relationship.Builder().name("success").
description("No unexpected errors.").build();
public static final Relationship FAILURE = new Relationship.Builder().name("failure").
description("Errors were thrown.").build();
private Set<Relationship> relationships;
private List<PropertyDescriptors> properties;
#Override
public void init(final ProcessorInitializationContext contex) {
relationships = new HashSet<>(Arrays.asList(SUCCESS, FAILURE));
properties = new Arrays.asList(IMMEDIATE_READ);
}
#Override
public Set<Relationship> getRelationships() {
return this.relationships;
}
#Override
public List<PropertyDescriptor> getSuppprtedPropertyDescriptors() {
return this.properties;
}
#Override
public void onTrigger(final ProcessContext context, final ProcessSession session) throws ProcessException {
FlowFile incomingFlowFile = session.get();
if (incomingFlowFile == null) {
return;
}
try {
final InfileReader inFileReader = new InfileReader();
session.read(incomingFlowFile, inFileReader);
Product product = infileReader.getProduct();
boolean transfer = false;
getLogger().info("\tSession :\n" + session);
getLogger().info("\toriginal :\n" + incomingFlowFile);
for(int i = 0; i < 2; i++) {
transfer = manipulate(context, session, inclmingFlowFile, product);
}
} catch (Exception e) {
getLogger().error(e.getMessage(), e);
session.rollback(true);
}
}
private boolean manipuate(final ProcessContext context, final ProcessSession session
final FlowFile incomingFlowFile, final Product product) {
boolean transfer = false;
FlowFile outgoingFlowFile = null;
boolean immediateRead = context.getProperty(IMMEDIATE_READ).asBoolean();
try {
//Clone incoming flowFile
outgoinFlowFile = session.clone(incomingFlowFile);
getLogger().info("\tclone outgoing :\n" + outgoingFlowFile);
if(immediateRead) {
readFlowFile(session, outgoingFlowFile);
}
//First write into clone
StageOneWrite stage1Write = new StaeOneWrite(product);
outgoingFlowFile = session.write(outgoingFlowFile, stage1Write);
getLogger().info("\twrite outgoing :\n" + outgoingFlowFile);
// Format the cloned file with another write
outgoingFlowFile = formatFlowFile(outgoingFlowFile, session)
getLogger().info("\format outgoing :\n" + outgoingFlowFile);
session.transfer(outgoingFlowFile, SUCCESS);
transfer != true;
} catch(Exception e)
getLogger().error(e.getMessage(), e);
if(outgoingFlowFile ! = null) {
session.remove(outgoingFlowFile);
}
}
return transfer;
}
private void readFlowFile(fainl ProcessSession session, fianl Flowfile flowFile) {
session.read(flowFile, new InputStreamCallback() {
#Override
public void process(Final InputStream in) throws IOException {
try (Scanner scanner = new Scanner(in)) {
scanner.useDelimiter("\\A").next();
}
}
});
}
private FlowFile formatFlowFile(fainl ProcessSession session, FlowFile flowfile) {
OutputFormatWrite formatWrite = new OutputFormatWriter();
flowfile = session.write(flowFile, formatWriter);
return flowFile;
}
private static class OutputFormatWriter implement StreamCallback {
#Override
public void process(final InputStream in, final OutputStream out) throws IOException {
try {
IOUtils.copy(in. out);
out.flush();
} finally {
IOUtils.closeQuietly(in);
IOUtils.closeQuietly(out);
}
}
}
private static class StageOneWriter implements OutputStreamCallback {
private Product product = null;
public StageOneWriter(Produt product) {
this.product = product;
}
#Override
public void process(final OutputStream out) throws IOException {
final Gson gson = new Gson();
final String json = gson.toJson(product);
out.write(json.getBytes());
}
}
private static class InfileReader implements InputStreamCallback {
private Product product = null;
public StageOneWriter(Produt product) {
this.product = product;
}
#Override
public void process(final InputStream out) throws IOException {
product = null;
final Gson gson = new Gson();
Reader inReader = new InputStreamReader(in, "UTF-8");
product = gson.fromJson(inreader, Product.calss);
}
public Product getProduct() {
return product;
}
}
SampleCloningProcessorTest.java
package sample.processors.cloning;
import org.apache.nifi.util.TestRunner;
import org.apache.nifi.util.TestRunners;
import org.junit.Before;
import org.junit.Test;
public class SampleCloningProcessorTest {
final satatic String flowFileContent = "{"
+ "\"cost\": \"cost 1\","
+ "\"description\": \"description","
+ "\"markup\": 1.2"
+ "\"name\":\"name 1\","
+ "\"supplier\":\"supplier 1\","
+ "}";
private TestRunner testRunner;
#Before
public void init() {
testRunner = TestRunner.newTestRunner(SampleCloningProcessor.class);
testRunner.enqueue(flowFileContent);
}
#Test
public void testProcessorImmediateRead() {
testRunner.setProperty(SampleCloningProcessor.IMMEDIATE_READ, "true");
testRunner.run();
testRinner.assertTransferCount("success", 2);
}
#Test
public void testProcessorImmediateRead_false() {
testRunner.setProperty(SampleCloningProcessor.IMMEDIATE_READ, "false");
testRunner.run();
testRinner.assertTransferCount("success", 2);
}
}
Product.java
package sample.processors.cloning;
public class Product {
private String name;
private String description;
private String supplier;
private String cost;
private float markup;
public String getName() {
return name;
}
public void setName(final String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescriptione(final String description) {
this.description = description;
}
public String getSupplier() {
return supplier;
}
public void setSupplier(final String supplier) {
this.supplier = supplier;
}
public String getCost() {
return cost;
}
public void setCost(final String cost) {
this.cost = cost;
}
public float getMarkup() {
return markup;
}
public void setMarkup(final float name) {
this.markup = markup;
}
}
product.json A sample input file.
{
"const" : "cost 1",
"description" : "description 1",
"markup" : 1.2,
"name" : "name 1",
"supplier" : "supplier 1"
}
Reported as a bug in Nifi. Being addressed by https://issues.apache.org/jira/browse/NIFI-5879

Can't stop javafx tables from ignoring my the setter function validation

I'm using javafx to do some table stuff. I want to validate my textfields in the myTextRow Class. In the "setText2" method I check the input if it is not bigger than 6 symbols, but it has no effects at all.
import java.util.ArrayList;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.scene.control.ContentDisplay;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TextArea;
import javafx.util.Callback;
import javafx.application.Application;
import static javafx.application.Application.launch;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
public class Supermain extends Application {
#Override
public void start(Stage primaryStage) {
ArrayList myindizes=new ArrayList();
final TableView<myTextRow> table = new TableView<>();
table.setEditable(true);
table.setStyle("-fx-text-wrap: true;");
//Table columns
TableColumn<myTextRow, String> clmID = new TableColumn<>("ID");
clmID.setMinWidth(160);
clmID.setCellValueFactory(new PropertyValueFactory<>("ID"));
TableColumn<myTextRow, String> clmtext = new TableColumn<>("Text");
clmtext.setMinWidth(160);
clmtext.setCellValueFactory(new PropertyValueFactory<>("text"));
clmtext.setCellFactory(new TextFieldCellFactory());
TableColumn<myTextRow, String> clmtext2 = new TableColumn<>("Text2");
clmtext2.setMinWidth(160);
clmtext2.setCellValueFactory(new PropertyValueFactory<>("text2"));
clmtext2.setCellFactory(new TextFieldCellFactory());
//Add data
final ObservableList<myTextRow> data = FXCollections.observableArrayList(
new myTextRow(5, "Lorem","bla"),
new myTextRow(2, "Ipsum","bla")
);
table.getColumns().addAll(clmID, clmtext,clmtext2);
table.setItems(data);
HBox hBox = new HBox();
hBox.setSpacing(5.0);
hBox.setPadding(new Insets(5, 5, 5, 5));
Button btn = new Button();
btn.setText("Get Data");
btn.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
for (myTextRow data1 : data) {
System.out.println("data:" + data1.getText2());
}
}
});
hBox.getChildren().add(btn);
BorderPane pane = new BorderPane();
pane.setTop(hBox);
pane.setCenter(table);
primaryStage.setScene(new Scene(pane, 640, 480));
primaryStage.show();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
public static class TextFieldCellFactory
implements Callback<TableColumn<myTextRow, String>, TableCell<myTextRow, String>> {
#Override
public TableCell<myTextRow, String> call(TableColumn<myTextRow, String> param) {
TextFieldCell textFieldCell = new TextFieldCell();
return textFieldCell;
}
public static class TextFieldCell extends TableCell<myTextRow, String> {
private TextArea textField;
private StringProperty boundToCurrently = null;
public TextFieldCell() {
textField = new TextArea();
textField.setWrapText(true);
textField.setMinWidth(this.getWidth() - this.getGraphicTextGap() * 2);
this.setGraphic(textField);
}
#Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (!empty) {
// Show the Text Field
this.setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
// myindizes.add(getIndex());
// Retrieve the actual String Property that should be bound to the TextField
// If the TextField is currently bound to a different StringProperty
// Unbind the old property and rebind to the new one
ObservableValue<String> ov = getTableColumn().getCellObservableValue(getIndex());
SimpleStringProperty sp = (SimpleStringProperty) ov;
if (this.boundToCurrently == null) {
this.boundToCurrently = sp;
this.textField.textProperty().bindBidirectional(sp);
} else if (this.boundToCurrently != sp) {
this.textField.textProperty().unbindBidirectional(this.boundToCurrently);
this.boundToCurrently = sp;
this.textField.textProperty().bindBidirectional(this.boundToCurrently);
}
double height = real_lines_height(textField.getText(), this.getWidth(), 30, 22);
textField.setPrefHeight(height);
textField.setMaxHeight(height);
textField.setMaxHeight(Double.MAX_VALUE);
// if height bigger than the biggest height in the row
//-> change all heights of the row(textfields ()typeof textarea) to this height
// else leave the height as it is
//System.out.println("item=" + item + " ObservableValue<String>=" + ov.getValue());
//this.textField.setText(item); // No longer need this!!!
} else {
this.setContentDisplay(ContentDisplay.TEXT_ONLY);
}
}
}
}
public class myTextRow {
private final SimpleIntegerProperty ID;
private final SimpleStringProperty text;
private final SimpleStringProperty text2;
public myTextRow(int ID, String text,String text2) {
this.ID = new SimpleIntegerProperty(ID);
this.text = new SimpleStringProperty(text);
this.text2 = new SimpleStringProperty(text2);
}
public void setID(int id) {
this.ID.set(id);
}
public void setText(String text) {
this.text.set(text);
}
public void setText2(String text) {
if(text2check(text)){
this.text2.set(text);}
else
{System.out.println("wrong value!!!");}
}
public int getID() {
return ID.get();
}
public String getText() {
return text.get();
}
public StringProperty textProperty() {
return text;
}
public String getText2() {
return text2.get();
}
public StringProperty text2Property() {
return text2;
}
public IntegerProperty IDProperty() {
return ID;
}
public boolean text2check(String t)
{
if(t.length()>6)return false;
return true;
}
}
private static double real_lines_height(String s, double width, double heightCorrector, double widthCorrector) {
HBox h = new HBox();
Label l = new Label("Text");
h.getChildren().add(l);
Scene sc = new Scene(h);
l.applyCss();
double line_height = l.prefHeight(-1);
int new_lines = s.replaceAll("[^\r\n|\r|\n]", "").length();
// System.out.println("new lines= "+new_lines);
String[] lines = s.split("\r\n|\r|\n");
// System.out.println("line count func= "+ lines.length);
int count = 0;
//double rest=0;
for (int i = 0; i < lines.length; i++) {
double text_width = get_text_width(lines[i]);
double plus_lines = Math.ceil(text_width / (width - widthCorrector));
if (plus_lines > 1) {
count += plus_lines;
//rest+= (text_width / (width-widthCorrector)) - plus_lines;
} else {
count += 1;
}
}
//count+=(int) Math.ceil(rest);
count += new_lines - lines.length;
return count * line_height + heightCorrector;
}
private static double get_text_width(String s) {
HBox h = new HBox();
Label l = new Label(s);
l.setWrapText(false);
h.getChildren().add(l);
Scene sc = new Scene(h);
l.applyCss();
// System.out.println("dubbyloop.FXMLDocumentController.get_text_width(): "+l.prefWidth(-1));
return l.prefWidth(-1);
}
}
A rule of the JavaFX Properties pattern is that for a property x, invoking xProperty().setValue(value) should always be identical to invoking setX(value). Your validation makes this not true. The binding your cell implementation uses invokes the setValue method on the property, which is why it bypasses your validation check.
(Side note: in all the code I am going to change the names so that they adhere to proper naming conventions.)
The default way to implement a property in this pattern is:
public class MyTextRow {
private final StringProperty text = new SimpleStringProperty();
public StringProperty textProperty() {
return text ;
}
public final void setText(String text) {
textProperty().set(text);
}
public final String getText() {
return textProperty().get();
}
}
By having the set/get methods delegate to the appropriate property methods, you are guaranteed these rules are enforced, even if the textProperty() methods is overridden in a subclass. Making the set and get methods final ensures that the rule is not broken by a subclass overriding those methods.
One approach might be to override the set and setValue methods in the property, as follows:
public class MyTextRow {
private final StringProperty text2 = new StringPropertyBase() {
#Override
public String getName() {
return "text2";
}
#Override
public Object getBean() {
return MyTextRow.this ;
}
#Override
public void setValue(String value) {
if (text2Check(value)) {
super.setValue(value);
}
}
#Override
public void set(String value) {
if (text2Check(value)) {
super.set(value);
}
}
}
public StringProperty text2Property() {
return text2 ;
}
public final void setText2(String text2) {
text2Property().set(text2);
}
public final String getText2() {
return text2Property().get();
}
// ...
}
however, I think this will break the bidirectional binding that you have with the text property in the TextArea (basically, there is no way to communicate back to the text area when a change is vetoed, so the text area will not know to revert to the previous value). One fix would be to implement your cell using listeners on the properties instead of bindings. You could use a TextFormatter on the text area that simply updates the property and vetoes the text change if the change doesn't occur.
Here is a complete SSCCE using this approach:
import java.util.function.Function;
import java.util.function.UnaryOperator;
import javafx.application.Application;
import javafx.beans.property.Property;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.property.StringPropertyBase;
import javafx.scene.Scene;
import javafx.scene.control.ContentDisplay;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextFormatter;
import javafx.scene.control.TextFormatter.Change;
import javafx.stage.Stage;
public class VetoStringChange extends Application {
#Override
public void start(Stage primaryStage) {
TableView<Item> table = new TableView<>();
table.setEditable(true);
table.getColumns().add(column("Item", Item::nameProperty));
table.getColumns().add(column("Description", Item::descriptionProperty));
for (int i = 1; i <= 20 ; i++) {
table.getItems().add(new Item("Item "+i, ""));
}
primaryStage.setScene(new Scene(table, 600, 600));
primaryStage.show();
}
public static <S> TableColumn<S,String> column(String title, Function<S,Property<String>> property) {
TableColumn<S,String> col = new TableColumn<>(title);
col.setCellValueFactory(cellData -> property.apply(cellData.getValue()));
col.setCellFactory(tc -> new TextAreaCell<S>(property));
col.setPrefWidth(200);
return col ;
}
public static class TextAreaCell<S> extends TableCell<S, String> {
private TextArea textArea ;
public TextAreaCell(Function<S, Property<String>> propertyAccessor) {
textArea = new TextArea();
textArea.setWrapText(true);
textArea.setMinWidth(this.getWidth() - this.getGraphicTextGap() * 2);
textArea.setMaxHeight(Double.MAX_VALUE);
UnaryOperator<Change> filter = c -> {
String proposedText = c.getControlNewText() ;
Property<String> prop = propertyAccessor.apply(getTableView().getItems().get(getIndex()));
prop.setValue(proposedText);
if (prop.getValue().equals(proposedText)) {
return c ;
} else {
return null ;
}
};
textArea.setTextFormatter(new TextFormatter<String>(filter));
this.setGraphic(textArea);
}
#Override
protected void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (!empty) {
if (! textArea.getText().equals(item)) {
textArea.setText(item);
}
// Show the Text Field
this.setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
} else {
this.setContentDisplay(ContentDisplay.TEXT_ONLY);
}
}
}
public static class Item {
private final StringProperty name = new StringPropertyBase() {
#Override
public Object getBean() {
return Item.this;
}
#Override
public String getName() {
return "name" ;
}
#Override
public void set(String value) {
if (checkValue(value)) {
super.set(value);
}
}
#Override
public void setValue(String value) {
if (checkValue(value)) {
super.setValue(value);
}
}
};
private final StringProperty description = new SimpleStringProperty();
public Item(String name, String description) {
setName(name);
setDescription(description);
}
private boolean checkValue(String value) {
return value.length() <= 6 ;
}
public final StringProperty nameProperty() {
return this.name;
}
public final String getName() {
return this.nameProperty().get();
}
public final void setName(final String name) {
this.nameProperty().set(name);
}
public final StringProperty descriptionProperty() {
return this.description;
}
public final String getDescription() {
return this.descriptionProperty().get();
}
public final void setDescription(final String description) {
this.descriptionProperty().set(description);
}
}
public static void main(String[] args) {
launch(args);
}
}
Another approach is to allow a "commit and revert" type strategy on your property:
public class MyTextRow {
private final StringProperty text2 = new SimpleStringProperty();
public MyTextRow() {
text2.addListener((obs, oldText, newText) -> {
if (! checkText2(newText)) {
// sanity check:
if (checkText2(oldText)) {
text2.set(oldText);
}
}
});
}
public StringProperty text2Property() {
return text ;
}
public final void setText2(String text2) {
text2Property().set(text2);
}
public final String getText2() {
return text2Property().get();
}
}
In general I dislike validation by listening for an invalid value and reverting like this, because other listeners to the property will see all the changes, including changes to and from invalid values. However, this might be the best option in this case.
Finally, you could consider vetoing invalid changes as in the first option, and also setting a TextFormatter on the control in the cell that simply doesn't allow text entry that results in an invalid string. This isn't always possible from a usability perspective (e.g. if empty strings are invalid, you almost always want to allow the user to temporarily delete all the text), and it means keeping two validation checks in sync in your code, which is a pain.

AsyncTask Crashing on postExecute

I have a problem when using asyntask to query all the data in a table and put it in an array List and then send it to the server. I am able to send the data to the server successfully. But the application crashes on the postexecute of the asynctask giving the following error:
(W/System.err﹕ org.json.JSONException: Value ["com.atlantis.eclectics.agentbank.SyncMembersActivity$MemberRecords#41b06d18","com.atlantis.eclectics.agentbank.SyncMembersActivity$MemberRecords#41b070b8"] of type org.json.JSONArray cannot be converted to JSONObject)..
What could be problem? Where am i getting it wrong. Someone please help...Thanks very much.
package com.practical.tasks.school;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.NotificationManager;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.Toast;
import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.auth.BasicScheme;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.protocol.HTTP;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
#SuppressWarnings("deprecation")
public class SyncMembersActivity extends ActionBarActivity {
CustomHttpClient jParser = new CustomHttpClient();
ListView lstView;
public MainDB dbs;
public SQLiteDatabase db;
public static String fname;
String username = "atlantis";
String password = "#t1#ntis";
Button submit;
String statusN = "NO";
String statusY = "YES";
String url = "http://123.456.78.90:1234/Api/create/Post";
String FirstName = "";
String SecondName = "";
String MobileNumber = "";
String DateofBirth = "";
String Gender = "";
String GroupName = "";
String GroupAccountNo = "";
String IdentificationID = "";
String IdentificationType = null;
String CreatedBy = null;
String Residence = "";
private int notificationIdOne = 111;
private int numMessagesOne = 0;
private NotificationManager myNotificationManager;
String account_statusY = "True";
private ProgressDialog prgDialog;
private ArrayAdapter<String> listAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sync_members);
getSupportActionBar().setHomeButtonEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
getSupportActionBar().setHomeActionContentDescription("Services");
getSupportActionBar().setDisplayUseLogoEnabled(true);
getSupportActionBar().setLogo(R.mipmap.ic_launcher);
getSupportActionBar().setDisplayShowTitleEnabled(true);
getSupportActionBar().setBackgroundDrawable(new ColorDrawable(Color.parseColor("#5A92F7")));
lstView = (ListView) findViewById(R.id.lstSample);
submit = (Button) findViewById(R.id.upload);
prgDialog = new ProgressDialog(this);
prgDialog.setMessage("Please wait...");
prgDialog.setCancelable(false);
submit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
try {
if (isNetworkAvailable(getApplicationContext())) {
new HttpAsyncTask().execute(FirstName, SecondName, MobileNumber, DateofBirth, Gender, GroupName, GroupAccountNo, IdentificationID, IdentificationType, CreatedBy, Residence);
} else {
showAlert("No internet Connectivity...");
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_sync_members, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
public class MemberRecords {
String FirstName;
String SecondName;
String MobileNumber;
String DateofBirth;
String Gender;
String GroupName;
String GroupAccountNo;
String IdentificationID;
String IdentificationType;
String CreatedBy;
String Residence;
public String getFirstName() {
return FirstName;
}
public String getSecondName() {
return SecondName;
}
public String getMobileNumber() {
return MobileNumber;
}
public String getDateofBirth() {
return DateofBirth;
}
public String getGender() {
return Gender;
}
public String getGroupName() {
return GroupName;
}
public String getGroupAccountNo() {
return GroupAccountNo;
}
public String getIdentificationID() {
return IdentificationID;
}
public String getIdentificationType() {
return IdentificationType;
}
public String getCreatedBy() {
return CreatedBy;
}
public String getResidence() {
return Residence;
}
public void setFirstName(String newfirstName) {
FirstName = newfirstName;
}
public void setSecondName(String newSecondName) {
SecondName = newSecondName;
}
public void setMobileNumber(String mobileNumber) {
MobileNumber = mobileNumber;
}
public void setDateofBirth(String dateofBirth) {
DateofBirth = dateofBirth;
}
public void setGender(String gender) {
Gender = gender;
}
public void setGroupName(String groupName) {
GroupName = groupName;
}
public void setGroupAccountNo(String groupAccountNo) {
GroupAccountNo = groupAccountNo;
}
public void setIdentificationID(String identificationID) {
IdentificationID = identificationID;
}
public void setIdentificationType(String identificationType) {
IdentificationType = identificationType;
}
public void setCreatedBy(String createdBy) {
CreatedBy = createdBy;
}
public void setResidence(String residence) {
Residence = residence;
}
}
public boolean isConnected() {
ConnectivityManager connMgr = (ConnectivityManager) getSystemService(Activity.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
if (networkInfo != null && networkInfo.isConnected())
return true;
else
return false;
}
public static String POST(String url, MemberRecords my) {
InputStream inputStream;
String result = "";
String username = "atlantis";
String password = "#t1#ntis";
Integer n;
try {
// 1. create HttpClient
HttpClient httpclient = new DefaultHttpClient();
// 2. make POST request to the given URL
HttpPost httpPost = new HttpPost("http://41.186.47.26:4433/Api/Account/PostAddSignatory");
String json = "";
Log.e("Url", "Url Here:" + url);
// 3. build jsonObject
JSONObject jsonObject = new JSONObject();
jsonObject.accumulate("FirstName", my.getFirstName());
jsonObject.accumulate("SecondName", my.getSecondName());
jsonObject.accumulate("MobileNumber", my.getMobileNumber());
jsonObject.accumulate("DateofBirth", my.getDateofBirth());
jsonObject.accumulate("Gender", my.getGender());
jsonObject.accumulate("GroupName", my.getGroupName());
jsonObject.accumulate("GroupAccountNo", my.getGroupAccountNo());
jsonObject.accumulate("IdentificationID", my.getIdentificationID());
jsonObject.accumulate("IdentificationType", my.getIdentificationType());
jsonObject.accumulate("CreatedBy", my.getCreatedBy());
jsonObject.accumulate("Residence", my.getResidence());
json = jsonObject.toString();
Log.e("Url", "Request:" + json);
StringEntity se = new StringEntity(json);
httpPost.setHeader(HTTP.CONTENT_TYPE, "application/json");
UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(username, password);
Header header = new BasicScheme().authenticate(credentials, httpPost);
httpPost.addHeader(header);
httpPost.setEntity(se);
HttpResponse httpResponse = httpclient.execute(httpPost);
inputStream = httpResponse.getEntity().getContent();
if (inputStream != null)
result = convertInputStreamToString(inputStream);
else
result = "Did not work!";
} catch (Exception e) {
Log.e("InputStream", e.getLocalizedMessage());
//e.printStackTrace();
}
// 11. return result
return result;
}
private static String convertInputStreamToString(InputStream inputStream) throws IOException, JSONException {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String line = "";
String result = "";
while ((line = bufferedReader.readLine()) != null)
result += line;
Log.e("Url", "Response:" + result);
inputStream.close();
return result;
}
private class HttpAsyncTask extends AsyncTask<String, Void,String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
prgDialog.show();
}
#Override
protected String doInBackground(String... urls) {
dbs = new MainDB(SyncMembersActivity.this);
db = dbs.getWritableDatabase();
Integer n=null;
MemberRecords my = new MemberRecords();
List<MemberRecords> member_list = new ArrayList<>();
try {
Cursor cursor = db.rawQuery("SELECT * FROM tbl_memberData" +
" where sync_status = '" + statusN + "' AND account_status = '" + account_statusY + "'", null);
if (cursor.moveToFirst()) {
do {
my = new MemberRecords();
my.setGroupName(cursor.getString(1));
my.setIdentificationID(cursor.getString(2));
my.setIdentificationType(cursor.getString(3));
my.setFirstName(cursor.getString(4));
my.setSecondName(cursor.getString(5));
my.setDateofBirth(cursor.getString(6));
my.setMobileNumber(cursor.getString(7));
my.setGender(cursor.getString(8));
my.setGroupAccountNo(cursor.getString(9));
my.setCreatedBy(cursor.getString(10));
my.setResidence(cursor.getString(11));
member_list.add(my);
} while (cursor.moveToNext());
}
cursor.close();
} catch (NumberFormatException e) {
e.printStackTrace();
}
for ( n = 0; n < member_list.size(); n++) {
POST(url, member_list.get(n));
}
db.close();
return String.valueOf(member_list);
}
//onPostExecute displays the results of the AsyncTask.
//Response format
//Response:{"ResponseCode":"00","ResponseMsg":"Successful"}
//Response:{"ResponseCode":"01","ResponseMsg":"Failed"}
#Override
protected void onPostExecute (String result){
prgDialog.dismiss();
Toast.makeText(getBaseContext(),"Saved Successfully",Toast.LENGTH_LONG).show();
dbs = new MainDB(SyncMembersActivity.this);
db = dbs.getWritableDatabase();
String updateQuery = "Update tbl_memberData set sync_status = '" + statusY + "' where account_status='" + account_statusY + "'";
db.execSQL(updateQuery);
String success="";
String message="";
try {
JSONObject jsonBreaker = new JSONObject(result);
success = jsonBreaker.getString("ResponseCode");
message = jsonBreaker.getString("ResponseMsg");
if (success.equalsIgnoreCase("00")) {
prgDialog.dismiss();
showAlert(message);
} else if (success.equalsIgnoreCase("01")) {
prgDialog.dismiss();
//do
showAlert(message);
} else {
prgDialog.dismiss();
Toast.makeText(getBaseContext(), "Error, Please try again...", Toast.LENGTH_LONG).show();
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
private void showAlert(String message) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage(message).setTitle("Response from Server")
.setCancelable(false)
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// do nothing
}
});
AlertDialog alert = builder.create();
alert.show();
}
public boolean isNetworkAvailable(final Context context) {
final ConnectivityManager connectivityManager = ((ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE));
return connectivityManager.getActiveNetworkInfo() != null && connectivityManager.getActiveNetworkInfo().isConnected();
}
}
If you would baste stacktrace and opoint where rxception is thrown would be much easier.
Anyway
Your result is probably and JSONArray not an JSONObject so this
JSONObject jsonBreaker = new JSONObject(result);
Is causing the exception. Construct JSONArray insteed of JSONObject and this shoult be fine (this is my blind guess cuz no viable info here)

Validation Error: value is not vaild

This error is happening sometimes. It's not always that happens, and so I am not able to find solution. The error happens when I select an item from the list (I repeat, the error only happens SOMETIMES).
I've implemented the methods 'equals' and 'hashCode' and created the converter.
See the code below:
<p:outputLabel for="pais" value="País:" />
<p:selectOneMenu id="pais" value="#{clienteController.pais}" >
<f:selectItem itemLabel="Selecione..." itemValue="" />
<f:selectItems value="#{clienteController.paises}" var="p" itemLabel="#{p.nome}" itemValue="#{p}"/>
<p:ajax event="change" listener="#{clienteController.actionCarregaUfs}" update="uf" />
</p:selectOneMenu>
package control;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.FacesConverter;
import dao.PaisDao;
import dao.PaisDaoImp;
import model.Pais;
#FacesConverter(forClass=Pais.class)
public class PaisConverter implements Converter {
#Override
public Object getAsObject(FacesContext arg0, UIComponent arg1, String value) {
if (value != null && !value.equals("")) {
PaisDao paisDao = new PaisDaoImp();
return paisDao.findById(Integer.valueOf(value));
}
return null;
}
#Override
public String getAsString(FacesContext arg0, UIComponent arg1, Object value) {
if (value instanceof Pais) {
Pais pais = (Pais) value;
return String.valueOf(pais.getCodigo());
}
return "";
}
}
package control;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.model.DataModel;
import javax.faces.model.ListDataModel;
import javax.faces.model.SelectItem;
import dao.ClienteDao;
import dao.ClienteDaoImp;
import dao.PaisDaoImp;
import dao.TipoDocumentoDaoImp;
import dao.UnidadeFederacaoDaoImp;
import model.Cliente;
import model.Municipio;
import model.Pais;
import model.TipoDocumento;
import model.UnidadeFederacao;
#ManagedBean
#ViewScoped
public class ClienteController implements Serializable {
private Cliente cliente;
private DataModel listaClientes;
private List<Cliente> filteredClientes;
private Boolean isInsercao;
private Boolean isAlteracao;
private Pais pais;
private List<Pais> paises;
private List<UnidadeFederacao> ufs;
private UnidadeFederacao uf;
private List<Municipio> municipios;
private List<TipoDocumento> tiposDocumentos;
public ClienteController() {
this.cliente = new Cliente();
this.pais = new Pais();
this.ufs = new ArrayList<UnidadeFederacao>();
this.uf = new UnidadeFederacao();
this.municipios = new ArrayList<Municipio>();
this.tiposDocumentos = new ArrayList<TipoDocumento>();
}
public List<Cliente> getFilteredClientes() {
return filteredClientes;
}
public void setFilteredClientes(List<Cliente> filteredClientes) {
this.filteredClientes = filteredClientes;
}
public DataModel getListarClientes() {
List<Cliente> lista = new ClienteDaoImp().list();
listaClientes = new ListDataModel(lista);
return listaClientes;
}
public Cliente getCliente() {
return cliente;
}
public void setCliente(Cliente cliente) {
this.cliente = cliente;
}
public String prepararAdicionarCliente() {
cliente = new Cliente();
isInsercao = true;
isAlteracao = false;
return "gerenciarCliente";
}
public String prepararAlterarCliente() {
isInsercao = false;
isAlteracao = true;
this.pais = this.cliente.getMunicipio().getUf().getPais();
this.uf = this.cliente.getMunicipio().getUf();
return "gerenciarCliente";
}
public String excluirCliente() {
Cliente clienteTemp = (Cliente) (listaClientes.getRowData());
ClienteDao dao = new ClienteDaoImp();
dao.remove(clienteTemp);
return "index";
}
public String actExcluirCliente() {
ClienteDao dao = new ClienteDaoImp();
dao.remove(cliente);
return "index";
}
public String adicionarCliente() {
System.out.println("Adicionando Cliente...");
ClienteDao dao = new ClienteDaoImp();
dao.save(cliente);
return "index";
}
public String alterarCliente() {
ClienteDao dao = new ClienteDaoImp();
dao.update(cliente);
return "index";
}
public Boolean getIsInsercao() {
return isInsercao;
}
public void setIsInsercao(Boolean insercao) {
this.isInsercao = insercao;
}
public Boolean getIsAlteracao() {
return isAlteracao;
}
public void setIsAlteracao(Boolean alteracao) {
this.isAlteracao = alteracao;
}
/**************************************************/
public Pais getPais() {
return pais;
}
public void setPais(Pais pais) {
this.pais = pais;
}
public List<Pais> getPaises() {
paises = new PaisDaoImp().list();
return paises;
}
public void setPaises(List<Pais> paises) {
this.paises = paises;
}
public List<UnidadeFederacao> getUfs() {
return ufs;
}
public void setUfs(List<UnidadeFederacao> ufs) {
this.ufs = ufs;
}
public UnidadeFederacao getUf() {
return uf;
}
public void setUf(UnidadeFederacao uf) {
this.uf = uf;
}
public List<Municipio> getMunicipios() {
return municipios;
}
public void setMunicipios(List<Municipio> municipios) {
this.municipios = municipios;
}
public List<UnidadeFederacao> getUfsByPais() {
ufs = new PaisDaoImp().getUFsByPais(this.pais.getCodigo());
return ufs;
}
public void actionCarregaUfs() {
ufs.clear();
if (this.pais != null) {
if (!String.valueOf(this.pais.getCodigo()).equals("")) {
this.getUfsByPais();
}
}
}
public List<Municipio> getMunicipiossByUf() {
municipios = new UnidadeFederacaoDaoImp().getMunicipiosByUF(this.uf.getCodigo());
return municipios;
}
public void actionCarregaMunicipios() {
municipios.clear();
try {
this.uf.getCodigo();
} catch(NullPointerException e) {
return;
}
this.getMunicipiossByUf();
}
public List<TipoDocumento> getTiposDocumentos() {
tiposDocumentos = new TipoDocumentoDaoImp().list();
return tiposDocumentos;
}
}
package model;
import java.io.Serializable;
import java.util.List;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
#Entity
#Table(name = "pais")
public class Pais implements Serializable {
#Id
#Column(name = "id_pais")
private Integer codigo;
#Column(length = 4)
private String sigla;
private String nome;
#OneToMany(mappedBy = "pais")
private List<UnidadeFederacao> unidadesFederacao;
public Pais() {
}
public Object getId() {
return nome;
}
public Integer getCodigo() {
return codigo;
}
public void setCodigo(Integer codigo) {
this.codigo = codigo;
}
public String getSigla() {
return sigla;
}
public void setSigla(String sigla) {
this.sigla = sigla;
}
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
public List<UnidadeFederacao> getUnidadesFederacao() {
return unidadesFederacao;
}
public void setUnidadesFederacao(List<UnidadeFederacao> unidadesFederacao) {
this.unidadesFederacao = unidadesFederacao;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((codigo == null) ? 0 : codigo.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (!(obj instanceof Pais))
return false;
Pais other = (Pais) obj;
if (codigo == null) {
if (other.codigo != null)
return false;
} else if (!codigo.equals(other.codigo))
return false;
return true;
}
}

Resources