NotSerializableException with BasicDataSource in JNDI - datasource

I am setting up a standalone JNDI and loading a Datasource to the JNDI.
DataSource I use is: org.apache.commons.dbcp.BasicDataSource
The JNDI is set up as follows
String detectorHost = InetAddress.getLocalHost().getHostName();
System.out.println("detectorHost: " + detectorHost);
System.setProperty(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");
final NamingBeanImpl namingInfo = new NamingBeanImpl();
namingInfo.start();
final Main JNDIServer = new Main();
JNDIServer.setNamingInfo( namingInfo );
JNDIServer.setPort( 5400 );
JNDIServer.setBindAddress(InetAddress.getLocalHost().getHostName());
JNDIServer.start();
final Hashtable _properties = new Hashtable();
_properties.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");
_properties.put(Context.PROVIDER_URL, "jnp://" + InetAddress.getLocalHost().getHostName() + ":5400");
final Context _context = new InitialContext(_properties);
_context.createSubcontext("jdbc");
String JNDI_PATH = "jdbc" + "/" + "mydbname";
_context.bind(JNDI_PATH, getDataSource());
I get the following exception
javax.naming.CommunicationException [Root exception is java.io.NotSerializableException: org.apache.commons.dbcp.BasicDataSource]
at org.jnp.interfaces.NamingContext.bind(NamingContext.java:677)
at org.jnp.interfaces.NamingContext.bind(NamingContext.java:611)
at javax.naming.InitialContext.bind(Unknown Source)
at com.lombardrisk.reform.integration.ReformIntegration.createJNDIServer(ReformIntegration.java:93)
at com.lombardrisk.reform.integration.ReformIntegration.main(ReformIntegration.java:44)
Caused by: java.io.NotSerializableException: org.apache.commons.dbcp.BasicDataSource
at java.io.ObjectOutputStream.writeObject0(Unknown Source)
at java.io.ObjectOutputStream.writeObject(Unknown Source)
at java.rmi.MarshalledObject.<init>(Unknown Source)
at org.jnp.interfaces.MarshalledValuePair.<init>(MarshalledValuePair.java:65)
at org.jnp.interfaces.NamingContext.createMarshalledValuePair(NamingContext.java:1425)
at org.jnp.interfaces.NamingContext.bind(NamingContext.java:640)
I don't quite follow why I am getting a NotSerializableException exception, this is a local JNDI in the same JVM and not a remote JNDI. Not sure why this occurs.
Can some one advise what is wrong here.
regards
D

The exception was misleading. The exception became clear after adding the following to the JVM startup
-Dsun.io.serialization.extendedDebugInfo=true
It appears I was not using the correct libraries.
I have explained the full problem and solution here in this link.
https://community.jboss.org/thread/241498
//Code to start a JNDI Server and a test client for the JNDI Context
import javax.naming.Context;
import javax.naming.InitialContext;
import org.apache.log4j.Logger;
import org.jnp.server.Main;
import org.jnp.server.NamingBeanImpl;
//Snippet of the code
System.setProperty("java.rmi.server.hostname", "localhost");
System.setProperty("java.naming.factory.initial", "org.jnp.interfaces.NamingContextFactory");
System.setProperty("java.naming.factory.url.pkgs", "org.jboss.naming:org.jnp.interfaces");
final NamingBeanImpl namingInfo = new NamingBeanImpl();
namingInfo.start();
final Main jndiServer = new Main();
jndiServer.setNamingInfo(namingInfo);
jndiServer.setPort(1099);
jndiServer.setBindAddress("localhost");
jndiServer.setRmiPort(1098);
jndiServer.setRmiBindAddress("localhost");
jndiServer.start();
final Hashtable<String, String> _properties = new Hashtable<String, String> ();
_properties.put(Context.INITIAL_CONTEXT_FACTORY, "org.apache.naming.java.javaURLContextFactory");
_properties.put(Context.PROVIDER_URL, "jnp://" + "localhost" + ":1099");
final Context _context = new InitialContext(_properties);
_context.createSubcontext("jdbc");
JdbcTemplate jdbcTemplate = new JdbcTemplate(getDataSource());
System.out.println("jdbcTemplate: " + jdbcTemplate.getClass());
System.out.println("getDataSource(): " + getDataSource().getClass());
_context.bind("/jdbc/reformDS", getDataSource());
//JNDI started
//Test the JNDI context
// There are 2 ways to test -
// Option 1: create a HashTable and pass the properties to the InitialContext constructor
final Hashtable<String, String> _properties = new Hashtable<String, String> ();
_properties.put(Context.INITIAL_CONTEXT_FACTORY, "org.apache.naming.java.javaURLContextFactory");
_properties.put(Context.PROVIDER_URL, "jnp://" + "localhost" + ":1099");
final Context _context = new InitialContext(_properties);
Object obj = _context.lookup("/jdbc/reformDS");
if (null != obj) {
System.out.println("OBJ: " + obj.getClass());
org.apache.commons.dbcp.BasicDataSource ds = (org.apache.commons.dbcp.BasicDataSource)obj;
JdbcTemplate jdbcTemplate2 = new JdbcTemplate(ds);
String sql = String.format("update MESSAGE_LOG set PROCESS_INSTANCE_ID = 123456 where ID =42395 ");
int update = jdbcTemplate2.update(sql);
System.out.println("Update*****************: " + update);
}
// Option 2: Set the System.properties and call the InitialContext
System.getProperty(Context.INITIAL_CONTEXT_FACTORY, "org.apache.naming.java.javaURLContextFactory");
System.getProperty(Context.PROVIDER_URL, "jnp://" + "localhost" + ":1099");
final Context _context = new InitialContext();
Object obj = _context.lookup("/jdbc/reformDS");
if (null != obj) {
System.out.println("OBJ: " + obj.getClass());
org.apache.commons.dbcp.BasicDataSource ds = (org.apache.commons.dbcp.BasicDataSource)obj;
JdbcTemplate jdbcTemplate2 = new JdbcTemplate(ds);
String sql = String.format("update MESSAGE_LOG set PROCESS_INSTANCE_ID = 123456 where ID =42395 ");
int update = jdbcTemplate2.update(sql);
System.out.println("Update*****************: " + update);
}

Related

Create and query a binary cache in ignite

I am trying to use BinaryObjects to create the cache at runtime. For example, instead of writing a pojo class such as Employee and configuring it as a cache value type, I need to be able to dynamically configure the cache with the field names and field types for the particular cache.
Here is some sample code:
public class EmployeeQuery {
public static void main(String[] args) throws Exception {
Ignition.setClientMode(true);
try (Ignite ignite = Ignition.start("examples/config/example-ignite.xml")) {
if (!ExamplesUtils.hasServerNodes(ignite))
return;
CacheConfiguration<Integer, BinaryObject> cfg = getbinaryCache("emplCache", 1);
ignite.destroyCache(cfg.getName());
try (IgniteCache<Integer, BinaryObject> emplCache = ignite.getOrCreateCache(cfg)) {
SqlFieldsQuery top5Qry = new SqlFieldsQuery("select * from Employee where salary > 500 limit 5", true);
while (true) {
QueryCursor<List<?>> top5qryResult = emplCache.query(top5Qry);
System.out.println(">>> Employees ");
List<List<?>> all = top5qryResult.getAll();
for (List<?> list : all) {
System.out.println("Top 5 query result : "+list.get(0) + " , "+ list.get(1) + " , " + list.get(2));
}
System.out.println("..... ");
Thread.sleep(5000);
}
}
finally {
ignite.destroyCache(cfg.getName());
}
}
}
private static QueryEntity createEmployeeQueryEntity() {
QueryEntity employeeEntity = new QueryEntity();
employeeEntity.setTableName("Employee");
employeeEntity.setValueType(BinaryObject.class.getName());
employeeEntity.setKeyType(Integer.class.getName());
LinkedHashMap<String, String> fields = new LinkedHashMap<>();
fields.put("id", Integer.class.getName());
fields.put("firstName", String.class.getName());
fields.put("lastName", String.class.getName());
fields.put("salary", Float.class.getName());
fields.put("gender", String.class.getName());
employeeEntity.setFields(fields);
employeeEntity.setIndexes(Arrays.asList(
new QueryIndex("id"),
new QueryIndex("firstName"),
new QueryIndex("lastName"),
new QueryIndex("salary"),
new QueryIndex("gender")
));
return employeeEntity;
}
public static CacheConfiguration<Integer, BinaryObject> getbinaryCache(String cacheName, int duration) {
CacheConfiguration<Integer, BinaryObject> cfg = new CacheConfiguration<>(cacheName);
cfg.setCacheMode(CacheMode.PARTITIONED);
cfg.setName(cacheName);
cfg.setStoreKeepBinary(true);
cfg.setAtomicityMode(CacheAtomicityMode.ATOMIC);
cfg.setIndexedTypes(Integer.class, BinaryObject.class);
cfg.setExpiryPolicyFactory(FactoryBuilder.factoryOf(new CreatedExpiryPolicy(new Duration(SECONDS, duration))));
cfg.setQueryEntities(Arrays.asList(createEmployeeQueryEntity()));
return cfg;
}
}
I am trying to configure the cache with the employeeId (Integer) as key and the whole employee record (BinaryObject) as value. When I run the above class, I get the following exception :
Caused by: org.h2.jdbc.JdbcSQLException: Table "EMPLOYEE" not found; SQL statement:
select * from "emplCache".Employee where salary > 500 limit 5
What am I doing wrong here? Is there anything more other than this line:
employeeEntity.setTableName("Employee");
Next, I am trying to stream data into the cache. Is this the right way to do it?
public class CsvStreamer {
public static void main(String[] args) throws IOException {
Ignition.setClientMode(true);
try (Ignite ignite = Ignition.start("examples/config/example-ignite.xml")) {
if (!ExamplesUtils.hasServerNodes(ignite))
return;
CacheConfiguration<Integer, BinaryObject> cfg = EmployeeQuery.getbinaryCache("emplCache", 1);
try (IgniteDataStreamer<Integer, BinaryObject> stmr = ignite.dataStreamer(cfg.getName())) {
while (true) {
InputStream in = new FileInputStream(new File(args[0]));
try (LineNumberReader rdr = new LineNumberReader(new InputStreamReader(in))) {
int count =0;
for (String line = rdr.readLine(); line != null; line = rdr.readLine()) {
String[] words = line.split(",");
BinaryObject emp = getBinaryObject(words);
stmr.addData(new Integer(words[0]), emp);
System.out.println("Sent data "+count++ +" , sal : "+words[6]);
}
}
}
}
}
}
private static BinaryObject getBinaryObject(String[] rawData) {
BinaryObjectBuilder builder = Ignition.ignite().binary().builder("Employee");
builder.setField("id", new Integer(rawData[0]));
builder.setField("firstName", rawData[1]);
builder.setField("lastName", rawData[2]);
builder.setField("salary", new Float(rawData[6]));
builder.setField("gender", rawData[4]);
BinaryObject binaryObj = builder.build();
return binaryObj;
}
}
Note: I am running this in cluster mode. Both EmployeeQuery and CsvStreamer I run from one machine, and I have ignite running in server mode in two other machines. Ideally I want to avoid the use of a pojo class in my application and make things as dynamic and generic as possible.
You are getting this exception because you didn't configure SQL scheme. In your case (you don't want to create pojo object and etc) I recommend to use SQL like syntacsis which was added to Apache Ignite since 2.0 version. I sure that the following example helps you with configuration: https://github.com/apache/ignite/blob/master/examples/src/main/java/org/apache/ignite/examples/datagrid/CacheQueryDdlExample.java

