Spring sftp - failed to read file; nested exception is 4 - java

Every now and then I get the exception pointed out in the title. Does anyone know what exception 4 means or where this is documented? I've looked at questions relating to this and I've learned that there's exception 2 which apparently means "No such file" and exception 3 which is "Permission Denied". However, when I get nested exception is 4, there is no description so I'm not sure what this means. Is it just a generic read time out? This happens very infrequently, and it's difficult to reproduce, as some of our users have no issues at all, while some run into this issue every now and then.
org.springframework.core.NestedIOException: failed to read file /ftadv:D=IBM-037,C=UTF-8/__'MAIN.FRAME.DATASET'; nested exception is 4:
at org.springframework.integration.sftp.session.SftpSession.readRaw(SftpSession.java:143)
at org.springframework.integration.file.remote.session.CachingSessionFactory$CachedSession.readRaw(CachingSessionFactory.java:268)
at org.springframework.integration.file.remote.session.CachingSessionFactory$CachedSession.readRaw(CachingSessionFactory.java:268)
at com.my.package.FTPService.ftpStoreAuthData(FTPService.java:166)
at com.my.package.FTPService.ftpStoreNetAuthData(FTPService.java:59)
at com.my.package.FTPEndpoint.ftpStoreNetAuthData(FTPEndpoint.java:27)
Here's my config if it helps.
#Configuration
class SftpConfiguration {
#Inject
private Environment env;
SessionFactory<LsEntry> getSftpSessionFactory() {
DefaultSftpSessionFactory sftpSessionFactory =
new DefaultSftpSessionFactory(Boolean.parseBoolean(env.getRequiredProperty("sftp.isSharedSession")));
sftpSessionFactory.setHost(env.getRequiredProperty("sftp.host"));
sftpSessionFactory.setPort(Integer.parseInt(env.getRequiredProperty("sftp.port")));
sftpSessionFactory.setUser(env.getRequiredProperty("sftp.id"));
sftpSessionFactory.setPrivateKey(new FileSystemResource(env.getRequiredProperty("sftp.keyPath")));
sftpSessionFactory.setPrivateKeyPassphrase(env.getRequiredProperty("sftp.passphrase"));
sftpSessionFactory.setTimeout(Integer.parseInt(env.getRequiredProperty("sftp.timeout")));
sftpSessionFactory.setAllowUnknownKeys(Boolean.parseBoolean(env.getRequiredProperty("sftp.allowUnknownKeys")));
return new CachingSessionFactory<LsEntry>(sftpSessionFactory);
}
CachingSessionFactory getCachingSessionFactory(){
CachingSessionFactory cachingSessionFactory = new CachingSessionFactory(getSftpSessionFactory());
cachingSessionFactory.setSessionWaitTimeout(Integer.parseInt(env.getRequiredProperty("sftp.sessionWaitTimeout")));
cachingSessionFactory.setPoolSize(Integer.parseInt(env.getRequiredProperty("sftp.poolSize")));
return cachingSessionFactory;
}
}
And here's an example of the calling code:
#Service
class FTPService {
private static final org.apache.logging.log4j.Logger logger = LogManager.getLogger(FTPEndpoint.class);
private CachingSessionFactory cachingSessionFactory;
private String adviceString;
#Inject
private FTPService(SftpConfiguration sftpConfig) {
this.cachingSessionFactory = sftpConfig.getCachingSessionFactory();
this.adviceString = sftpConfig.getAdviceString();
}
private String ftpStoreAuthData() {
Session session = this.cachingSessionFactory.getSession();
String mainframeDataSet = "'MAIN.FRAME.DATASET'";
try(BufferedInputStream inputStream = new BufferedInputStream(session.readRaw(adviceString + mainframeDataSet));
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))
{
Stream<String> lines = reader.lines());
return doThingsWithFTPData(lines);
} catch (IOException ex) {
LogException.writeToFile(ex.getMessage(),ex.getStackTrace(), env.getProperty("sftp.exceptionsPath"));
}finally {
try {
if (session.isOpen()) {
session.finalizeRaw();
session.close();
}
}catch (IOException ioe){
System.out.println(ioe.getLocalizedMessage() + ioe.getCause().toString());
LogException.writeToFile(ioe.getMessage(),ioe.getStackTrace(), env.getProperty("sftp.exceptionsPath"));
throw new IOException();
}
}
return "test";
}
}

Related

How to resolve "Deserialization of untrusted data" issue?

