Alright, I'm trying to program a bukkit plugin and I need to have values from the config file, I've looked up the tutorial at
http://wiki.bukkit.org/Configuration_API_Reference#The_Configuration_Object but this gave me no assistance.
So my code for connect.java is this:
package com.live.AlioGenerica.netherflight;
import java.util.Set;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
public class users {
this.getConfig().options().copyDefaults(true);
public static Boolean getValue(Player p) {
this.getConfig().getBoolean(p);
return true;
}
public static Object setValue(Player p, Boolean v) {
conval.myConfig().set("users." + p + ".boolean", v);
return true;
}
}
config.yml is this:
users:
username: false
userother:true
and etcetera.
How in the world do I connect, I couldn't find anything. I know this is a mess, because I have no idea how to do it.
I myself create Bukkit plugins on my own. The YamlConfiguration is quite easy to use. You can use the method
public void set(String option, Object value)
to set a certain configuration option (option) to a specified value (value) and
public Object get(String option)
and others to get a previously set value. To find all the methods you can use, look them up in Bukkit's JavaDoc for YamlConfiguration.
If you want to save your YamlConfiguration, use
public void save(File f) throws IOException
Besides that, you should work on your coding. Here's a improved version of your code as it is now.
package com.live.AlioGenerica.netherflight;
import java.io.IOException;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
public class Users {
private static YamlConfiguration config = null;
// some code
// this method has to be static if you want to use it
// in another static method
public static YamlConfiguration getConfig() {
// load the configuration if it hasn't been loaded yet
if(config == null) {
config = YamlConfiguration.loadConfiguration("path/to/config.yml");
}
// some code
return config;
}
// this will return the boolean you want to get
public static Boolean getValue(Player p) {
return getConfig().getBoolean("users."+p.getName());
}
// use this code to set the value
public static void setValue(Player p, Boolean value) {
getConfig().set("users."+p.getName(), value);
}
// save the configuration
public static void save() {
try{
config.save(new File("path/to/config.yml"));
}catch(IOException e){
e.printStackTrace();
}
}
}
If there are any questions left, just let me know.
#EDIT: Just realized you wanted to save a boolean for a player so that it looks like this in the configuration.
users:
player: true
anotherplayer: false
andsoon: false
Ok, so to deal with the config, the first thing you want to do is actually have a config and put it in the correct place. It looks like you have a config, so you just have to make sure it's located in the resource section of your plugin. After you do that, then you can start dealing with it in your code.
First you want to actually get the config. You do that with this code.
FileConfiguration config = plugin.getConfig();
Simple enough. Now what you want to do is make it so that the plugin will retrieve the values in the config.
config.options().copyDefaults(true);
Finally, you just check to see if the config has been saved in you plugin's data folder.
if (!(new File(plugin.getDataFolder() + config.getName()).exists())) {
plugin.saveDefaultConfig();
}
After you do all those things, you can retrieve the actual values of the config with:
plugin.getConfig().getBoolean("username");
Using this.getConfig() can only be done from the main class that extends JavaPlugin.
You can use the getConfig() and methods built in with that if you do something like this:
public class Example {
MyPlugin plugin;
public String getSomethingFromConfig() {
return plugin.getConfig().getString("path");
}
}
Thats the Easiest way, In My Opinion.
Having a configuration file to get reference variables is very easy to do once you know how to do it. Starting this off you need actually have a config.yml in your src folder of your project. If you are not in Eclipse, I would suggest switching to it to do this easier. Just make a file called config.yml. You can put your variables inside of here that I see you have already did.
After this you need to create the config file when the server starts.
You would need to call a method on your onEnabled method from your main class. You can pull the getConfig() method from other classes also, that I will show you how below.
Since everytime the console enables it will do this method you will need a try/catch operation:
try
{
}
catch (Exception e)
{
e.printStackTrace();
}
The catch is if something goes wrong it will print a stackTrace to console. Inside of the try you will create the config.yml. To do this you will need to make a file variable inside of the try:
File config = new File(getDataFolder(), "config.yml");
Before you can make the config there has to be a data folder for the config to be stored in. To make this data Folder you will need to first see if it is there:
if(!getDataFolder().exists())
{
getDataFolder().mkdirs();
}
After making the data folder you will need to check if the config.yml is already there, and if not create it.
if(!config.exists())
{
getLogger().info("Config.yml not found, Creating");
saveDefaultConfig();
}
Having the saveDefaultConfig(); method will make sure to save your #notes inside of your config file to tell the user what each variable does. This is the best way to save your config file upon creating it. If the config already exists you can put an else and say that it is already there, but this is not necessary.
Make sure all of that is inside of a method that is called in the onEnable() method from your main class. Now that your config is created you can easily get variables from the main class by using the method getConfig()
You can also do this from other classes that I will tell you how to do soon. You can grab any variable from the config by doing getConfig().get ... and past here you can get many things such as strings, integers, booleans, etc... It will then give you a string to find the variable from. This will be the variable name inside of your config.
To use the getConfig() method from other classes you will need to use a constructor. You will need to call an instance from the main class to do this.
In your other class make a constructor like this:
[MainClassName] plugin;
public [OtherClassName]([MainClassName] instance)
{
plugin = instance;
}
The plugin variable will be your instance from the main class. You can use plugin.getConfig() to get the config now.
However, when you register events/commands you will need to match this constructor. Just put this to match the constructor when registering events/commands.
I also notice that you have variables inside of variables. To get the variables inside of the variables you need to get a Configuration Section:
for(String key : instance#getConfig().getConfigurationSection([config path]).getKeys(false))
The String key will be the variable inside of the variable. Since this is iterating, it will get all the variables inside of the variable with the one string key. To get the value of the key variable you would just make a boolean/int/string or whatever is inside and get it by doing:
[String/boolean/int/etc...] value = instance#getConfig().get[Int/String/Boolean/etc...]([first config path]+"."+key)
This is all you need to know about configuration files.
Related
We're developing a Java application that reads a Config file at runtime. My question is that which of the following scenario is efficient for reading a Config file.
Scenario #1: Retrieves a value from config by opening the file, get the value, then close the file.
So this means that file will be open and close every time retrieving a value.
Scenario #2: Open the file during initialization, then expose the object statically across the runtime.
File will be open once, then retrieving a value using the Config object.
Honestly, we currently using the scenario #2. A reason why we choose it because Config file will be open once. Opening file needs syncrhonization, which may lead to untimely retrieval of value. Also, scenario #1 may cause runtime error if the Config file is moved from it's absolute path (anything is possible). But scenario #1 is efficient when it comes in modifying the Config values during runtime.
So which is efficient?
Is your application a mulit-threaded application? if yes, you need to make sure that you have scenario #1 with necessary synchronisation and semaphores. The reason is that your config file is a general item in your application which will be used by all the threads. You don't want the config file reading operation to be interleaved. Even with single threaded operation, it is good to do #1 because you will have less chances of having IO Error. The RTE that you mentioned in your question can happen with anything if you decide to move the file (? Why would you if you need it at a certain place?).
If I should have to access the file more than once, probably I would create a class with a field for each configuration, I would read the file once (only to initialize the class fields) and then I would close the file. In this way you read the file once, during the init, and then you could simply access the configuration by reading the field values stored in the class.
public class Configuration
{
private static String confOne;
private static int confTwo;
private static boolean confThree;
public static init(File configFile) {
/* read the file and init fields */
}
public static String getConfigOne() {
return configOne;
}
public static int getConfigTwo() {
return configOne;
}
public static boolean getConfigThree() {
return configOne;
}
}
A little advice: tries to never hold open a file (or resources) unless absolutely necessary.
I think neither of the scenarios is the best one:
As you you have already stated in sencario #1 you may have a lot of unnecessary IO-Workload and in #2 you cannot change config parameters dynamically at runtime.
I suggest to use a mixture of both. You can load your configuration statically once and then check periodically, if changes have happend. If so, reload your config.
You can see how it may be done by inspecting Java's ResourceBundle-Class. In fact, if the config can be placed as properties-file in your classpath, you can (ab?)use this implementation for your purpose:
private static Control MY_CONTROL = new Control()
{
#Override
public long getTimeToLive(String baseName, Locale locale)
{
return MY_TTL; //make shure, that changes are checked periodically
}
};
public static String getParamter(String name)
{
ResourceBundle config = ResourceBundle.getBundle("config", MY_CONTROL);
return config.getString(name);
}
What I want to do is load key/value pairs from a file (excel file using Apache poi) into a static map that will be used as a lookup table. Once loaded the table will not change.
public final class LookupTable
{
private final static Map<String, String> map;
static {
map = new HashMap<String, String>();
// should do initialization here
// InputStream is = new FileInputStream(new File("pathToFile"));
// not sure how to pass pathToFile without hardcoding it?
}
private LookupTable() {
}
public static void loadTable(InputStream is) {
// read table from file
// load it into map
map.put("regex", "value");
}
public static String getValue(String key) {
return map.get(key);
}
}
Ideally I want to load the map within the static initialization block, but how would I pass the stream in without hard coding it? The problem I see using the loadTable static method is it might not be called before calling the other static methods.
// LookupTable.loadTable(stream);
LookupTable.getValue("regex"); // null since map was never populated.
Is there a better approach to this?
Anything you use will have to be accessible at startup. As far as I know, your options are:
Hard-code the path. This is bad for obvious reasons.
A static variable or static method. This presents a bit of a chicken-and-egg problem; ultimately it gets hard-coded, but at least you can do a search with a static method.
Use a variable, either Java or Environment. So, you'd use something System.getProperty("filename", "/default/filename"). Better because it's at least customizable using the environment or -D parameters at JVM startup.
Use the ClassLoader getResource* methods. This is probably The Right Answer. Specifically, you'll probably want to use the getResourceAsStream() method on the current thread's context ClassLoader Thread.currentThread().getContextClassLoader(). (So, Thread.currentThread().getContextClassLoader().getResourceAsStream("filename") in total.) The ClassLoader will then find your resource for you (as long as you put it somewhere sane in your CLASSPATH).
Yes, there is a better approach, use the Factory design pattern to initialise the object before you have to use it:
http://www.oodesign.com/factory-pattern.html
You cannot pass information into static initialization blocks - they are supposed to work in isolation. Since the stream that you are planning to pass needs to be known before the program begins execution, presumably your LookupTable should be able to find it too. For example, this could be some sort of configuration utility that provides the stream for you. Then you can write your initializer like this:
static {
InputStream exelStream = MyConfigUtil.getExcelStreamForLookup();
loadTable(exelStream);
}
Presumably, there is a class in the system that could get your Excel stream from a source that is known to it. The source does not need to be hard-coded: it could read the location from a configuration file, or receive the data from a predefined network location on your server. In all cases the process of getting the Excel stream has to "bottom out" somewhere, in the sense that something in your system needs to be able to find it without additional parameters.
This is not directly answering your question, but I don't see why map has to be static. You could change map to non-static and change the constructor to public LookupTable(File file) {...fill map...}. You could then even have many instances of that class if you have different excel files; it might not be the case now, but it would "future-proof" your code.
This is probably a case for using lazy loading of the map.
But you will need to set the inputFileName before calling getValue() the first time. This would be done in your initialization code for the applications. (Or you could have a static method to set it.)
This points out the advantage of lazy loading. You don't have to have the file name available until you call getValue() the first time. With a static initializer, you have to get the file name stored somewhere outside the class so it can be used to load the data when the class loads (but after the static fields have been initialized.
public static String inputFileName = null;
public static String getValue(String key) {
if (map == null) {
map = = new HashMap<String, String>();
// open the file using 'inputFileName'
loadTable(InputStream is);
}
return map.get(key);
}
If your code is multithreaded, let me know and I'll comment on the synchronization issues.
Alternate
You could also use Spring to inject the map and build it in some other class -- MapBuilder for example.
Try using System.getProperty() and pass parameter with -D in command line.
static String prop;
static {
prop = System.getProperty("java.home");
}
public static void main(String... args) {
System.out.println(prop);
}
I would suggest a singleton enum approach if it suits your case.
public enum LookupTable {
INSTANCE(FileManager.getFileName());
LookupTable(String fileName){
props = new HashMap<String,String>();
//Read from excel and fill the hashmap
}
private final Map<String, String> props;
public String getMapValue(String key){
return props.get(key);
}
}
Which can be called by
LookupTable.INSTANCE.getMapValue("mykey");
This will call these methods in order
Get filename from a filemanager class, which is parametrized on your needs
Call the constructor (it is private) and load properties from the excel file
getMapValue for the key and return
A subsequent call LookupTable.INSTANCE.getMapValue("mysecondkey") will only call getMapValue as the INSTANCE is initialized beforehand.
At many places in my web application I need a certain String which is :
request.getServletContext().getRealPath("/");
// I can only get this once the web-app starts
Sometimes a simple java class needs to know this string. I don't want to pass each and every time this string to the class's function. One way could be to stash this string in a file at the very beginning of the web application. Every time I would need this, simply read the file.But this doesn't seem a pretty good option. Is there any other way out ?
May be I can store in the context.xml of the application. If it is possible how do I do that ?
If there is a better way please suggest.
I am using tomcat as the server.
Invoke run the following code when your application starts (e.g. with a ServletContextListener):
public void contextInitialized(ServletContextEvent sce) {
ServletContextRootRealPath.set(sce.getServletContext().getRealPath("/"));
}
Then later whenever you need it you simply call
ServletContextRootRealPath.get()
Since it's all static the variable is accessible JVM-wide to every code that runs in this JVM.
Utility class
public final class ServletContextRootRealPath {
private static String path;
private ServletContextRootRealPath() {
// don't instantiate utility classes
}
public static void set(String rootRealPath) {
path = rootRealPath;
}
public static String get() {
return path;
}
}
You can store the value in static variable of any class (Basically a helper class which is used for serving common utility functions). Later you can refer to this variable without creating instance of the class, as it is static and can be accessed without its instance.
I am working on a project that has been through multiple hands with a sometimes rushed development. Over time the message.properties file has become out of sync with the jsps that use it. Now I don't know which properties are used and which aren't. Is there a tool (eclipse plugin perhaps) that can root out dead messages?
The problem is that messages may be accessed by JSP or Java, and resource names may be constructed rather than literal strings.
Simple grepping may be able to identify "obvious" resource access. The other solution, a resource lookup mechanism that tracks what's used, is only semi-reliable as well since code paths may determine which resources are used, and unless every path is traveled, you may miss some.
A combination of the two will catch most everything (over time).
Alternatively you can hide the functionality of ResourceBundle behind another façade ResourceBundle, which should generally pipe all calls to original one, but add logging and/or statistics collection on the top.
The example can be as following:
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.NoSuchElementException;
import java.util.ResourceBundle;
public class WrapResourceBundle {
static class LoggingResourceBundle extends ResourceBundle {
private Collection<String> usedKeys = new HashSet<String>();
public LoggingResourceBundle(ResourceBundle parentResourceBundle) {
setParent(parentResourceBundle);
}
#Override
protected Object handleGetObject(String key) {
Object value = parent.getObject(key);
if (value != null) {
usedKeys.add(key);
return value;
}
return null;
}
#Override
public Enumeration<String> getKeys() {
return EMPTY_ENUMERATOR;
}
public Collection<String> getUsedKeys() {
return usedKeys;
}
private static EmptyEnumerator EMPTY_ENUMERATOR = new EmptyEnumerator();
private static class EmptyEnumerator implements Enumeration<String> {
EmptyEnumerator() {
}
public boolean hasMoreElements() {
return false;
}
public String nextElement() {
throw new NoSuchElementException("Empty Enumerator");
}
}
}
public static void main(String[] args) {
LoggingResourceBundle bundle = new LoggingResourceBundle(ResourceBundle.getBundle("test"));
bundle.getString("key1");
System.out.println("Used keys: " + bundle.getUsedKeys());
}
}
Considering that some of your keys are run-time generated, I don't think you'll ever be able to find a tool to validate which keys are in use and which ones are not.
Given the problem you posed, I would probably write an AOP aspect which wraps the MessageSource.getMessage() implementation and log all the requested codes that are being retrieved from the resource bundle. Given that MessageSource is an interface, you would need to know the implementation that you are using, but I suspect that you must know that already.
Given that you would be writing the aspect yourself, you can create a format that is easily correlated against your resource bundle and once you are confident that it contains all the keys required, it becomes a trivial task to compare the two files and eliminate any superfluous lines.
If you really want to be thorough about this, if you already have Spring configured for annotation scan, you could even package up your aspect as its own jar (or .class) and drop it in a production WEB-INF/lib (WEB-INF/classes) folder, restart the webapp and let it run for a while. The great thing about annotations is that it can all be self contained. Once you are sure that you have accumulated enough data you just delete the jar (.class) and you're good to go.
I know that at least two of the major java IDEs can offer this functionality.
IntelliJ IDEA has a (disabled, by default) Inspection that you can
use to do this:
go to Settings -> Inspections -> Properties files -> ... and enable
the 'Unused property'
..Only problem I had was that it didn't pick up some usages of the property from a custom tag library I had written, which I was using in a few JSPs.
Eclipse also has something like this ( http://help.eclipse.org/helios/index.jsp?topic=%2Forg.eclipse.jdt.doc.user%2Ftasks%2Ftasks-202.htm ) but I haven't really exhausted the how well it works.
I'm new to Java and I have to create a value object, (maybe it's called mapped object in Java) but my code doesn't seem to work, here is the value object:
package ....;
public class User {
private int id;
private int uid;
private String name;
public User()
{
// do something here
}
}
and I assign a new value object like this:
public boolean some_function()
{
User u = new User();
return true; // got a breakpoint here
}
So if I comment out "User u = new User();" I will go to the breakpoint but if I keep it like above it will just stop running.
On a side note, I keep both the files in the same folder so eclipse doesn't import the file, is this correct or should I import it?
EDIT:
After some time I found out that I had to import the file manually, I thought I tried that but apparently I didn't.
Dennis, if the code as you posted it is the exact code you're running, then this makes no sense -- the "User u = new User();" call would return you a new User object without any issues, since your constructor is empty.
To demonstrate that to yourself, change your constructor to:
public User() {
System.out.println("I'm inside the User constructor!");
}
and call your some_function() function again. You should see that line printed out to your console.
Given what you're reporting and the code you're showing, I suspect that the class that contains some_function() isn't "seeing" the User class -- you're importing some other User class rather than the one you created. Are the two classes -- the User class and the class which contains some_function() -- in the same package? If not, what import statement at the top of the some_function()-containing class is handling the import of your User class?
Sure you don't have an infinite loop in your User() constructor?
Put some code into the constructor, for example
id = 99;
set a break point there.
I don't understand what you mean about importing into Eclipse - I have all my code in Eclipse - however I suspect that your application is not correctly seeing the User class. Maybe you are even getting a compilation error. Create your packages and classes in Eclipse, let it sort out the directories for you.
Show us the whole app class , including the import of User.
Put the breakpoint on User u = new User(); and step into the constructor to see what it's doing.