javax.naming.CommunicationException: Connection reset [Root exception is java.net.SocketException: Connection reset]; remaining name

I am getting socket exception when I try to connect LDAP. Here is my sample code. I am seeing this issue in java 8. I never observed this issue in the earlier java versions.
public static DirContext getDirectoryContext() throws NamingException {
Properties env = new Properties();
env.put(Context.INITIAL_CONTEXT_FACTORY,
Common.getProperty("ldap.context.factory"));
env.put(Context.PROVIDER_URL,
Common.getProperty("ldap.provider.url"));
env.put(Context.SECURITY_AUTHENTICATION,
Common.getProperty("ldap.security.authentication"));
env.put(Context.SECURITY_PRINCIPAL,
Common.getProperty("ldap.security.principal"));
env.put(Context.SECURITY_CREDENTIALS,
Common.getProperty("ldap.security.credential"));
context = new InitialDirContext(env);
log.debug("NamingContext Initialized");
return context;
}
context = getDirectoryContext();
I am using the same context for all LDAP calls.
private NamingEnumeration getResultsFromLdap(String searchFilter) {
NamingEnumeration results = null;
try {
// Getting the list from LDAP matching the given filter
SearchControls sControls = new SearchControls();
sControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
String baseContext = Common.getProperty("ldap.base.context");
results = context.search(baseContext, searchFilter, sControls);
} catch (Exception e) {
log.error("EXCEPTION IN getLDAPConnection METHOD, searchFilter : "
+ searchFilter + " : Exception Message : " + e.getMessage());
}
return results;
} // End of getLDAPConnection_SearchResults
Can someone help?

