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.
Related
Currently, I have a class whose constructor takes a username, password, and Context. I would like to be able to access this object from anywhere, so I was thinking of implementing a singleton pattern.
The current constructor uses the credentials passed in to authenticate future api calls through that class. If I were to implement the singleton pattern, my first thought would to be have the getInstace() method take a username, password, etc.., but it seems wrong to have to pass that info everytime i grab an instance. Because of this I was thinking of adding some sort of .authenticate(usr, pswrd) method to be called when grabbing the first instance.
My question is, is this the correct approach? If not, what would be a good way to handle this? Heres the current code:
constructor:
public Play(String username, String password, Context context) {
api = getApi(username, password);
Intent intent = new Intent(context, MyService.class);
context.bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
//check if first run
//if so, call api for info and store locally
//if not, update as needed
SharedPreferences pref = context.getSharedPreferences("pref", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = pref.edit();
if (pref.getBoolean("first_run", true)) {
loadInitialData(context);
}
editor.putBoolean("first_run", false);
editor.commit();
}
Singleton pattern restricts the instantiation of a class and ensures that only one instance of the class exists in the java virtual machine. The singleton class must provide a global access point to get the instance of the class. Singleton pattern is used for logging, drivers objects, caching and thread pool
This code is not tested but should give you an idea how you can use singleton pattern while using SharedPrefrencess.
Constructor is private, So only getInstance() method can access the instance, so you will create an instance of this class if it doesn't exists or if instantiated previously use that instance
synchronization is required to make sure when multiple thread are trying to make a instance for the first time
import android.content.Context;
import android.content.SharedPreferences;
/**
* Created by Pankaj Nimgade on 23-05-2016.
*/
public class Play {
/**
* volatile keyword ensures that multiple threads handle the uniqueInstance
* variable correctly when it is being initialized to Singleton instance
*/
private volatile static Play play;
private static final String XML_FILE = "play_xml_file.xml";
private static final String KEY_DATA = "SOME_DATA_KEY";
private static final String KEY_USERNAME = "SOME_USERNAME_KEY";
private static final String KEY_PASSWORD = "SOME_PASSWORD_KEY";
private static SharedPreferences sharedPreferences;
private static SharedPreferences.Editor editor;
private Play() {
}
public static Play getInstance(Context context) {
if (play == null) {
synchronized (Play.class) {
if (play == null) {
sharedPreferences = context.getSharedPreferences(XML_FILE, Context.MODE_PRIVATE);
editor = sharedPreferences.edit();
play = new Play();
}
}
}
return play;
}
public boolean saveSomeData(String someData) {
editor.putString(KEY_DATA, someData);
return editor.commit();
}
public String readSomeData() {
return sharedPreferences.getString(KEY_DATA, "default Value");
}
public boolean saveUserNameData(String username) {
editor.putString(KEY_USERNAME, username);
return editor.commit();
}
public String readUserNameData() {
return sharedPreferences.getString(KEY_USERNAME, "default username Value");
}
public boolean savePasswordData(String password) {
editor.putString(KEY_PASSWORD, password);
return editor.commit();
}
public String readPasswordData() {
return sharedPreferences.getString(KEY_PASSWORD, "default password value");
}
}
in this above approach I am making instance creation of the class lazy, as the instance will only be created if demanded, although the code is thread safe and will work on all Java version you may want to consider different approach to implement this if you are using Java 5 and above.
https://sourcemaking.com/design_patterns/singleton/java/1
public class Singleton {
// Private constructor prevents instantiation from other classes
private Singleton() {}
/**
* SingletonHolder is loaded on the first execution of Singleton.getInstance()
* or the first access to SingletonHolder.INSTANCE, not before.
*/
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
The inner class is referenced no earlier (and therefore loaded no earlier by the class loader) than the moment that getInstance() is called. Thus, this solution is thread-safe without requiring special language constructs (i.e. volatile or synchronized).
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.
Is there any way to make field static or transient using java reflection API.
EDIT: I have some Beans that are already being serialised using soap api and is being used by some clients, for some clients i don't want to expose one or two fields.
Sure there are so many ways to do it without changing or adding transient keyword.
Just want to know if it can be done, and if so, how ?
EDIT: I wouldn't call it an API or framework issue, more like a design flaw...
I'm using apache axis2 for soap
No. Such a thing would require modifying the byte code of the class. A particular difficulty in the case of static fields is that they are accessed using different bytecodes than object fields.
I don't see a why a field couldn't be made transient in runtime, at least in theory, but the current reflection API doesn't allow it. See also: Can a field's transient property/flag be set through reflection in java?
You can't do it with the reflection api. I think there are some byte-code manipulation tools but in this case you can use the Decorator pattern. It solves the problem but I think it is extremely ugly:
(I omited the usual boilerplate from here such as interfaces)
public class StaticDecorator {
private static Object staticField;
private Object yourObject;
public StaticDecorator(Object yourObject) {
this.yourObject = yourObject;
}
public static Object getStaticField() {
return staticField;
}
public static void setStaticField(Object object) {
staticField = object;
}
}
I used Object for the type of the class you are going to wrap but of course you can substitute any type you want. Using an approach like this you can "decorate" any class with a static field.
If you are really, extremely must want a static field in an object at run time this can help you but I think that there is a design flaw lurking somewhere.
You can wrap your bean inside another bean that only exposes the fields that you'd like to expose through your API. For example, with an internal bean with the fields foo, bar, and baz, where you do not want to expose baz.
Lombok Delegation can make this incredibly simple, but here's an example using plain-old-Java.
public class ExposedBean {
private InternalBean internalBean;
public ExposedBean(InternalBean internalBean) {
this.internalBean = internalBean;
}
public String getFoo() { return internalBean.getFoo(); }
public String getBar() { return internalBean.getBar(); }
}
public class InternalBean {
private String foo;
private String bar;
private String baz;
public String getFoo() { return foo; }
public String getBar() { return bar; }
public String getBaz() { return baz; }
}
Original answer, regarding setting modifiers
You can not set modifiers. You can check them, however.
Field myField = /* get a field object */;
if (Modifier.isTransient(myField.getModifiers()) {
System.out.println("myField is transient.");
}
if (Modifier.isFinal(MyClass.class.getModifiers()) {
System.out.println("MyClass is final.");
}
With more information about the problem you're trying to solve, we can suggest alternatives. Member#getModifiers() is not declared final, so you could possibly use a decorator. (The below code is 100% untested.)
public class FieldModifierDecorator extends Field {
protected Field field;
private int modifiers = -1;
public static void decorate(Field field) {
FieldModifierDecorator newInstance = new FieldModifierDecorator();
newInstance.field = field;
return newInstance;
}
public void overrideModifiers(int modifiers) {
this.modifiers = modifiers;
}
public int getModifiers() {
if (-1 == modifiers) {
return field.getModifiers();
}
return modifiers;
}
}
// Example usage
public Field makeFieldAppearTransient(Field field) {
FieldModifierDecorator decoratedField = FieldModifierDecorator.decorate(field);
decoratedField.overrideModifiers(field.getModifiers() | Modifier.TRANSIENT);
// if (Modifier.isTransient(decoratedField.getModifiers())) {
// System.out.println("It looks transient, but really isn't.");
//}
return decoratedField;
}
Modfifying class information or byte code modification is definitely the wrong tool for the job. You are trying to solve a business problem with solely technical tools.
It sounds more like you need a permission concept. Users may have permission to see some fields. Based on that you could use java bean introspection to clear the values of those fields just before they are sent to the client.
However this might have its problems as well. A client should be able to determine if it has permission to see that field or not.
I have a design question: let me expalin in simple example:
Public class A()
{
public static HashMap map = new HashMap();
public static String url = "default";
static {
getJson();
}
//url getters and setters are defined
public static getJson() {
//code which uses url to get json and populate hashmap
}
public string getresult(String key) {
//uses hashmap to send result.
}
I am using static initialization block because i want to get json only once.
public class B {
//here I want to change url and call getJson method. If i call A.setUrl() then before setting url, A.getJson () method is called as it is in static initialization block.how can i set url first and then call getJson().
//is this a bad design?
}
Yes, it is bad design:
It is impossible to customize where A gets its data from without modifying the definition of A. Among other things, this prevents unit testing (as you probably don't want to fail the unit test if the network is unavailable ...).
If initialization fails (for instance because the remote URL is currently unavailable), you can't easily catch that exception, as you don't know which access triggered loading. You can't throw a checked exception from a static initializer. You can't retry initialization either (all subsequent access immediately result in an exception).
If you must access A through a static field, I'd recommend:
public class A {
private static Map<String, String> map;
/** must be invoked before get is first called */
public static void init(Map<String, String> newmap) {
map = newmap;
}
public static String get(String key) {
return map.get(key);
}
}
This separates the concern of using the data from the concern of obtaining it, allowing each to be replaced and tested independently.
Also consider getting rid of static, as it enforces there is only ever one map in your entire application at the same time, which is quite inflexible. (See the second code sample in Ajay's answer for how)
This should work I guess. Add a new method.
public static void getJson(String url) {
setUrl(url);
getJSon();
}
Static Initializers are generally a bad idea because unit testing becomes difficult .
Check out Misko Hevery's Guide to writing Testable Code.
You can rework the design by doing something like this :
public class A {
//Add generics
private Map map = new HashMap();
public A(Map map){
this.map = map;
}
public String getresult(String key) {
//uses hashmap to send result.
}
}
//Helper Class
public class URLToJSon() {
//Add private constructor
public static Map convertUrlToJSon(String url) {
//do the conversion and return a hashmap
}
}
In this manner we get to follow the Single Responsibility Principle.
Now both the classes are testable as well.
Where is the URL set? In the constructor? If so, simply do
//Normal init stuff like set url here, followed by
if (! some check for if json is set) {
setJson();
}
I have a question about the following code:
public Class Settings{
public static final String WelcomeMessage= "helloworld";
public static final String ByeMessage= "yo";
public static String[] widgets = {WelcomeMessage,ByeMessage};
}
The compiler complains about duplicat variables. Can I delete the 2 separate variables and still acces WelcomeMessage by Settings.WelcomeMessage? I don't need to acces it by Settings.widget[0]? And is it possible to add another variable to the WelcomeMessage variable (by for instance using a static hashtable)?
Edit: I know this code doesn't look right but it's just an example because I wondered why the compiler thinks WelcomeMessage (as a separata variable) is the same as the variable in the Widgets array.
I would consider java-enums in your case:
public enum Settings {
WelcomeMessage ("helloworld"),
ByeMessage ("yo");
public final String value;
Settings(String value) {
this.value = value;
}
}
You can access now the values via Settings.WelcomeMessage.value. Also you get a List of the enums with Settings.values().
You've marked the fields as public static which means that yes you'll be able to access them via:
Settings.WelcomeMessage
or if you you use a static import in your class, just:
WelcomeMessage
You haven't actually used these constants in the widgets array, you've just created two new strings in there "WelcomeMessage" and "ByeMessage"
public static String[] widgets = {"WelcomeMessage","ByeMessage"};
No, if you delete the WelcomeMessage and ByeMessage constants you can't access them in that way, you'd have to go through the widgets array and access them as:
Settings.widgets[0]
I think you meant to use this instead:
public Class Settings
{
public static final String WelcomeMessage= "helloworld";
public static final String ByeMessage= "yo";
public static String[] widgets = {WelcomeMessage,ByeMessage};
}
But this is better:
public Class Settings
{
public static String[] widgets = {"WelcomeMessage","ByeMessage"};
}
And yes you can access WelcomeMessage via Settings.widgets[0].
Edit: Oops - yep - of course you cannot access them by name, only index into the array.
Edit 2: If you make the field protected or private and provide 'getter' methods, then it doesn't matter to any user classes how they are implemented:
public Class Settings
{
private static final String welcomeMessage= "helloworld";
private static final String byeMessage= "yo";
public static String getWelcomeMessage()
{
return welcomeMessage;
}
public static String getByeMessage()
{
return byeMessage;
}
}