this is the issue at hand, when trying to serialize the class below with the code below i'm getting is the below xml file without all the strings in the class.
The Class (some static values have changed but basically it), I left out all the generated get\set but they are all there with public access modifiers.
public class NotificationConfiguration implements Serializable
{
public static final String PORT_KEY = "mail.smtp.port";
public static final String DEFAULT_PORT_VALUE = "587";
public static final String TTL_KEY = "mail.smtp.starttls.enable";
public static final String DEFAULT_TTL_VALUE = "true";
public static final String AUTH_KEY = "mail.smtp.auth";
public static final String DEFAULT_AUTH_VALUE = "true";
public static final String MAIL_SERVER_KEY = "mail.smtp.host";
public static final String DEFAULT_MAIL_CLIENT_HOST = "smtp.gmail.com";
public static final String DEFAULT_MAIL_CLIENT_USERNAME = "*********";
public static final String DEFAULT_MAIL_CLIENT_PASSWORD = "*********";
public static final String DEFAULT_MAIL_CLIENT_ADDRESS = "*********";
public static final String DEFAULT_ADMIN_EMAIL = "*********";
public static final long DEFAULT_MAIL_INTERVAL = 24*60*60*1000; //One time a day default
public static final String SAVED_FOLDER_NAME = "C:\\Library";
public static final String SAVED_FILE_NAME = "C:\\Library\\NotificationCfg.xml";
private String portValue = DEFAULT_PORT_VALUE;
private String ttlValue = DEFAULT_TTL_VALUE;
private String authValue = DEFAULT_AUTH_VALUE;
private String mailClientHost = DEFAULT_MAIL_CLIENT_HOST;
private String mailClientUserName = DEFAULT_MAIL_CLIENT_USERNAME;
private String mailClientPassword = DEFAULT_MAIL_CLIENT_PASSWORD;
private String mailClientAddress = DEFAULT_MAIL_CLIENT_ADDRESS;
private String adminEMail = DEFAULT_ADMIN_EMAIL;
private boolean overdueSubsNotificationEnabled = false;
private boolean adminReportNotificationEnabled = false;
private long mailInterval =
}
The code used to serialize, which also creates the folder if missing.
public void storeChanges()
{
try
{
try
{
File f = new File(NotificationConfiguration.SAVED_FOLDER_NAME);
f.mkdir();
}
catch (Exception e){}
XMLEncoder encoder = new XMLEncoder( new BufferedOutputStream(new FileOutputStream(NotificationConfiguration.SAVED_FILE_NAME)));
encoder.writeObject(notificationConfig);
encoder.close();
System.out.println(LOG_CONFIGURATION_STORED);
}
catch (Exception ex)
{
System.out.println(LOG_CONFIGURATION_NOT_STORED + ex.getMessage());
}
}
The XML file received, with no exceptions thrown while serializing.
It basically just has the long value.
XMLEncoder encodes information about how to restore your object. If field values haven't changed from their defaults, XMLEncoder doesn't store anything.
This can cause confusion.
Hence, my rules of thumb when using XMLEncoder are:
1. don't initialize fields. don't do private String foo = DEFAULT_FOO;
2. don't do anything in the default constructor.
3. have some other method, or factory that will give you a "default" setup if needed.
I highly recommend to read again the XMLEncoder Javadoc
I will point out the main differences with the binary serialization we all know.
to restore the instance it need the class definition available to the JVM
It serializes only the data. And only the modified from default data.
As result of the 2 points above - is that there is no reason to serialize Static final values - they are part of the class definition.
The binary serialization on the other hand does serialize the class definition and can load from byte stream a class that was not available to the JVM before.
That is why you got results that you see. It Ok this is behavior by design and you use it right. It seems just not to be what you need.
By the way see what Xstream has to offer.
What is SAVED_FOLDER_NAME ? Is that like a factory object and did you by any chance call setMailInterval on that object?
Could that be that only mailInterval has a getter?
Just looked again the question apparently there is getter for all fields so ...
Related
I'm Working in A new Project and I already coded config.java for my project
My config.java code
package com.egf.myapp;
public class Config {
public static final String APP_API_URL = "http://www.egypt-freelancers.me/en/index.php";
public static final String APP_IMAGES_URL = "http://www.egypt-freelancers.me/uploads/";
public static final String APP_IMAGES_THUMB_URL = "http://www.egypt-freelancers.me/uploads/thumbnail/";
public static final String LANGUAGE_EN = "en";
public static final String LANGUAGE_AR = "fr";
public static final String DEFAULT_LANGUAGE = LANGUAGE_EN;
how to replace APP_API_URL with
custom language string.xml value
For English
http://www.egypt-freelancers.me/en/index.php
For French
http://www.egypt-freelancers.me/fr/index.php
Thanks
As per my understandings on the question you gave,
To get those variable values you can use this.
Config.STRING_VARIABLE_NAME; // this will return you the value from that class and object creation for that class is not needed as the variable is static.
Example :
String myvalue = Config.APP_API_URL;
I have lots of classes representing user screens in the application that I am testing (page objects). Each of the page objects contains various number of elements with wach of the having an ID. I need to declare those IDs. It looks something like this:
public class MessagesScreen extends BasePage {
private static final String backArrowButtonID = PACKAGE_NAME_ID + "backArrow";
private static final String noMessagesImageID = PACKAGE_NAME_ID + "empty_messages_icon";
private static final String noMessagesTextViewI = PACKAGE_NAME_ID + "label_no_documents";
private static final String errorTextViewID = PACKAGE_NAME_ID + "text_error_response";
private static final String progressBarID = PACKAGE_NAME_ID + "message_list_progress_bar";
private static final String messagesRecyclerViewID = PACKAGE_NAME_ID + "messageList";
private static final String swipeRefreshLayoutID = PACKAGE_NAME_ID + "swipeRefreshLayout";
private static final String instantMessageLayoutID = PACKAGE_NAME_ID + "item_instant_message_layout";
}
Each of the IDs needs to have the an environmental variable added as above.
My question is: is there any nifty way of not having to repeat this PACKAGE_NAME_ID all the time? Is there a way of automatic assigning the constant string to every new class field?
Using an enum here will improve your code in many ways. In addition to solving your current problem, you'd be using the right tool for constants.
enum IdKey {
BACK_ARROW_BUTTON_ID("backArrow"),
NO_MESSAGES_IMAGE_ID("empty_messages_icon"),
NO_MESSAGES_TEXT_VIEW_ID("label_no_documents"),
ERROR_TEXT_VIEW_ID("text_error_response"),
PROGRESS_BAR_ID("message_list_progress_bar"),
MESSAGES_RECYCLER_VIEW_ID("messageList"),
SWIPE_REFRESH_LAYOUT_ID("swipeRefreshLayout"),
INSTANT_MESSAGE_LAYOUT_ID("item_instant_message_layout");
private final String suffix;
private IdKey(String suffix) {
this.suffix = suffix;
}
public String getSuffix() {
return BasePage.PACKAGE_NAME_ID + this.suffix;
}
}
And all you'd have to do wherever you were using your fields is just call:
IdKey.BACK_ARROW_BUTTON_ID.getSuffix();
And the code is both more reliable and cleaner. You can even nest the enum as a private member of MessagesScreen.
I might consider an enum in this case, you can still reference a specific value in the code and override the toString to return your message in the format you want
I have lots of classes representing user screens in the application that I am testing (page objects). Each of the page objects contains various number of elements with wach of the having an ID. I need to declare those IDs. It looks something like this:
public enum MessagesScreen {
BACK_ARROW("backArrow"),
NO_MESSAGES_IMAGE("empty_messages");
private String value;
private Messages(String value) {
this.value = value;
}
#Override public String toString() {
return PACKAGE_NAME_ID + this.value;
}
}
As you cannot enrich the state of final variables after their valuing, I would do things in the other way : providing a getter that adds the desired prefix.
public class MessagesScreen extends BasePage {
private static final String backArrowButtonID = "backArrow";
private static final String noMessagesImageID = "empty_messages_icon";
///...
public String getIdWithPrefix(String constantValue){
return PACKAGE_NAME_ID + constantValue;
}
}
Note that with an enum it would be more robust as Strings accept a very large range of possible values whereas enums don't.
It will require you to change many classes but it is worthful.
The ernest_k answer shows that very well.
I have few constant values which I refer across my application. I am creating a class something like below snippet.
public class Styles {
public static final String tableStyle = "TableGrid";
public static final String fontFamily = "Calibri";
public static final String headerStyle = "Heading2";
public static final String footerStyle = "Heading3";
public static final String tableHeaderStyle = "Heading1";
public static final String tableDataFontFamily = "Cambria";
public static final int tableHeaderFontSize = 16;
public static final int tableDataFontSize = 12;
}
I am assigning the values in it and I am referring them like Styles.headerStyle . My doubt is, is this the good way or is there any better approach to achieve this? something like Enum ?
Thanks in advance.
It depends on the nature of your application, in most cases it is not a good practice to have a collection of constants in that way, but it is difficult to tell without knowing the context of your application. BTW, are sure that you'll never (or almost never) change things like "fontFamily"?
Of course an enum would be a little less verbose and more functional:
public enum Styles {
TABLE_STYLE("TableGrid"),
FONT_FAMILY("Calibri"),
HEADER_STYLE("Heading2"),
FOOTER_STYLE("Heading3"),
TABLE_HEADER_STYLE("Heading1"),
TABLE_DATA_FONT_FAMILY("Cambria"),
TABLE_HEADER_FONT_SIZE("16"),
TABLE_DATA_FONT_SIZE("12");
private String value;
private Styles(String value) {
this.value = value;
}
public String getStringValue() {
return value;
}
public int getIntValue() {
return Integer.valueOf(value);
}
}
1) You can use an external file as a Property File.
2) You can use an enum as #morgano answer
3) I would change your class declaration to
public final class Styles { // final class can't have childs
private Styles(){} // you cannot instanciate
public static final String tableStyle = "TableGrid";
.
.
.
}
I would know what is the best practice for storing global constants which can change with the environnement (debug, preprod, prod, release, etc) at compile time.
In iOS, I used to keep all global constants in a header file and change it with pre-processor macro see this answer:
Where to store global constants in an iOS application?
What solution should I use for Android ?
Create a class constants in your base package folder. (or create an interface instead of a class so there is no need to reference the class everytime, however this is bad practice due to code readability, but it will work)
Fill it with public static final values.
Moreover, both the class as well as the interface can also be declared as abstract.
If values for your constants depend on environment (density, locale etc.) then you should use resources for storing them (integer, string, dimen etc.).
In another case you can put your global constants in one file (best practices - use prefixes for every set of constants) or put local constants in related classes (for instance, Intent holds flags. extras, categories and so on).
Use public static final values. and keep them in separate java file as follows:
static String QC = "http:/************";
static String DEV = "http:/************";
static String CLOUD = "http:/************";
static String SERVICEURL = CLOUD ; //Use this SERVICEURL in your code at run time
Another solution might be to use the resource file (if you are content with storing only string values).
This could be used to store constants such as the account that this application manages:
Ex. WelcomeActivity.java
AccountManager am = AccountManager.get(WelcomeActivity.this);
Account account = am.getAccountsByType(getResources().getString(R.string.ACCOUNT_TYPE))[0];
Ex. res/values/strings.xml
<resources>
<string name="ACCOUNT_NAME">com.acme.MyAccountSignature</string>
</resources>
This would also allow you to modify this without the need to recompile (similarly to how you would normally decouple translations, which the strings.xml file is best used for).
Pretty simple solutions is here
public class Constants {
/**
* Object key prams when pass the json object from server.
*/
public static final String KEY_EMAIL = "email";
public static final String KEY_PASSWORD = "password";
public static final String KEY_DEVICE_TOKEN = "device_token";
public static final String KEY_DEVICE_TYPE = "device_type";
public static final String KEY_NAME = "name";
public static final String KEY_COUNTRY_CODE = "country_code";
public static final String KEY_PHONE_CODE = "phone-code";
public static final String KEY_GENDER = "gender";
public static final String KEY_DATE_OF_BIRTH = "date_of_birth";
public static final String KEY_USER_ID = "user_id";
public static final String KEY_LIMIT = "limit";
public static final String KEY_DRIVER_ID = "driver_id";
public static final String KEY_LONGTITUDE = "logitude";
public static final String KEY_LATTITUDE = "lattitude";
public static final String KEY_RATING = "rating";
public static final String KEY_DETAILS = "details";
public static final String KEY_ACCESS_TOKEN= "access_token";
/**
* Fragments name
*/
public static final String FRAG_ETA = "ETA";
public static final String FRAG_ACCOUNT_FRAGMENT = "ACCOUNT_FRAGMENT";
public static final String FRAG_SETTING_FRAGMENT = "SETTING_FRAGMENT";
public static final String FRAG_MAP_FRAGMENT = "MAP_FRAGMENT";
public static final String FRAG_FEEDBACK = "FEEDBACK";
public static final String FRAG_RATE_FRAGMENT = "RATE_FRAGMENT";
public static final String USA_CODE = "+1";
public static final String DISTANCE_SEARCH = "DISTANCE_SEARCH";
}
happy coding
Property File
We store a property file under <project>/<package>/src/main/assets/config.properties
Loading properties
private static final String PROPS_NAME = "config.properties";
private static Properties configuration;
...
public static void init(Context ctx) {
configuration = new Properties();
InputStream rawResource = resources.getAssets().open(PROPS_NAME);
configuration.load(rawResource);
I have the folowing interface;
public static interface Attributes
{
public final static String InterestDeterminationDate = "InterestDeterminationDate";
public final static String CreditType = "CreditType";
public final static String NumberInternal = "NumberInternal";
public final static String InterestRate = "InterestRate";
public final static String RemainingDebtAmount = "RemainingDebtAmount";
public final static String ConsumerPart = "ConsumerPart";
public final static String TechnicalProductName = "TechnicalProductName";
public final static String TermOfDuration = "TermOfDuration";
public final static String PeriodInterestTaxReduction = "PeriodInterestTaxReduction";
public final static String OriginMark = "OriginMark";
public final static String Currency = "Currency";
public final static String PenaltyRuleId = "PenaltyRuleId";
public final static String InstallmentCalculationMethod = "InstallmentCalculationMethod";
public final static String InterestRenewalDate = "InterestRenewalDate";
public final static String TechnicalProductDescription = "TechnicalProductDescription";
public final static String TechnicalProductDate = "TechnicalProductDate";
public final static String CollectionIntervalPeriod = "CollectionIntervalPeriod";
public final static String Enddate = "Enddate";
}
I need to check is a given string is a part of this Attributes Interface.
How can i check this?
Regards,
bas Hendriks
If you really want todo this, then you should use reflection and go through all the values in Attributes.
A better way to do this would be the use of enums :
public enum Attributes{
InterestDeterminationDate,
CreditType,
NumberInternal,
InterestRate,
RemainingDebtAmount,
ConsumerPart,
TechnicalProductName,
TermOfDuration,
PeriodInterestTaxReduction,
OriginMark,
Currency,
PenaltyRuleId,
InstallmentCalculationMethod,
InterestRenewalDate,
TechnicalProductDescription,
TechnicalProductDate,
CollectionIntervalPeriod,
Enddate;
}
and the Attributes.valueOf(yourVariable); would check this for you.
Beware with enum, the valueOf() method will throw a IllegalArgumentException if yourVariable isn't in Attributes. Plus you yourVariable isn't null or you will have to handle a NullPointerException
Your question doesn't make it clear whether you're trying to find out if the query string is the property name or value. If you're trying to find out if it's a value, the following will work:
public static boolean hasValue(String value) throws IllegalAccessException {
for(Field field : Attributes.class.getDeclaredFields()) {
if(((String)field.get(Attributes.class)).equals(value)) {
return true;
}
}
return false;
}
However, I would advise following Colin's suggestion of using an Enum, it will be easier for you to work with in the future.
You can build a set using reflection and test against that set:
Class<Attributes> attr = Attributes.class;
Field[] fields = attr.getDeclaredFields();
final Set<String> fieldsInAttributes = new HashSet<String>();
for (Field field : fields) {
fieldsInAttributes.add(field.getName());
}
System.out.println(fieldsInAttributes.contains("PenaltyRuleId"));
You can use the reflection API, and the "getFields()" method of the Class class.
Then you check the field name with the "getName()" method of the Field class.
Here is the Oracle official tutorial.
public static String getFieldName(String fieldValue) throws Exception {
for (Field field : Attributes.class.getFields())
if (fieldValue.equals(field.get(null)))
return field.getName();
return null;
}