Eclipselink Moxy error for native datatype

I'm able to bind complex objects (bs2 in code below) but getting error while doing for String (bs1 in code below) . using Eclipselink 2.4.2. Please see code:
private static void initJAXBContext() {
String bs1 = "<?xml version=\"1.0\"?>\n" +
"<xml-bindings\n" +
" xmlns=\"http://www.eclipse.org/eclipselink/xsds/persistence/oxm\"\n" +
" package-name=\"java.lang\" >\n" +
" <xml-schema element-form-default=\"QUALIFIED\" namespace=\"java.lang\">\n" +
" <xml-ns prefix=\"sc\" namespace-uri=\"java.lang\"/>\n" +
" </xml-schema>\n" +
" <java-types>\n" +
" <java-type name=\"java.lang.String\">\n" +
" <xml-root-element/>\n" +
" </java-type>\n" +
" </java-types>\n" +
"</xml-bindings>";
String bs2 = "<?xml version=\"1.0\"?>\n" +
"<xml-bindings\n" +
" xmlns=\"http://www.eclipse.org/eclipselink/xsds/persistence/oxm\"\n" +
" package-name=\"test\" >\n" +
" <xml-schema element-form-default=\"QUALIFIED\" namespace=\"test\">\n" +
" <xml-ns prefix=\"sc\" namespace-uri=\"test\"/>\n" +
" </xml-schema>\n" +
" <java-types>\n" +
" <java-type name=\"test.TestService\">\n" +
" <xml-root-element/>\n" +
" </java-type>\n" +
" </java-types>\n" +
"</xml-bindings>";
List<Object> fl = new ArrayList<Object>();
Map<String, Object> properties = new HashMap<String, Object>();
try {
InputStream iStream2 = new ByteArrayInputStream(bs1.getBytes("UTF-8"));
fl.add(iStream2);
properties.put(JAXBContextProperties.OXM_METADATA_SOURCE, fl);
System.out.println("before jaxb");
JAXBContext context = (org.eclipse.persistence.jaxb.JAXBContext) JAXBContext.newInstance("test", Class.forName("test.TestService").getClassLoader(), properties);
System.out.println("after jaxb");
} catch (Exception e) {
System.out.println("Exception: " + e);
e.printStackTrace();
}
}
Above code works fine for bs2. But gives following exception for bs1:
---------------------------------------------------------------------------------------
javax.xml.bind.JAXBException
- with linked exception:
[java.lang.NullPointerException]
at org.eclipse.persistence.jaxb.JAXBContext$ContextPathInput.createContextState(JAXBContext.java:915)
at org.eclipse.persistence.jaxb.JAXBContext$ContextPathInput.createContextState(JAXBContext.java:848)
at org.eclipse.persistence.jaxb.JAXBContext.<init>(JAXBContext.java:182)
at org.eclipse.persistence.jaxb.JAXBContextFactory.createContext(JAXBContextFactory.java:129)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:128)
at javax.xml.bind.ContextFinder.find(ContextFinder.java:249)
at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:372)
at GenericTest.initJAXBContext(GenericTest.java:337)
at GenericTest.main(GenericTest.java:366)
Caused by: java.lang.NullPointerException
at org.eclipse.persistence.jaxb.compiler.XMLProcessor.processXML(XMLProcessor.java:249)
at org.eclipse.persistence.jaxb.compiler.Generator.<init>(Generator.java:104)
at org.eclipse.persistence.jaxb.JAXBContext$ContextPathInput.createContextState(JAXBContext.java:912)
... 12 more
---------------------------------------------------------------------------------------
Can you please let me know the issue with binding string bs1.
Thanks in advance,
Vikas
EclipseLink JAXB (MOXy) does not allow you to treat a data type as a domain object. Below is an example of handling a String as a top level object.
import java.io.StringReader;
import javax.xml.bind.*;
import javax.xml.namespace.QName;
import javax.xml.transform.stream.StreamSource;
public class Example {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Example.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
StreamSource xml = new StreamSource(new StringReader("<foo>Hello World</foo>"));
JAXBElement<String> unmarshalJAXBElement = unmarshaller.unmarshal(xml, String.class);
String string = unmarshalJAXBElement.getValue();
System.out.println(string);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
JAXBElement<String> marshalJAXBElement = new JAXBElement<String>(new QName("bar"), String.class, string);
marshaller.marshal(marshalJAXBElement, System.out);
}
Output from running above code:
Hello World
<?xml version="1.0" encoding="UTF-8"?>
<bar>Hello World</bar>
}