I am getting "Deserialization_of_Untrusted_Data" issue in SonarQube in the below part of my code.
public Configuration deserializeConfiguration(final InputStream xml) {
Configuration config = null;
exception = null;
try {
final XMLDecoder decoder = new XMLDecoder(new BufferedInputStream(xml), null, e -> {
});
config = (Configuration) decoder.readObject();
decoder.close();
} catch (final Exception e) {
exception = new Exception(e);
}
return config;
}
I tried to use class loader but it didn't resolve the issue.
public Configuration deserializeConfiguration(final InputStream xml) {
Configuration config = null;
exception = null;
try {
final XMLDecoder decoder = new XMLDecoder(new BufferedInputStream(xml), this.getClass().getClassLoader(), e -> {});
config = (Configuration) decoder.readObject();
decoder.close();
} catch (final Exception e) {
exception = new Exception(e);
}
return config;
}
Please suggest what I can do here without impacting other parts of the project.
This is my first time on this platform, so please ignore if there's any mistake.

Methods in interface not getting covered in mockito junit

I am using mockito-junit to test a piece of my code. As progressing I found out that there was an interface implemented in the main file which I was testing, when the test was running I found that the line where interface method is called get's covered but the real method doesn't get's covered.
This the code for the main file:
public class ExtractCurrencyDataTask {
private static final Logger LOGGER = LoggerFactory.getLogger(ExtractCurrencyDataTask.class);
#Autowired
private ExtractCurrencyService extractCurrencyService;
public void writeCurrencyListToFile(List<Currency> currencyList) {
if (currencyList != null && !currencyList.isEmpty()) {
String dir = "A path";
String fileName = "A filename";
String writeToFile = dir + "/" + fileName + ".writing";
String renameFile = dir + "/" + fileName + ".dat";
BufferedWriter writer = null;
FileWriter fileWriter = null;
try {
fileWriter = new FileWriter(writeToFile);
writer = new BufferedWriter(fileWriter);
extractCurrencyService.extractCurrencyList(currencyList, writer);
} catch (Exception e) {
throw new RuntimeException("Error writing Currency codes", e);
} finally {
if (writer != null) {
try {
writer.close();
fileWriter.close();
} catch (IOException e) {
LOGGER.info("Exception occured while closing the file writer", e);
}
moveFile(writeToFile, renameFile);
}
}
}
}
private void moveFile(String writeToFile, String renameFile) {
try {
FileUtils.moveFile(FileUtils.getFile(writeToFile), FileUtils.getFile(renameFile));
} catch (IOException e) {
LOGGER.info("Exception occured while moving file from writing to dat", e);
}
}
Here extractCurrencyService is the interface which I have mentioned.
The interface:
public interface ExtractCurrencyService {
public void extractCurrencyList(List<Currency> currency, Writer writer);
}
This the method definition which is done another file which implements same interface Filename:ExtractCurrencyServiceImpl.java
public class ExtractCurrencyServiceImpl implements ExtractCurrencyService {
private static final String SEP = "|";
private static final String NEWLINE = "\n";
#Override
public void extractCurrencyList(List<Currency> currencyList, Writer writer) {
if (currencyList != null) {
currencyList.forEach(currency -> {
String code = currency.getCode();
String name = currency.getName() == null ? "" : currency.getName();
Long noOfDecimals = currency.getNumberOfDecimals();
RoundingMethodValue roundingMethod = currency.getRoundingMethod();
boolean isDealCurrency = currency.isDealCurrency();
String description = currency.getDescription() == null ? "" : currency.getDescription();
try {
writer.write(createCurrencyDataLine(code,
name,
noOfDecimals,
roundingMethod,
isDealCurrency,
description));
} catch (Exception e) {
throw new RuntimeException(e);
}
});
}
}
private String createCurrencyDataLine(String code,
String name,
Long noOfDecimals,
RoundingMethodValue roundingMethod,
boolean isdealCurrency,
String description) {
return code + SEP + name + SEP + noOfDecimals.toString() + SEP + roundingMethod.toString() + SEP
+ isdealCurrency + SEP + description + NEWLINE;
}
public static <T> Predicate<T> distinctByKey(Function<? super T, Object> keyExtractor) {
Map<Object, Boolean> map = new ConcurrentHashMap<>();
return t -> map.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
}
}
This is the test file:
#RunWith(MockitoJUnitRunner.class)
public class ExtractCurrencyDataTaskTest {
#Mock
private Currency mockCurrency;
#Mock
private ExtractCurrencyService mockExtractCurrencyService;
#Mock
private BufferedWriter mockBufferWriter;
#Mock
private Bean mockBean;
#InjectMocks
private ExtractCurrencyDataTask extractCurrencyDataTask;
#Test
public void writeCurrencyListToFileTest() {
List<Currency> currencyList = new ArrayList();
when(mockCurrency.getCode()).thenReturn("USD");
when(mockCurrency.getNumberOfDecimals()).thenReturn((long) 2);
when(mockCurrency.getRoundingMethod()).thenReturn(enum value);
when(mockCurrency.isDealCurrency()).thenReturn(true);
when(mockCurrency.getName()).thenReturn("US Dollars");
when(mockCurrency.getDescription()).thenReturn("Currency Description");
currencyList.add(mockCurrency);
extractCurrencyDataTask.writeCurrencyListToFile(currencyList);
}
}
This the configuration for Autowired bean
#Bean
public ExtractCurrencyService extractCurrencyService() {
return new ExtractCurrencyServiceImpl();
}
As you can see the real output of this process is a file will be created in a path mentioned with some data. Here in this test I am mocking the data and passing it to main file. Main file is the created file in respective path but there is no data in the file.
The data writing part is done by the interface method. This is the part where I need help.
Thanks in advance....
You are injecting a mock of ExtractCurrencyService into your tested class. So the test is running with this mock instance instead of ExtractCurrencyServiceImpl. The current behaviour is that your ExtractCurrencyDataTasktested class is calling to extractCurrencyService#extractCurrencyList, but this extractCurrencyService is a mock, not your real implementation, so the call is done but it does nothing.
If you want to unit test ExtractCurrencyDataTask then thats ok, but maybe you should assert the call to extractCurrencyService#extractCurrencyList is done in the way you expect.
If you want to unit test ExtractCurrencyServiceImpl then create a unit test for this class.
If you want to test the interaction between these two classes then create an integration test where ExtractCurrencyDataTask has injected a real instance of ExtractCurrencyServiceImpl, not a mock.

Can not Connect to MLab Mongo Database from mongodb java driver

This is my MLab setup for my blooddb database
I am trying to connect it from a spring application by mongodb java driver.
This is my springDataDb Utils file:
public class SpringDataDBUtils {
private static MongoOperations mongoOperation;
private final static Properties properties = new Properties();
private final static Logger logger = LoggerFactory.getLogger(SpringDataDBUtils.class);
public static MongoOperations getMongoOperations() throws Exception {
if( mongoOperation==null){
logger.info("Connecting to db ... ");
MongoClientURI uri = new MongoClientURI(getDatabaseURI()+getDatabaseName());
MongoClient client = new MongoClient(uri);
mongoOperation = new MongoTemplate(client, getDatabaseName());
logger.info("Connected to db : "+ getDatabaseName());
}
return mongoOperation;
/*AppConfig appConfig = new AppConfig();
return appConfig.getMongoOperations();*/
}
protected static String getDatabaseName() {
try {
InputStream inputStream = SpringDataDBUtils.class.getClassLoader()
.getResourceAsStream(AppConstant.PROPERTIES_FILE);
properties.load(inputStream);
} catch (IOException e) {
logger.error("Error:"+e.getMessage());
}
return properties.getProperty(AppConstant.PROPERTIES_DB_NAME);
}
protected static String getDatabaseURI() {
try {
InputStream inputStream = SpringDataDBUtils.class.getClassLoader().getResourceAsStream(AppConstant.PROPERTIES_FILE);
properties.load(inputStream);
} catch (IOException e) {
logger.error("Error:"+e.getMessage());
}
String dbURI = "mongodb://"+ properties.getProperty(AppConstant.PROPERTIES_DB_USER) +
":" + properties.getProperty(AppConstant.PROPERTIES_DB_PASSWORD) +
"#" + properties.getProperty(AppConstant.PROPERTIES_DB_IP) +
":" + properties.getProperty(AppConstant.PROPERTIES_DB_PORT) + "/";
logger.info(dbURI);
return dbURI;
}
public static Properties ssProperties(){
try {
InputStream inputStream = SpringDataDBUtils.class.getClassLoader()
.getResourceAsStream(AppConstant.PROPERTIES_FILE);
properties.load(inputStream);
} catch (IOException e) {
logger.error("Error:"+e.getMessage());
}
return properties;
}
}
and my properties file is:
db.name=blooddb
db.password=****
db.user=****
db.ip= mongodb://<dbuser>:<dbpassword>#ds037587.mlab.com:37587/blooddb
db.port=27017
But while running the app i am getting exception.
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'mongoTemplate' defined in class path resource [com/istiak/blooddb/AppConfig.class]: Bean instantiation via factory method failed
this is probably the db.ip i have provided here in the properties file.
so what can i do while putting ip from mLab?
Seems like there is problem in your dbURI string.
You are adding "mongoldb://" two times in dbURI, one the constant string and other as computed from db.ip in properties file.

Cassandra Trigger java.lang.AbstractMethodError

Hey i try to do the first steps with Casssandra trigger. The trigger should only get the mutation and write it to a simple .txt file nothing more nothing less.
Everytime i do an isert i get the following Error:
java.lang.AbstractMethodError: org.apache.cassandra.triggers.invertedindex.augment(Lorg/apache/cassandra/db/partitions/Partition;)Ljava/util/Collection
The code is from a example i found in the internet.
public class invertedindex implements ITrigger
{
// private static final Logger logger = LoggerFactory.getLogger(invertedindex.class);
private Properties properties = loadProperties();
//private Object array;
public void augment(ByteBuffer key, ColumnFamily update) throws IOException
{
PrintWriter pWriter = null;
//long millis2;
// List<RowMutation> mutations = new ArrayList<>();
String indexKeySpace = properties.getProperty("keyspace");
String indexColumnFamily = properties.getProperty("table");
for (IColumn cell : update)
{
// Skip the row marker and other empty values, since they lead to an empty key.
if (cell.value().remaining() > 0)
{
pWriter = new PrintWriter(new BufferedWriter(new FileWriter("log_trigger_test.txt",true)));
RowMutation mutation = new RowMutation(indexKeySpace, cell.value());
// mutation.add(properties.getProperty("columnfamily"), cell.name(), cell.value(), System.currentTimeMillis();
// mutations.add(mutation);
// mutation.addColumnOrSuperColumn(arg0, arg1);
//System.out.println((mutation.toString()));
pWriter.println((mutation.toString()));
}
}
pWriter.close();
// return mutations;
}
private static Properties loadProperties()
{
Properties properties = new Properties();
InputStream stream = invertedindex.class.getClassLoader().getResourceAsStream("invertedindex.properties");
try
{
properties.load(stream);
}
catch (Exception e)
{
throw new RuntimeException(e);
}
finally
{
FileUtils.closeQuietly(stream);
}
return properties;
}
}
What i am doing wrong here? And is there more information about Casssandra trigger anywere? I only found some old stuff?
It looks like you are using Cassandra 3.x but have written a trigger for pre-3.x. Your trigger should be implementing the:
public Collection<Mutation> augment(Partition update);
method.
Take a look at the trigger example here for how to implement a 3.x trigger.

Load java properties inside static initializer block

I have a static util class that does some string manipulation on a bit sensitive data.
Prior to use of this class I need to initialize certain static variables with values, such as usernames/password, that I prefer to store in a .properties file.
I am not very familiar with how loading of .properties file work in Java, especially outside of *Spring DI *container.
Anyone can give me a hand/insight on how this can be done?
Thank you!
Addition: .properties file precise location is unknown, but it will be on the classpath. Sorta like classpath:/my/folder/name/myproperties.propeties
First, obtain an InputStream from which the properties are to be loaded. This can come from a number of locations, including some of the most likely:
A FileInputStream, created with a file name that is hard-coded or specified via a system property. The name could be relative (to the current working directory of the Java process) or absolute.
A resource file (a file on the classpath), obtained through a call to getResourceAsStream on the Class (relative to the class file) or ClassLoader (relative to the root of the class path). Note that these methods return null if the resource is missing, instead of raising an exception.
A URL, which, like a file name, could be hard-coded or specified via a system property.
Then create a new Properties object, and pass the InputStream to its load() method. Be sure to close the stream, regardless of any exceptions.
In a class initializer, checked exceptions like IOException must be handled. An unchecked exception can be thrown, which will prevent the class from being initialized. That, in turn, will usually prevent your application from running at all. In many applications, it might be desirable to use default properties instead, or fallback to another source of configuration, such as prompting a use in an interactive context.
Altogether, it might look something like this:
private static final String NAME = "my.properties";
private static final Properties config;
static {
Properties fallback = new Properties();
fallback.put("key", "default");
config = new Properties(fallback);
URL res = MyClass.getResource(NAME);
if (res == null) throw new UncheckedIOException(new FileNotFoundException(NAME));
URI uri;
try { uri = res.toURI(); }
catch (URISyntaxException ex) { throw new IllegalArgumentException(ex); }
try (InputStream is = Files.newInputStream(Paths.get(uri))) { config.load(is); }
catch (IOException ex) { throw new UncheckedIOException("Failed to load resource", ex); }
}
Check out java.util.Properties.
You can use a static initializer. So on the top of the class you can do:
static {
Properties props = new Properties();
InputStream steam = ...; // open the file
props.load(stream);
// process properties content
String username = props.getProperty("username");
}
Use either:
CurrentClassName.class.getResourceAsStream
new FileInputStream(File)
to get the input stream depending on if the class is in or out of the classpath. Then use
Properties.load
to load the properties.
It's been a while, but if I remember correctly you just do something like this:
Properties prop = new Properties();
prop.load(new FileInputStream(filename));
//For each property you need.
blah = prop.getProperty(propertyname);
Well with static Properties it would make sense to initialize them as a Singleton which will be loaded once in a class. Here's an example:
class Example
{
public final static String PROPSFILE = "test.properties";
private static Properties props;
protected static Properties getProperties()
{
if(props == null)
{
props = new Properties();
props.load(new FileInputStream(new File(PROPSFILE));
}
return props;
}
public static User getUser()
{
String username = getProperties().getProperty("username");
return new User(username);
}
}
If you use relative Pathnames you should make sure, that your classpath is setup righ.
for me MyClass.class.getClassLoader().getResourceAsStream(..) did the trick:
private static final Properties properties;
static {
Properties fallback = new Properties();
fallback.put(PROP_KEY, FALLBACK_VALUE);
properties = new Properties(fallback);
try {
try (InputStream stream = MyClass.class.getClassLoader().getResourceAsStream("myProperties.properties")) {
properties.load(stream);
}
} catch (IOException ex) {
// handle error
}
}
I agree with #Daff, maybe better to use singleton class...this what i have on my project for similar requirement, maybe it may help:
clients of the class can use it like this:
ConfigsLoader configsLoader = ConfigsLoader.getInstance("etc/configs.xml");
System.out.format("source dir %s %n", configsLoader.getSourceDir());
and then the class:
public class ConfigsLoader {
private String sourceDir;
private String destination;
private String activeMqUrl;
private static Logger log = Logger.getLogger(ConfigsLoader.class.getName());
private static ConfigsLoader instance = null;
private ConfigsLoader(String configFileName) {
log.info("loading configs");
Properties configs = new Properties();
try {
configs.loadFromXML(new FileInputStream(configFileName));
sourceDir = configs.getProperty("source.dir");
destination = configs.getProperty("destination");
activeMqUrl = configs.getProperty("activemqconnectionurl");
configs.setProperty("lastLoaded", new SimpleDateFormat("yyyy-M-d HH:mm").format(new Date()));
configs.storeToXML(new FileOutputStream(configFileName), "saving last modified dates");
} catch (InvalidPropertiesFormatException e) {
log.log(Level.SEVERE,"Error occured loading the properties file" ,e);
} catch (FileNotFoundException e) {
log.log(Level.SEVERE,"Error occured loading the properties file" ,e);
} catch (IOException e) {
log.log(Level.SEVERE,"Error occured loading the properties file" ,e);
}
}
public static ConfigsLoader getInstance(String configFileName) {
if(instance ==null) {
instance = new ConfigsLoader(configFileName);
}
return instance;
}
public String getSourceDir() {
return sourceDir;
}
public void setSourceDir(String sourceDir) {
this.sourceDir = sourceDir;
}
public String getDestination() {
return destination;
}
public void setDestination(String destination) {
this.destination = destination;
}
public String getActiveMqUrl() {
return activeMqUrl;
}
public void setActiveMqUrl(String activeMqUrl) {
this.activeMqUrl = activeMqUrl;
}
}
I did this finally using getResourceAsStream() fuction associated with the class in which the static code block is being written.
//associate Property and ImputStream imports
public class A {
static Properties p;
static {
p = new Properties();
try {
InputStream in = A.class.getResourceAsStream("filename.properties");
p.load(in);
} catch (FileNotFoundException e) {
System.out.println("FileNotFoundException");
e.printStackTrace();
} catch (IOException e) {
System.out.println("IOException");
e.printStackTrace();
}
}
.
.
.
}

Categories

Resources