the following code is incomplete but the main focus of my question is on the method processConfig() anyway. It reads the properties out of a file and I want to handover these properties to the method replaceID(). It worked already when the content of processConfig was in the main()-method. But now I wanted to put this code into it´s own method. What is the best way of handing over the properties (which I saved in Strings like difFilePath). I´m not that familiar with OO-programming and want to understand the concept. Thanks for your help.
public class IDUpdater {
....
public static void main(String[] args) throws Exception {
//Here I want to call the variables from processConfig() to make them available for replaceID(...)
replaceID(difFilePath, outputDifPath, encoding);
}
public static void replaceID(String difFilePath, String outputDifPath, String encoding) throws Exception{
return record;
}
public void processConfig(){
Properties prop = new Properties();
InputStream input = null;
try {
input = new FileInputStream("config.properties");
} catch (Exception e) {
logger.error("File 'config.properties' could not be found.");
}
try {
prop.load(input);
} catch (Exception e) {
logger.error("Properties file could not be loaded.");
}
String difFilePath = prop.getProperty("dif_file_path");
String outputDifPath = prop.getProperty("output_dif_path");
String encoding = prop.getProperty("encoding");
}
}
You've to declare your variables globally. This way they can be accessed in each method. After you've declared them globally you first call your processConfig in your main method, which will set your variables to what they should be.
public class IDUpdater {
private String difFilePath;
private String outputDifPath;
private String encoding;
public void main(String[] args) throws Exception {
processConfig();
replaceID();
}
public void replaceID() throws Exception{
// You can use your variables here.
return record;
}
public void processConfig(){
Properties prop = new Properties();
InputStream input = null;
try {
input = new FileInputStream("config.properties");
} catch (Exception e) {
logger.error("File 'config.properties' could not be found.");
}
try {
prop.load(input);
} catch (Exception e) {
logger.error("Properties file could not be loaded.");
}
difFilePath = prop.getProperty("dif_file_path");
outputDifPath = prop.getProperty("output_dif_path");
encoding = prop.getProperty("encoding");
}
}
Note that I declared the variables privately. For more information about protecting your variables see https://msdn.microsoft.com/en-us/library/ba0a1yw2.aspx.
You may want to read an article (or even better yet - a book) on topic of encapsulation and objects. This or this may be a good starting point for you. There is no point in anyone fixing your code, if you don't understand the concepts behind it.
Related
I'm looking for a way to pass a code block to a method, which will then perform actions on other arguments passed to method, take the results of those actions, and pass those results to the code block passed to the method. For clarity:
private static void method1(String filename, int sheetNum) {
runOnSheet(filename, () -> {
doStuffWithStream(FileInputStream fileStream); // Does something with a file stream
doOtherStuffWithStream(FileInputStream fileStream); // Does something else with a file stream
});
}
// Elsewhere
private static void runOnFile(String fileName, Runnable block1) {
try {
fileStream = new FileInputStream(fileName);
} catch (IOException e) {
e.printStackTrace();
}
block1.run(); // I'd like to pass fileStream to this code block. Ideally i could do block1.run(fileStream );
fileStream.close();
}
I want to be able to reuse runOnFile anywhere I need to open a file, run some code on the stream, and close the stream.
What I actually want to do is more complicated, and uses other libraries in addition to FileInputStream, but the structure of what I wish to accomplish is the same.
Thanks for any help!
Java 8+ has a Class called Consumer that can be used for your usecase:
https://docs.oracle.com/javase/8/docs/api/java/util/function/Consumer.html
private static void method1(String filename, int sheetNum) {
runOnFile(filename, (fileStream) -> {
doStuffWithStream(fileStream);
doOtherStuffWithStream(fileStream);
});
}
// Elsewhere
private static void runOnFile(String fileName, Consumer<FileInputStream> block1) {
try {
fileStream = new FileInputStream(fileName);
} catch (IOException e) {
e.printStackTrace();
}
block1.accept(fileStrean);
fileStream.close();
}
EDIT: As suggested by Dimitri using the try-with-resource syntax:
// Elsewhere
private static void runOnFile(String fileName, Consumer<FileInputStream> block1) {
try (FileInputStream fis = new FileInputStream(fileName)) {
block1.accept(fis);
} catch (IOException e) {
e.printStackTrace();
}
}
Try something like this:
private static void method1(String filename, int sheetNum)
{
try ( final FileInputStream fileStream = new FileInputStream(filename))
{
runOnSheet(filename, () ->
{
doStuffWithStream(fileStream); // Does something with a file stream
doOtherStuffWithStream(fileStream); // Does something else with a file stream
});
}
}
public static Properties defaultProps = new Properties();
static {
try {
FileInputStream in = new FileInputStream("config.properties");
defaultProps.load(in);
in.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public static String getProperty(String database) {
return defaultProps.getProperty(database);
}
public static void main(String[] args) {
System.out.println(...key database?);
// this is the part where I try to test if I can print the property 'database'
// I also try to make it available to other classes, tried using public statics,
}
This is my code in which I retrieve the properties from properties file config.properties. However, I want to be able to print property N (here: database) and be able to use property N in other classes.
Thanks for the help in advance.
so just call
System.out.println(getProperty("database"));
I`m new developper of spark, And now I was block by a issue.
I was implements freemarker as web template.
Not like other framework when you modify a .ftl file, You no need to restart the server.
But now in my local it must restart the server if I wanto see the change.
Below is code.
public class SparkServer {
public static void main(String[] args){
get("/hello",(request,response) ->{
Map root = new HashMap();
root.put("user", "xiekakaban");
Map product = new HashMap();
product.put("name","Pringles");
product.put("price",13.2);
root.put("product",product);
return new ModelAndView(root,"test.ftl");
},FreeMarkerEngine.getInstance());
}
}
public class FreeMarkerEngine extends TemplateEngine{
private static FreeMarkerEngine freeMarkerEngine;
private Configuration freeConfig;
private FreeMarkerEngine() throws IOException{
freeConfig = new Configuration();
freeConfig.setDirectoryForTemplateLoading(StringUtil.getResourceFile("templates"));
freeConfig.setTemplateUpdateDelay(1);
}
public static FreeMarkerEngine getInstance(){
if(freeMarkerEngine == null){
try {
freeMarkerEngine = new FreeMarkerEngine();
} catch (IOException e) {
e.printStackTrace();
System.exit(0);
}
}
return freeMarkerEngine;
}
#Override
public String render(ModelAndView modelAndView) {
StringWriter stringWriter = new StringWriter();
try {
freeConfig.clearTemplateCache();
freeConfig.clearSharedVariables();
freeConfig.clearEncodingMap();
Template template = freeConfig.getTemplate(modelAndView.getViewName());
template.process(modelAndView.getModel(), stringWriter);
System.out.println(stringWriter.toString());
return stringWriter.toString();
} catch (IOException | TemplateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return "Can not find the template:"+modelAndView.getViewName();
}
}
I don`t sure whether it is cache by spark or freemarker.But I have clear freemarker cache.
Anyone can help me.....
ok, I have figure out it.
Reloading the static files in Spark/Jetty-server
first I think you should make sure which page the freemarker load.
if you not setup, it will load ftl under "target" fold.
I think I put out a stupid question....
The class partially shown below contains a main method. When I run the code, I see a NullPointerException (NPE) and then an error message - "Could not find the main class, program will exit". My understanding is that if I get NPE, it means that the code is running, ie the JRE found a main method to begin execution, so why do I get the error message?
This is the console output
java.lang.ExceptionInInitializerError
Caused by: java.lang.NullPointerException
at com.MyWorldDemo.getValue(MyWorldDemo.java:57)
at com.MyWorldDemo.<clinit>(MyWorldDemo.java:23)
Exception in thread "main"
In a nutshell:
username is stored in a properties file.
properties file is like this username=superman....etc
here is some code example
class MyClass {
private final static String username = getData("username"); // ERROR HERE
private static Properties prop;
// more variables
static {
prop = new Properties();
try {
FileInputStream fis = new FileInputStream("MyDB.properties");
prop.load(fis);
} catch (IOException ex) {
ex.printStackTrace();
}
}
// this method will assign a value to my final variable username.
public static String getData(String props) {
String property = prop.getProperty(props);// ERROR HERE !!!
return property;
}
}
Initializing of static variables depends on its position in code (variables are initialized from top to bottom). In your code
private final static String username = getData("username"); // ERROR HERE
private static Properties prop;
// more variables
static {
prop = new Properties();
try {
FileInputStream fis = new FileInputStream("MyDB.properties");
prop.load(fis);
} catch (IOException ex) {
ex.printStackTrace();
}
}
prop object will be initialized after username in static block, but since to initialize username prop is necessary and its not initialized yet you get NPE. Maybe change your code to something like:
private static Properties prop = new Properties();
private final static String username = getData("username");
static {
try {
FileInputStream fis = new FileInputStream("MyDB.properties");
prop.load(fis);
} catch (IOException ex) {
ex.printStackTrace();
}
}
You have a static initialization at line 23 of MyWorldDemo that is calling the method getValue, which is then causing a NPE at line 57, therefore the class cannot be instantiated, therefore the main method cannot be called. It probably looks something like:
class MyWorldDemo {
private static String foo = getValue("username");
private static Properties prop;
// This happens too late, as getValue is called first
static {
prop = new Properties();
try {
FileInputStream fis = new FileInputStream("MyDB.properties");
prop.load(fis);
} catch(IOException ex) {
ex.printStackTrace();
}
}
// This will happen before static initialization of prop
private static String getValue(String propertyValue) {
// prop is null
return prop.getProperty(propertyValue);
}
public static void main(String args[]) {
System.out.println("Hello!"); // Never gets here
}
}
public class Storage implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
public static List<Message> MessageList = Collections.synchronizedList(new ArrayList<Message>()); //Fail safe if multiple threads modify them.
public static List<Group> GroupList = Collections.synchronizedList(new ArrayList<Group>());
protected Storage() {
super();
}
static private Storage _instance = null;
//initialized: Storage.instance();
static public Storage instance() {
if(_instance == null) {
_instance = new Storage();
}
return _instance;
}
}
I have the upper class which creates a single object. I want to save this object with its Lists to a file. Then when my app starts and I instantiate Storage I want it to read the file and if it is empty create a new Storage, but if its not then read the previous instance of Storage and create this new based on the old. Basically meaning that I want the contents of GroupList and MessageList to be persistent.
EDIT: because I didn't make it clear enough.
Where do I place the code needed to check and read a previous instance of this class in? I guess in the constructor, but then will my Lists also get the values of the other object? I dont know where/how to code that.
EDIT2: pasting solution.
public class Storage implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
public static List<Message> MessageList = Collections.synchronizedList(new ArrayList<Message>()); //Fail safe if multiple threads modify them.
public static List<Group> GroupList = Collections.synchronizedList(new ArrayList<Group>());
protected Storage() {
super();
}
static private Storage _instance = null;
//initialized: Storage.instance();
public static synchronized Storage instance(){
initialize();
if(_instance == null) {
_instance = new Storage();
}
return _instance;
}
public static synchronized void persist(){
FileOutputStream fos = null;
ObjectOutputStream out = null;
try{
fos = new FileOutputStream("Storage.txt");
out = new ObjectOutputStream(fos);
out.writeObject(instance());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
protected static synchronized void initialize(){
FileInputStream fis = null;
ObjectInputStream in = null;
try{
fis = new FileInputStream("Storage.txt");
in = new ObjectInputStream(fis);
_instance = (Storage)in.readObject();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (OptionalDataException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static synchronized void addElement(Message message){
if(!MessageList.contains(message)){
MessageList.add(message);
persist();
Log.i("STORAGE-addElement", "Added: " + message);
}
}
public static synchronized void addElement(Group group){
if(!GroupList.contains(group)){
GroupList.add(group);
persist();
Log.i("STORAGE-addElement", "Added: " + group);
}
}
public static synchronized void removeElement(Message message){
if(!MessageList.contains(message)){
MessageList.remove(message);
persist();
Log.i("STORAGE-removeElement", "Removed: " + message);
}
}
public static synchronized void removeElement(Group group){
if(!GroupList.contains(group)){
GroupList.remove(group);
persist();
Log.i("STORAGE-removeElement", "Removed: " + group);
}
}
public static synchronized void wipeAll(){
MessageList.clear();
GroupList.clear();
persist();
Log.i("STORAGE-wipeAll", "Wiped all data");
}
}
Thanks for your help! :)
You can add the following methods to your Storage object:
public void persist() throws IOException{
FileOutputStream fos = null;
ObjectOutputStream out = null;
try{
fos = new FileOutputStream(FILE_NAME); //assumes filename is a constant you've defined
out = new ObjectOutputStream(fos);
out.writeObject(time);
}finally{
out.close();
}
}
protected static void initialize() throws IOException{
FileInputStream fis = null;
ObjectInputStream in = null;
try{
fis = new FileInputStream(FILE_NAME);
in = new ObjectInputStream(fis);
instance = (PersistentTime)in.readObject();
}finally{
in.close();
}
}
You can call initialize() from your static instance method instead of calling the constructor directly.
It can be done by reading the object in the main method of your application and saving it again in the main method close to the shutdown point. May be I am missing something.
There is a good description of the Java serialization api here:
http://java.sun.com/developer/technicalArticles/Programming/serialization/
The short version is you probably need to add the following two methods to customize how your object is written. Note that these do not Override any superclass method -- just add them with these exact signatures.
Make sure your Message and Group objects are serializable as well.
Then you'll create an ObjectOuputStream and call its writeObject method to write your object to a file.
The methods to add to your Serializable class:
private void writeObject(ObjectOutputStream out) throws IOException
and
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException
I'm assuming there's code in your real Storage class that sets member data for the Storage object. Given that, I would recommend something along the lines of:
static public Storage instance() {
if(_instance != null) {
return _instance;
}
_instance = new Storage();
if (file.exists()) {
deserialize_Storage_data_from_file();
}
return _instance;
}
All the above - and change those List's to be non-static too!
Obviously you need to store the serialized singleton in the file system, so you will need a canonical location, e.g. a config parameter for the file name.
Then, the instance accessor method effectively is in charge of marshalling/unmarshalling the persistent instance. This is the easy part. (There is a small can of worms for a robust system: you will need to insure no other process is ever writing to this file, e.g if another JVM instance comes up and uses the same singleton class. Again: the name of serialized file is a simple mechanism to address this issue.
Operationally, any changes to the instance (in mem) need to be synchronized with the persistent form, e.g. consistency requirements will demands some sort of transactional semantics. Simplest (but least efficient) is to simply flush the instance to the serialized file on every mutating action on the singleton instance, e.g. when modifying list content.