httpcomponents's ssl connection results in socket is closed

I am trying to get some data from webserver which works fine with http.
But when I try https(ssl connection), I get the exceptions like below.
I get the http status code 200 and response content length 2230 which is correct.
java.net.SocketException: Socket is closed
at sun.security.ssl.SSLSocketImpl.checkEOF(SSLSocketImpl.java:1483)
at sun.security.ssl.AppInputStream.read(AppInputStream.java:92)
at org.apache.http.impl.io.AbstractSessionInputBuffer.fillBuffer(AbstractSessionInputBuffer.java:166)
at org.apache.http.impl.io.SocketInputBuffer.fillBuffer(SocketInputBuffer.java:90)
at org.apache.http.impl.io.AbstractSessionInputBuffer.read(AbstractSessionInputBuffer.java:183)
at org.apache.http.impl.io.ContentLengthInputStream.read(ContentLengthInputStream.java:144)
at org.apache.http.conn.EofSensorInputStream.read(EofSensorInputStream.java:121)
My code is like below with apache httpcomponents httpclient(4.2.5) library.
try {
HttpPost httppost = new HttpPost(uri);
HttpHost targetHost = new HttpHost(HOST_NAME, HOST_PORT, PROTOCOL);
InputStreamEntity reqEntity = new InputStreamEntity(new ByteArrayInputStream(request), -1);
String contentType = TSPConstants.CONST_TSA_CONTENT_TYPE_TSREQUEST;
reqEntity.setContentType(contentType);
reqEntity.setChunked(true);
// It may be more appropriate to use FileEntity class in this particular
// instance but we are using a more generic InputStreamEntity to demonstrate
// the capability to stream out data from any arbitrary source
//
// FileEntity entity = new FileEntity(file, "binary/octet-stream");
httppost.setEntity(reqEntity);
//Authentication
httpclient.getCredentialsProvider().setCredentials(
new AuthScope(targetHost.getHostName(), targetHost.getPort()),
new UsernamePasswordCredentials(id, password));
// Create AuthCache instance
AuthCache authCache = new BasicAuthCache();
// Generate BASIC scheme object and add it to the local
// auth cache
BasicScheme basicAuth = new BasicScheme();
authCache.put(targetHost, basicAuth);
// Add AuthCache to the execution context
BasicHttpContext httpContext = new BasicHttpContext();
httpContext.setAttribute(ClientContext.AUTH_CACHE, authCache);
httpContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);
//SSL
SSLContext ctx = SSLContext.getInstance("TLS");
X509TrustManager tm = new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] xcs, String string) throws CertificateException { }
public void checkServerTrusted(X509Certificate[] xcs, String string) throws CertificateException { }
public X509Certificate[] getAcceptedIssuers() {
return null;
}
};
ctx.init(null, new TrustManager[]{tm}, null);
SSLSocketFactory ssf = new SSLSocketFactory(ctx, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
Scheme sch = new Scheme("https", HOST_PORT, ssf);
httpclient.getConnectionManager().getSchemeRegistry().register(sch);
System.out.println("executing request " + httppost.getRequestLine());
httpclient.execute(httppost, httpContext);
HttpResponse response = send(request);
HttpEntity resEntity = response.getEntity();
System.out.println("----------------------------------------");
System.out.println(response.getStatusLine());
if (resEntity != null) {
System.out.println("Response content length: " + resEntity.getContentLength());
System.out.println("Chunked?: " + resEntity.isChunked());
}
EntityUtils.consume(resEntity);
resEntity.getContent()
} finally {
// When HttpClient instance is no longer needed,
// shut down the connection manager to ensure
// immediate deallocation of all system resources
httpclient.getConnectionManager().shutdown();
}
Basically the answer gave #Avner in the comment.
The problem (for me) was, that the response was closed before the entity was read.
I did something like this, which was wrong:
HttpEntity entity = null;
try (CloseableHttpResponse response = client.execute(request)) {
entity = response.getEntity();
}
read(entity);
The following worked:
try (CloseableHttpResponse response = client.execute(request)) {
HttpEntity entity = response.getEntity();
read(entity);
}
The maybe not so obvious part: The try-with-resources block in the first example closed the stream, before it was read.

