I need to create message class that can retrieve the data for message and print it out the problem is that I must provide in the message class to the static filed value like (public static String exc01 ="testErr";) if I remove the equal "testErr"; Im getting an error;
Exception in thread "main" java.lang.NullPointerException
at java.util.PropertyResourceBundle.handleGetObject(Unknown Source)
at java.util.ResourceBundle.getObject(Unknown Source)
at java.util.ResourceBundle.getString(Unknown Source)
at test1.Messages.getString(Messages.java:19)
at test1.TestMessageClass.main(TestMessageClass.java:8)
1.why should I provide value to the static string exc01 in class message if the message properties file already contain the error value?
2.there is better/nicer to do this all logic of messages ?
for that I have created message class as follows
package msg;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
public class Messages {
private static final String BUNDLE_NAME = "test1.messages";
private static final ResourceBundle RESOURCE_BUNDLE = ResourceBundle.getBundle(BUNDLE_NAME);
public static String exc01 ="testErr";
public static String exc02;
private Messages() {
}
public static String getString(String key) {
try {
return RESOURCE_BUNDLE.getString(key);
} catch (MissingResourceException e) {
return '!' + key + '!';
}
}
}
I have file for message under the same package which is called messages.properties and contain the following message
exc01=Failed to create the extension for {0}
exc02=Failed to create the extension
I have created simple test program
public class TestMessageClass {
public static void main(String[] args) {
System.out.println(Messages.getString("exc01"));
System.out.println(Messages.getString(Messages.exc01));
}
}
print
Failed to create the extension for {0}
!testErr!
Your code calls
Messages.getString(Messages.exc01)
Messages.exc01 is a variable or type String. Its default value is null. It's not "exc01" as you seem to believe. You're confusing the name of a variable with its value.
So, if you don't initialize the variable, the code above tries to get the message from the properties file having a null key, which doesn't make sense: you must provide a non-null key, and that's why you get a NullPointerException.
If you want to get the message for the key "exc01", then you can use
Messages.getString("exc01")
or you can initialize any String variable to "exc01", and pass this variable:
public static String exc01 = "exc01";
...
Messages.getString(Messages.exc01);
Note that exc01 should be defined as a constant, and not as a variable. It should thus be final, and respect the Java naming conventions for constants:
public static final String EXC01 = "exc01";
...
Messages.getString(Messages.EXC01);
Note that if you initialize the variable with "testErr", as you did, the code will look for the message associated with the key "testErr" in the properties file. And since such a message doesn't exist, you'll get a MissingResourceException, and the ctach block will thus return !testErr!. That's why you have !testErr! in your test output.
Related
I have properties file app.properties and it has 50 different properties.
I am accessing those in my java class using
Properties prop = new Properties();
prop.load("app.properties");
System.out.prinltn(prop.getProperty("APPNAME"));
Actually, I want to get rid of accessing property like prop.getProperty("APPNAME"). Is there any best way in java to access properties.
I can declare all variables as static in java class.
static String appName = prop.getProperty("APPNAME");
Any other best way available?
I can suggest two approaches:
1. Define a utility method which will take String as parameter and return value from properties.
For Example:
public static String GetValue(String key) {
return properties.getProperty(key);
}
And now you can use this function on callers
String value = GetValue("key"); // properties.getProperty("key");
Define above method and in addition create one class Called Constants(or something suitable). Define all your Keys here as Static final variable.
public class Constants
{
public static final String KEY = "key";
public static final String KEY2 = "key2";
}
and now make call for getting value using these variable instead of string:
String value = GetValue(KEY); //GetValue("key");
If you do only option 1, your code is becoming more readable. But I will recommend 2nd option, which is making your code readable as well as maintainable.
You can easily do following operation :
Update property name
No need to worry about mistyping key etc.
You may use "resourceBundle" package as
First import the resourceBundle API:
import java.util.ResourceBundle;
Create an instance of your property file:
private static ResourceBundle resource = ResourceBundle.getBundle("app");
Now you can get the value of the property:
String appName = resource.getString("APPNAME");
IMO, your approach of using static variables to hold the values is the best. The following structure was what I was using in a project for the same functionality.
package snippet;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Properties;
public class Constants {
public static final String APPNAME;
public static final String VERSION;
public static final int DEFAULT_TIMEOUT;
static {
Properties p = new Properties();
try {
p.load(new FileInputStream("constants.properties"));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
APPNAME = p.getProperty("APPNAME");
VERSION = p.getProperty("VERSION");
DEFAULT_TIMEOUT = Integer.parseInt(p.getProperty("DEFAULT_TIMEOUT"));
}
}
Of course, there were checks for NumberFormatException etc.
The error message keep disallow me to compile my project in eclipse lula. I found this only happen if my util class reading the message from resources bundle, else it is working fine.
Please advise.
Below is my code:
MessageUtil.java
private static final String MSG_FILE = "com.by.go.booking.ui.messages";
private final static ResourceBundle MESSAGE = ResourceBundle.getBundle(MSG_FILE);
public static final String LOGIN_ID_EXISTS = MESSAGE.getString("ERR1");
LoginBean.java
#AssertTrue(message = MessageUtil.LOGIN_ID_EXISTS)
public boolean isLoginIdUnique() {
boolean result = false;
// validate login ID exists
........
return result;
}
From the code above, eclipse will trigger the error message:"The value for annotation attribute AssertTrue.message must be a constant expression"
Anyway, if I modify the MessageUtil.java as below, that is not error in eclipse.
MessageUtil.java
public static final String LOGIN_ID_EXISTS = "Login is invalid";
I am getting the following error message:
"Cannot make a static reference to the non-static method
getPreferences(int) from the type Activity" is the error in my case.
'TimeCardLogin' must be a static variable."
How do I get a preference into a static String variable?
public class MyBaseURLContainer extends Activity {
public static String urlPref = "";
static String BASE_URL =
getPreferences(MODE_PRIVATE).getString("Name of variable",urlPref);
public static final String TimeCardLogin = BASE_URL + "/timecard";
}
I'd recommend making a static getter that takes an Context as an argument. That way a) it will actually compile, and b) if your base-url changes at some point, it will load the most recent value, instead of loading once in the beginning like your program is:
private final static String PREFS = "myUrlPrefs";
public static String getBaseUrl(Context context) {
return context.getSharedPreferences(PREFS, MODE_PRIVATE).getString(
"Name of variable",urlPref);
}
You'd call it from another activity like this:
String baseUrl = MyBaseUrlContainer.getBaseUrl(this);
Or from anywhere you have access to a Context like this (an Activity is a Context):
String baseUrl = MyBaseUrlContainer.getBaseUrl(myContext);
If you absolutely have to use this code from somewhere that doesn't have access to a Context (which really should almost never be the case in an Android app), you could store the value after it's retrieved, but the first time you get the value it has to be from a Context.
I have a service interface that reads thus
package services;
import domain.Items;
public interface IItemsService extends IService {
public final String NAME = "IItemsService";
/** Places items into the database */
public void storeItem(Items items);
/** Retrieves items from the database
*
* #param category
* #param amount
* #param color
* #param type
* #return
* #throws ClassNotFoundException
*/
public Items getItems (String category, float amount, String color, String type) throws ItemNotFoundException, ClassNotFoundException;
}
And a factory that looks like this...
package services;
public class Factory {
public Factory(){}
#SuppressWarnings("unchecked")
public IService getService(String name) throws ServiceLoadException {
try {
Class c = Class.forName(getImplName(serviceName));
return (IService)c.newInstance();
} catch (Exception e) {
throw new ServiceLoadException(serviceName + "not loaded");
}
}
private String getImplName (String name) throws Exception {
java.util.Properties props = new java.util.Properties();
java.io.FileInputStream fis = new java.io.FileInputStream("properties.txt");
props.load(fis);
fis.close();
return props.getProperty(serviceName);
}
}
This should be really simple - but I keep getting two errors - IService cannot be resolved to a type (on both the factory and the service) and also an serviceName cannot be resolved into a variable error in the factory. I know I am missing something simple...
Regarding the type error: if IService is not in the package services, then IItemService will not have access to it and you will need to import some.package.name.IService.
The second answer is simple: in the getService and getImplName methods, the parameter is named name. In the method bodies, you're referring to it as serviceName. You should probably change name to serviceName in each of them.
If, on the other hand, you're trying to access an instance variable, note that in Java you have to declare all instance variables before you can access (read from/write to) them. You would need to modify the class as such:
public class Factory {
private String serviceName;
public Factory () {}
// other code
}
Well the second error is simple: there isn't a variable called serviceName. If you think there is, point to its declaration. I suspect you meant to use the parameter - in which case just change the parameter name to match the name you're trying to use:
public IService getService(String serviceName) throws ServiceLoadException
...
private String getImplName (String serviceName) throws Exception
This was a pretty simple error - you should think about what bit of your diagnosis let you down in working it out for yourself. (You should also indent your code more sensibly, btw.)
As for IService being missing - we have no idea where IService is meant to be declared, which makes it very hard to help you on this front...
I get the following error in my Java code:
java.lang.IllegalAccessException: Class org.apache.commons.digester.ObjectCreateRule can not access a member of class Response with modifiers ""
Is it maybe because class Response is not public class ?
If so, how can I make it accessible and keep the class Response in the same file with the main class ?
thanks
Update, Code: http://www.smipple.net/snippet/aneuryzma/on:%20is%20related%20to%20public%20/%20private%20attribute%20for%20classes%20%3F
As far as I remember your class Response should follow the bean convention: should be public, should have public default constructor and should have setters and getters for all fields that you refer from your xml.
Yes it is, as IllegalAccessException documentation says.
You can circumvent access modifiers with reflection. For example, to access private fields, use Class.getDeclaredField(String) to get a specific Field (works also for private fields - using plain getField can only get public members), and then set Field.setAccessible(true). Now the field can be used as if it was public.
You can also circumvent access modifier with JNI. It doesn't care about access modifiers at all. Yet one more way is to generate custom bytecode with a tool such as ASM.
can not access a member of class Response with modifiers ""
A member is an instance variable, modifiers are public, protected, static, ...
So it looks to me, that the Response class has a field that can't be accessed or created through the apache-commons-digesters ObjectCreationRule.
Either you have a Response class that is not compatible with digester or the error lies within the xml file that defines the Response class.
Looking at your code - the only Java "items" with no access modifiers are the classes Response and Request. Maybe the error tells us that those classes have to be public.
ObjectCreateRule attempts uses the loads Request via it's class name and then invokes Class.newInstance(). For this to work the Request and Response both need public and have public default constructors.
You have two options for this:
1. Place Request and Response in their own source files and make them public
2. Nest Request and Response inside your public top level class and make them public static.
If you took option two then your code would look like this:
import java.io.Reader;
import java.io.StringReader;
import org.apache.commons.digester.Digester;
public class DigExample {
public static void main(String ar[]) {
try {
Digester digester = new Digester();
digester.setValidating( false );
digester.addObjectCreate( "response", Response.class );
digester.addObjectCreate( "response/request", Request.class );
digester.addBeanPropertySetter("response/request/name", "name" );
digester.addBeanPropertySetter("response/request/value", "value" );
digester.addSetNext( "response/request", "setRequest" );
digester.addBeanPropertySetter( "response/matches", "matches" );
Reader reader = new StringReader(
"<?xml version='1.0' encoding='UTF-8'?>" +
"<response>" +
"<request><name>books</name><value>xml</value></request>" +
"<matches>20</matches>" +
"</response>");
Response response = (Response)digester.parse( reader );
System.out.println( response.toString() );
} catch( Exception exc ) {
exc.printStackTrace();
}
}
static public class Response {
public Response(){}
private int _matches = 0;
private Request _request;
public Request getRequest() {
return _request;
}
public void setRequest(Request request) {
_request = request;
}
public int getMatches() {
return _matches;
}
public void setMatches(int matches) {
_matches = matches;
}
}
static public class Request {
public Request() {}
private String _name = "";
private String _value = "";
public String getName() {
return _name;
}
public void setName(String name) {
_name = name;
}
public String getValue() {
return _value;
}
public void setValue(String value) {
_value = value;
}
}
}
As other people have mentioned, if you were using reflection directly yourself you could probably circumvent the access modifiers, but this isn't an option in your example.