I'm quite new to OOP concepts, and right now I am developing a small system, it has a login system. I have saved the user info in a database, and when I log in, I have made it so it retrieves and assigns the user info(name, privileges, etc) to a set of static variables in my staff class to use later. I was wondering is there a way around this, to save the variables while the program is running after log in to be used later in other forms. The reason I assigned them to static variables while the user has logged in, is so that I don't have to retrieve his user info everytime I need to use them(for example to check which form to fall back to if the user presses back and has certain privileges)
If you want this the OOP way, you would typically define a UserInfo class, which will hold the relevant information (passed in via constructor). If you need to change between different users, the most common solution would be to store the UserInfos in a container such as a HashMap, and have one of the attributes (possibly a dedicated one) act as key to the users. Later you can just get the information object for a given user.
In most cases using static variables is a mistake, not just for the clutter it causes but for the on-going pain of remembering it.
There are some generally accepted exceptions though. Loggers are acceptable when made static.
You are in need of a session static Context. I.e. a context that is static for one session (i.e. login).
class Context {
private static final Context context = new Context();
String userName;
String userPriveliges;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getUserPriveliges() {
return userPriveliges;
}
public void setUserPriveliges(String userPriveliges) {
this.userPriveliges = userPriveliges;
}
public static Context getContext() {
return context;
}
}
One approach is to use the Singleton Pattern. This allows you to avoid static fields at the cost of a static method.
public class LoginInfo {
private String username;
private List<String> privileges;
private static INSTANCE = new LoginInfo();
private LoginInfo() {
}
public void initFromDB() {
}
// Everything else is non-static but this
public static getInstance() {
return INSTANCE;
}
}
public class Form1 {
public void doSomething() {
LoginInfo info = LoginInfo.getInstance();
}
}
public class Form2 {
public void doSomething() {
LoginInfo info = LoginInfo.getInstance();
}
}
The other approach is Dependency Inversion. In this case, the users of LoginInfo get the information from outside, somehow.
public class Form1 {
private LoginInfo loginInfo;
public Form1(LoginInfo loginInfo) {
this.loginInfo = loginInfo;
}
public void doSomething() {
}
}
public class Form2 {
private LoginInfo loginInfo;
public Form2(LoginInfo loginInfo) {
this.loginInfo = loginInfo;
}
public void doSomething() {
}
}
Somewhere else:
// The Hollywood Principle - don't call me, I'll call you
public void login() {
LoginInfo loginInfo = new LoginInfo();
form1 = new Form1(loginInfo);
form2 = new Form2(loginInfo);
}
The Dependency Inversion approach has the benefit of the nasty side effects of static variables and methods, at the cost of some wiring. There are frameworks such as Spring, CDI and Guice that help you with that part.
Also, Singletons are Pathalogical Liars.
Instead of using static use final. I mean un-initialised final. But it will work only if after logged offing you exit from application. If you are not existing after logged off then use registry to save users. Java has inbuilt registry, you can use it to save anything. It also has password protection, and you can use that registry as cookies of web applications. Here are few linksconstant-vs-staticbad design practice statichow to avoid static
You can pass variables through constructors. Otherwise you can use a singleton class. There's no other way.
Related
I am attempting to make a library. Had some constants in my code which were some kind of different time delays and certain String values across the code. I could extract them to a separate constant class to get something like
Delays.LENGTH_SHORT (seems cleaner)
They are linked to many different classes inside the library code.
Now, the problem in hand is to make it configurable, from the calling consumer (i.e., if the consumer provides the values, then use those, otherwise use the preset values). From the consumer end, I decided to use Builder pattern for creating the config and passing it in the init of the library module (this only happens once in the lifecycle of it).
Is there a way to keep the above syntax and yet accept the config from consumer (the settings are only configured once during init, for all other times, it completely behaves as constant)?
Reading from a file, appeared to be costly.
For constants that can take a value from only a fixed set of values then it is always better to use Java enums instead of integers or strings or other raw data types. They are much better to understand and maintain over the period of time. Default values should ideally be read from a property file to initialize them. But as you have mentioned in your case, you want to avoid the cost of reading from a file for performance reasons. The design question is always open ended and can have multiple approaches. One approach that I recommend can be as below:
public interface Configuration {
public Continent getContinent(); //For fixed set of values use enum
public Integer getPoolSize(); //If the config can take any value then use the corresponding data type directly
public String getDefaultLabel();
}
public enum Continent {
ANTARTICA, AFRICA, ASIA, AUSTRALIA, EUROPE, NORTH_AMERICA, SOUTH_AMERICA;
}
public class ConfigurationBuilder {
private DefaultConfiguration configurationInstance;
private class DefaultConfiguration implements Configuration {
//Ideally the below values should be read from a property file, instead of hard coding it here.
private Integer poolSize = Integer.valueOf(50);
private String defaultLabel = "DEFAULT";
private Continent continent = Continent.ASIA;
#Override
public Continent getContinent() {
return continent;
}
#Override
public Integer getPoolSize() {
return poolSize;
}
#Override
public String getDefaultLabel() {
return defaultLabel;
}
}
public ConfigurationBuilder withContinent(Continent continent) {
this.configurationInstance.continent = continent;
return this;
}
public ConfigurationBuilder withPoolSize(Integer poolSize) {
this.configurationInstance.poolSize = poolSize;
return this;
}
public ConfigurationBuilder withDefaultLabel(String defaultLabel) {
this.configurationInstance.defaultLabel = defaultLabel;
return this;
}
public Configuration build() {
return this.configurationInstance;
}
public ConfigurationBuilder() {
this.configurationInstance = new DefaultConfiguration();
}
public static Configuration buildDefaultConfiguration() {
return new ConfigurationBuilder().build();
}
}
public class Library {
private Configuration configuration;
public void init(Configuration configuration) {
this.configuration = configuration;
}
public void init() {
this.configuration = ConfigurationBuilder.buildDefaultConfiguration();
}
private Library(Configuration config) {
this.init(config);
}
private Library() {
this.init();
}
/**
* Library is not singleton here.
*
*/
public static Library getInstance(Configuration configuration) {
return new Library(configuration);
}
public static Library getInstance() {
return new Library();
}
}
public class Client {
public static void main(String args[]) {
Configuration config = new ConfigurationBuilder()
.withContinent(Continent.AFRICA)
.withPoolSize(20)
.withDefaultLabel("Label")
.build();
Library lib = Library.getInstance();
lib.init(config);
}
}
Please check the Library and Client classes for usage.
- It uses the Builder pattern.
- It has init() and init(Configuration) methods to allow completely relying on Library defaults.
- ConfigurationBuilder supports supplying some or all configuration values to override
- Currently all three config options are overridable - continent, poolSize and defaultLabel. However if some configuration is private to Library then just remove the withXXX method for that property from the Builder.
Hope this fits your need. Good question!
I have two ways of saving data in my application: save to database and save to file. Since I don't want client code dealing with construction of objects I created a class that (to my understanding) is simple factory with a factory method. Code below:
public static DataPersister createDataPersister(Boolean saveToDb, Session session, String filename) {
if (saveToDb) {
return new DatabaseDataPersister(session);
} else {
return new FileDataPersister(filename);
}
}
With this setup client code doesn't have to deal with constructing anything or deciding whether to save to DB or file - it can just call a save() method on an object returned by the factory like so:
DataPersister dataPersister = DataPersisterSimpleFactory.createDataPersister(this.savetoDb, this.session, this.filename);
dataPersister.save(this.data);
My question is - is this solution breaking SOLID principles? In order to create e.g. a DatabaseDataPersister client code needs to pass on a filename parameter, and this implementation of DataPersister won't have any use of it. I feel like it doesn't sit right with something similar to Interface-segregation principle but not quite that.
And if the solution is indeed a code smell - how do I go about cleaning it?
The SOLID principle I think is in violation is DIP.
Your client classes, by having to depend on the static factory directly, have a compile-time dependency on actual implementations, DatabaseDataPersister and FileDataPersister, rather than just the abstraction DataPersister.
To solve, supply to the client the DataPersister you want them to use. The constructor is usually a good place for this:
public class ExampleClient {
private final DataPersister dataPersister;
public ExampleClient(DataPersister dataPersister) {
this.dataPersister = dataPersister;
}
public void methodThatUsesSave(){
dataPersister.save(data);
}
}
This code compiles without the concrete implementations, i.e. it has no dependency on them. The client also doesn't need to know the filename or session so it solves that code smell too.
We can decide which concrete implementation to give it at construction time, here I use your existing method:
DataPersister dataPersister = DataPersisterSimpleFactory.createDataPersister(this.savetoDb, this.session, this.filename);
ExampleClient example = new ExampleClient(dataPersister);
This is a perfect opportunity to use the factory pattern
interface DataPersister {
void persist(String s);
}
private class DatabasePersister implements DataPersister {
final Session session;
public DatabasePersister(Session session) {
this.session = session;
}
#Override
public void persist(String s) {
System.out.println("Persist to database: " + s);
}
}
private class FilePersister implements DataPersister {
final String filename;
public FilePersister(String filename) {
this.filename = filename;
}
#Override
public void persist(String s) {
System.out.println("Persist to file: " + s);
}
}
class PersisterFactory {
public DataPersister createDatabasePersister(Session session) {
return new DatabasePersister(session);
}
public DataPersister createFilePersister(String filename) {
return new FilePersister(filename);
}
}
public void test(String[] args) {
DataPersister databasePersister = new PersisterFactory().createDatabasePersister(new Session());
databasePersister.persist("Hello");
DataPersister filePersister = new PersisterFactory().createFilePersister("Hello");
filePersister.persist("Hello");
}
You already pass a bunch of stuff irrelevant to various persisters.
As it stands you need a method that takes a Session and one that takes a String and you're done. No need for a boolean, no need for useless params. That handles your decision making with no cruft.
Whether or not that's a good idea... I'm ambivalent. You're not saving much; might as well just have a static factory in each type so it's explicit in the code what type you're creating.
Consider what happens when you add a new persister, like a REST endpoint, that would take a URL (could be a string, could be an actual URL). You now need even more useless parameters etc. Or you could pass in a URI from the beginning, e.g., file:// or http:// and get around that problem.
There are any number of ways this could be done–I'm not convinced there's a "clearly correct" answer, and it may boil down to opinion.
Well the right solution here is combining the dependency injection from weston and the factory pattern from OldCurmudgeon.
public class ExampleClient {
private final DataPersister dataPersister;
public ExampleClient(DataPersister dataPersister) {
this.dataPersister = dataPersister;
}
public void methodThatUsesSave(){
dataPersister.save(data);
}
}
class PersisterFactory {
public DataPersister createDatabasePersister(Session session) {
return new DatabasePersister(session);
}
public DataPersister createFilePersister(String filename) {
return new FilePersister(filename);
}
}
The upper level code:
PersisterFactory = new PersisterFactory();
DataPersister dataPersister;
if (saveToDb)
dataPersister = PersisterFactory.createDatabasePersister(new Session());
else
dataPersister = PersisterFactory.createFilePersister("Hello");
ExampleClient example = new ExampleClient(dataPersister);
Usually the dataPersister comes from the DI container and the saveToDb comes from the config, but of course testing can be an exception.
This is a bit of a design question involving inner classes in Java (Java 8). All of the example code is below my text
As an example, let's say I have some machinery that involves pumping fuel from an oil geyser to some sort of burner, which I can control using an external API called OilAPI.
I have a Controller class which is doing the work and decides which burner needs to get oil from which geyser, but I don't want the logic of using the API's classes like Geyser and Burner to leak out into the Controller (also since the API does still undergo some changes over time).
Now, to encapsulate it, so I create a class called FuelFacility which contains all of the logic of the OilAPI.
The thing is, I've put the classes Pump and Engine as inner classes inside of FuelFacility.
First of all, this is for the syntax of being able to go Pump.activate() instead of FuelFacility.activatePump(...) or whatever.
Further is that in order to connect a Geyser and Burner in the Oil API, you need both the Geyser and Burner objects, but I don't want to expose them externally, so in order to have some sort of "Connect Pump and Engine" method, I have to allow either the Pump to access the Engine's Burner variable, the Engine to access the Pump's Geyser +variable, or the FuelFacility to access both these variables. In the example below, I have a Engine.connectToPump(pump) method, which is basically the way it works in my actual code.
My teammates thought that this is a bit strange; they said that the accessing the private variables across the classes breaks encapsulation, and especially that a programmer looking at the code from the "outside" (i.e., from the point of view of working in the Controller class) would assume that once you have obtained the Engine and Pump objects, they would no longer depend on e.g. which OilAPI object the original FuelFacility is using (although this should remain final, as I've done below) nor on each other.
Now, since then, I've managed to change their minds a bit - that basically this is just a way of doing things that they're not used to, but that it's not bad practice.
However, now I am busy altering some other code to work in a similar fashion to this, and I just want to make sure before I continue, is what I am doing good practice? Is there a better way of doing things? Advice is appreciated!
CODE:
Oil API (not under my control):
public class OilAPI {
private final Pipes pipes = new Pipes();
public static class Geyser {}
public static class Burner {}
public static class Pipes {
public void createConnectionBetweenGeyserAndBurner(Geyser g, Burner b) {
// Connects geyser and burner
}
}
public Geyser getGeyserWithId(String id) {
// Actually retrieves a specific instance
return new Geyser();
}
public Burner getBurnerWithId(String id) {
// Actually retrieves a specific instance
return new Burner();
}
public void activateGeyser(Geyser g) {
// do stuff
}
public void activateBurner(Burner b) {
// do stuff
}
public void createConnectionBetweenGeyserAndBurner(Geyser g, Burner b) {
pipes.createConnectionBetweenGeyserAndBurner(g,b);
}
}
Fuel Facility (class I created to encapsulate the Oil API):
public class FuelFacility {
private final OilAPI oil;
FuelFacility(OilAPI oil) {
this.oil = oil;
}
public Pump getPumpForId(String id) {
OilAPI.Geyser geyser = oil.getGeyserWithId(id);
return new Pump(geyser);
}
public Engine getEngineForId(String id) {
OilAPI.Burner burner = oil.getBurnerWithId(id);
return new Engine(burner);
}
public class Pump {
private final OilAPI.Geyser geyser;
private Pump(OilAPI.Geyser geyser) {
this.geyser = geyser;
}
public void activate() {
oil.activateGeyser(geyser);
}
}
public class Engine {
private final OilAPI.Burner burner;
private Engine(OilAPI.Burner burner) {
this.burner = burner;
}
public void connectToPump(Pump pump) {
oil.createConnectionBetweenGeyserAndBurner(pump.geyser, burner);
}
public void activate() {
oil.activateBurner(burner);
}
}
}
Controller (owned by me, and sits inside of our codebase):
public class Controller {
public static void main(String[] args) {
// We actually get these from a database
String engineId = "engineId";
String pumpId = "pumpId";
OilAPI oil = new OilAPI();
FuelFacility facility = new FuelFacility(oil);
FuelFacility.Engine engine = facility.getEngineForId(engineId);
FuelFacility.Pump pump = facility.getPumpForId(pumpId);
engine.connectToPump(pump);
}
}
Having inner classes access each others' private fields isn't necessary bad in itself. It seems that your main goal is to protect Controller from changes to OilAPI. In this design, FuelFacility, Pump, and Engine are so close to OilAPI, Geyser, and Burner that I'm not sure you actually protect Controller all that much. FuelFacility should be designed more for what Controller needs than what OilAPI does. In your example, you don't call activate on the Pump or Engine but I'm assuming you'd ultimately want to do that. First, I'd start by declaring some interfaces:
public interface PumpEngineConnection {
public void activate();
}
public interface FuelFacility {
public PumpEngineConnection connect(String pumpId, String engineId);
}
Controller works through these interfaces and does not know what implementations that it actually uses. Then you can make a OilAPIFuelFacility implementation of FuelFacility. The PumpEngineConnection implementation that it returns will be one specifically designed to work with OilAPIFuelFacility. You could do this with an inner class:
public class OilAPIFuelFacility implements FuelFacility {
private final OilAPI oil;
public OilAPIFuelFacility(OilAPI oil){ this.oil = oil; }
#Override
public PumpEngineConnection connect(String pumpId, String engineId){
Geyser geyser = oil.getGeyserWithId(pumpId);
Burner burner = oil.getBurnerWithId(engineId);
oil.createConnectionBetweenGeyserAndBurner(geyser, burner);
return this.new GeyserBurnerConnection(geyser, burner);
}
private class GeyserBurnerConnection implements PumpEngineConnection {
private final Geyser geyser;
private final Burner burner;
private GeyserBurnerConnection(Geyser geyser, Burner burner){
this.geyser = geyser;
this.burner = burner;
}
#Override
public void activate() {
OilAPIFuelFacility.this.oil.activateGeyser(this.geyser);
OilAPIFuelFacility.this.oil.activateBurner(this.burner);
}
}
}
Each GeyserBurnerConnection implicitly gets a reference to the OilAPIFuelFacility that created it. That's reasonable because it only makes sense to use a PumpEngineConnection with the FuelFacility that created it. Likewise, it's perfectly reasonable for GeyserBurnerConnection to reference the oil member from OilAPIFuelFacility.
That said, it may make more sense for GeyserBurnerConnection to be a package-private class in the same package as OilAPIFuelFacility. It may be that different versions of the OilAPI can use the same GeyserBurnerConnection class.
Finally, the Controller could look something like this:
import com.example.fuelfacility.FuelFacility;
import com.example.fuelfacility.PumpEngineConnection;
public Controller {
private final FuelFacility fuelFacility;
public Controller(FuelFacility fuelFacility){
this.fuelFacility = fuelFacility;
}
public void example(){
String pumpId = "pumpId";
String engineId = "engineId";
PumpEngineConnection connection = fuelFacility.connect("pumpId", "engineId");
connection.activate();
}
}
Note that it's completely ignorant of what implementation of FuelFacility and PumpEngineConnection it actually uses. In practice, we'd pass in OilAPIFuelFacility with a dependency injection framework or an external Main class.
I realize that your example is probably simplified from what you actually need to do. Nonetheless, you should really think in terms of what Controller needs and not what OilAPI does.
Finally, I should note that I generally agree with your colleagues' concerns about your design. Consider this snippet:
OilAPI oil1 = new OilAPI();
OilAPI oil2 = new OilAPI();
FuelFacility fuel1 = new FuelFacility(oil1);
FuelFacility fuel2 = new FuelFacility(oil2);
Engine engine = fuel1.getEngineForId("engineId");
Pump pump = fuel2.getPumpForId("pumpId");
engine.connectToPump(pump);
What happens? Then oil1 is used to connect a Pump which was retrieved through oil2. Depending on the internals of OilAPI that would likely be a problem.
A Piece of important information: The classes are all separate files and there are about 10 beans in total .
I am working on a project with multiple classes through which data must be passed.
I.e. a couple strings from say Class1 must be able to be used in Class2.
My program uses JavaBeans with set and get methods but if I set a bean in one class and try to get that data in another class I just get a null value returned.
I am unsure as to what the best method is, I have the beans nicely defined and would like to keep using them but I do not know how.
Could someone point me in the correct direction or give an example.
Thanks
Edit
Bean class snippet;
public class beans implements java.io.Serializable {
private String string1;
public String getstring1() {
return this.string1;
}
public void setstring1(String string1) {
this.string1 = string1;
}
And the setter code in say class1:
beans bean = new beans();
bean.setstring1("test");
And the class where the bet is "got", class2
beans bean = new beans();
String text = bean.getstring1();
That is pretty much how I am using the beans and they are not working as I want them to.
In your example you are creating a new bean in each class. The first and the second class have references to two different objects, that's why they can't access the same values.
There are multiple ways to solve this and it really depends on your application. But let me suggest one generic solution.
You can create a BeanRepository which is responsible for having references to all bean objects. Other classes then need to know the id of the bean and they can get a reference.
BeanRepository (notice the static methods):
public class BeanRepository {
private static Map<Integer, Bean> beanMap = new HashMap<Integer, Bean>();
public static void putBean(int id, Bean bean) {
beanMap.put(id, bean);
}
public static Bean getBean(int id) {
return beanMap.get(id);
}
}
The bean:
public class Bean {
private String name;
public Bean(String name) {
this.name = name;
}
public String whoAmI() {
return name;
}
}
Classes A and B:
public class ClassA {
private Bean bean;
public ClassA(int beanId) {
this.bean = BeanRepository.getBean(beanId);
}
public void test() {
System.out.println("I am ClassA. You are " + bean.whoAmI());
}
}
public class ClassB {
private Bean bean;
public ClassB(int beanId) {
this.bean = BeanRepository.getBean(beanId);
}
public void test() {
System.out.println("I am ClassB. You are " + bean.whoAmI());
}
}
Test method:
public class Main {
public static void main(String[] args) {
BeanRepository.putBean(1, new Bean("one"));
ClassA a = new ClassA(1);
ClassB b = new ClassB(1);
a.test();
b.test();
}
}
container I am very puzzled by your question. Are you referring to Enterprise Java Beans?
If you just mean ordinary JavaBeans just featuring get and set methods, the first thing I would advise is to learn how to use jUnit. Test your data bean first inorder to ensure it is working as intended.
Beside that if your class live within the same JVA (you only start a single java.exe / run a single application) everything should just work fine.
public class Data {
private String value;
public void set(String value) { this.value = value; }
public String get() { return this.value; }
}
public class ClassA {
Data data = new Data();
ClassA() { data.set("From ClassA"); }
}
public class ClassB {
Data data;
ClassB(Data data) { this.data = data; }
public void print() {
System.out.println(data.get());
}
}
public static void main(String args []) {
new ClassB(new ClassA().data).println();
}
This is a simple example using a data object to pass informations around.
Hope this is what you want to know.
[Update]
After you add some code I see the problem. As other users already wrote you are creating new objects (instances) every time. Since the string1 is a property of that class ever instance of it will have their own value.
The default example is a person. Creating a Person class with a property name (similar to your string1) you can create two persons (instances of class Person). You can now name every person individual.
Thats what Class mean. You specify the properties (instance variables) and behavior (methods) of instances (actual object) of that class.
If you want to share information you need a way to pass(!) an instance (object) of a Class to other instances. In Java different way exist. You can use static variables which are global (bound to the Class instead of an instance of a class), you can use singleton pattern (which employes the static variable), you can use ThreadLocal (a global store limited to the current thread), you may use managers / repositories storing objects and you pass the manager / repository objects along, you can use databases or you can use a dependency injector which is like a transparent object manager. Those are basically it.
For your use case I would use Singleton first.
public class MySingleton {
private static Bean myBean;
public static void setBean(Bean myBean) { MySingleton.myBean = myBean; }
public static Bean getBean() { return myBean; }
}
Using the class is straight forward:
Bean bean = new Bean();
bean.setString1("test");
MySingleton.setBean(bean);
Bean bean2 = MySingleton.getBean();
System.out.println(bean2.getString1()); //prints test
But beware this is the lazy way of doing things. Using static has some draw backs if you have a complex project especially when it comes to serialization, concurrency and reuse.
If you'se serializing/deserializing your classes, make sure that
string fields themselves are not marked as transient.
you're not using custom writeObject(ObjectOutputStream ) methods in your object where you forgot your string fields.
you're not cloning your class with custom clone() methods where you forgot your string field
you wrote setter and getter properly in the first place.
and things shoud work ;)
I am providing Settings of my JAVA project in a Prefs.java class with static attributes and static methods. But the token for OAuth2 needs to be assigned on runtime. Is this a good way to go... ?
public class Prefs {
//known before runtime
public static final String SERVER_BASE_URL ="http://api.mycompany.com/";
//needs to be set on startup through the setter method
private static String token;
public static String getToken() {
return token;
}
public static void setToken( String token ) {
Prefs.token = token;
}
public static String getXyEndpointUrl() {
return SERVER_BASE_URL + "/xy";
}
}
I would advice against such design. This type of static variables no better than global variables. This page gives a few reasons why you should avoid them. Here are a few of them.
Non-locality
No Access Control or Constraint Checking
Implicit coupling
Concurrency issues
Testing and Confinement
But the token for OAuth2 needs to be assigned on runtime. Is this a good way to go... ?
Here it really seems to me like you would want to pass such token to the constructor of the Prefs object.
Static variables are object-oriented substitutes for global variables in C. Try to avoid them whenever possible.
Many times you only need one object, in your case it's the Prefs object.
public class Prefs {
//known before runtime
public final String SERVER_BASE_URL ="http://api.mycompany.com/";
//needs to be set on startup through the setter method
private String token;
public String getToken() {
return token;
}
public void setToken( String token ) {
Prefs.token = token;
}
public String getXyEndpointUrl() {
return SERVER_BASE_URL + "/xy";
}
}
public class Program {
protected Prefs prefs;
protected Other prefsAware;
public Program() {
prefs = new Prefs();
prefsAware = new Other(prefs);
}
// or even (if you don't like constructor mediated passing of prefs)
public Prefs getPrefs() {
return prefs;
}
}
typically global configs are read from properties files at runtime. You can have varying config files for the development, QA, production environments.
The only thing you need to at least be aware of is that in a web application, if you set static variables from a web request, you could munge the data if you do not synchronize the setter. If you are only reading then you should be fine.
An alternative to what you are doing is why not inject the OAuth key into a service that handles the authentication concerns of your system? You could do what you need to do with a static resource, but in this case, but you should be aware that you don't really need a static variable to hold the key.