Powermock: ProcessBuilder redirectErrorStream giving nullPointerException

I am using powermock to mock some native command invocation using process builder. the strange thing is these test pass sometimes and fail sometimes giving a NPE. Is this a powermock issue or some gotcha in the program.
Here is a snippet of the class I am testing:
public void method1(String jsonString, String filename) {
try {
JSONObject jObj = new JSONObject(jsonString);
JSONArray jArr = jObj.getJSONArray("something");
String cmd = "/home/y/bin/perl <perlscript>.pl<someConstant>" + " -k " + <someConstant> + " -t " + <someConstant>;
cmd += vmArr.getJSONObject(i).getString("jsonKey");
ProcessBuilder pb = new ProcessBuilder("bash", "-c", cmd);
pb.redirectErrorStream(false);
Process shell = pb.start();
shell.waitFor();
if (shell.exitValue() != 0) {
throw new RuntimeException("Error in Collecting the logs. cmd="+cmd);
}
StringBuilder error = new StringBuilder();
InputStream iError = shell.getErrorStream();
BufferedReader bfr =
new BufferedReader(
new InputStreamReader(iError));
String line = null;
while ((line = bfr.readLine()) != null) {
error.append(line + "\n");
}
if (!error.toString().isEmpty()) {
LOGGER.error(error`enter code here`);
}
iError.close();
bfr.close();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
and the unit test case is:
#PrepareForTest( {<Classtobetested>.class, ProcessBuilder.class,Process.class, InputStream.class,InputStreamReader.class, BufferedReader.class} )
#Test(sequential=true)
public class TestClass {
#Test(groups = {"unit"})
public void testMethod() {
try {
ProcessBuilder prBuilderMock = createMock(ProcessBuilder.class);
Process processMock = createMock(Process.class);
InputStream iStreamMock = createMock(InputStream.class);
InputStreamReader iStrRdrMock = createMock(InputStreamReader.class);
BufferedReader bRdrMock = createMock(BufferedReader.class);
String errorStr =" Error occured";
String json = <jsonStringInput>;
String cmd = "/home/y/bin/perl <perlscript>.pl -k "+<someConstant>+" -t "+<someConstant>+" "+<jsonValue>;
expectNew(ProcessBuilder.class, "bash", "-c", cmd).andReturn(prBuilderMock);
expect(prBuilderMock.redirectErrorStream(false)).andReturn(prBuilderMock);
expect(prBuilderMock.start()).andReturn(processMock);
expect(processMock.waitFor()).andReturn(0);
expect(processMock.exitValue()).andReturn(0);
expect(processMock.getErrorStream()).andReturn(iStreamMock);
expectNew(InputStreamReader.class, iStreamMock)
.andReturn(iStrRdrMock);
expectNew(BufferedReader.class, iStrRdrMock)
.andReturn(bRdrMock);
expect(bRdrMock.readLine()).andReturn(errorStr);
expect(bRdrMock.readLine()).andReturn(null);
iStreamMock.close();
bRdrMock.close();
expectLastCall().once();
replayAll();
<ClassToBeTested> instance = new <ClassToBeTested>();
instance.method1(json, fileName);
verifyAll();
} catch (Exception e) {
Assert.fail("failed while collecting log.", e);
}
}
I get an error on execution and the test case fails..
Caused by: java.lang.NullPointerException
at java.lang.ProcessBuilder.start(ProcessBuilder.java:438)
Note: I do not get this error on all executions. Sometimes it passes and sometimes it fails. I am not able to understand this behavior. Also, I have camouflaged some variable names because of the copyright issues.
Since your are mocking the constructor call you have to prepare your code as wall. This is because the constructor invocation is part of your code. Read more in the PowerMock documentation:
http://code.google.com/p/powermock/wiki/MockConstructor