F.A.Q. |
---|
Questions? |
---|
[LINK] : Im getting an error running Emma inside eclipse, why? |
[LINK] : How can I make an individual property read only? |
[LINK] : How do I make one item selectable from a finite list, example select one Locale from a list of define Locales? |
[LINK] : How do I discover that one of my properties has invalid value on load time, without checking it manually? |
[LINK] : How can include other properties in my PropertyIOCollection with out definining them, like including log4j or hibernate properties? |
[LINK] : How do I a JUnit test validate all my property files for my different environments? |
[LINK] : How do I initialize this from a web context? |
[LINK] : How do a I make a runtime value change when I use the format ${a.name} in avalue, and how do I stop it?. AKA using System.properties and System.env in values. |
[LINK] : How to get commons-logging and log4j to work in my web project? |
[LINK] : Can a Property have the value NULL or be undefined and still be valid? |
[LINK] : Can Properties be dependent on other Properties? |
[LINK] : Where do I setup global framework parameters? |
[LINK] : How to use it with a JBoss setup? |
[LINK] : How to perform an action automatically when a Property is changed, or how to alter a Property when another Property is changed? |
[LINK] : Sometimes I would like to leave a property empty, like an email address, to signify that no emails should be sent, how do I do that? |
[LINK] : I dont want my PropertyCollection to be registred in PropertyCollectionRegistry, what can I do to avoid this? |
[LINK] : When will a default value be used? |
[LINK] : Can I have I18N for my property description? |
[LINK] : Do the the framework supports I18N for its internal messages? |
[LINK] : How do I make a SFTPUrlValidator? |
[LINK] : Im getting an error "Software\JavaSoft\Prefs at root 0x80000002. Windows RegCreateKeyEx(...)", how do I fix this. |
[LINK] : How do I set flush cache time for a specific PropertyIO manually? |
Answers? |
Im getting an error running Emma inside eclipse, why? |
If running codecoverage with emma inside Eclipse. Im getting a "A fatal error has been detected by the Java Runtime Environment" To fix this
|
How can I make an individual property read only? |
You can on the constructor time of the property set the read only parameter, but often it is easier to set it on collection construction time. Look at the example : public class FileDemoProperties extends PropertyStaticCollection implements DemoProperties { private FileDemoProperties(boolean readonly, boolean cached) { super(new FilePropertyIO(new File("c:/app/resources/properties/app.properties",readonly,cached)); } private FileDemoProperties instance = null; public static FileDemoProperties getInstance() { if (instance==null) { instance = new FileDemoProperties(false, true); } } }Set the readonly here: public class FileDemoProperties extends PropertyStaticCollection implements DemoProperties { private FileDemoProperties(boolean readonly, boolean cached) { super(new FilePropertyIO(new File("c:/app/resources/properties/app.properties",readonly,cached)); } @Override public void preValidation() { //Method that will be called before collection is initialized DemoProperties.MY_PROPERTY_H.setReadonly(true); DemoProperties.MY_PROPERTY_A.setReadonly(true); DemoProperties.MY_PROPERTY_L.setReadonly(true); } private FileDemoProperties instance = null; public static FileDemoProperties getInstance() { if (instance==null) { instance = new FileDemoProperties(false, true); } } } |
How do I make one item selectable from a finite list, example select one Locale from a list of define Locales? |
Let us say you got a list of Locales [en,de,dk,fr]).
I would make a Enum public Enum ValidLocale { EN(Locale.ENGLISH), DE(Locale.GERMAN), DK(new Locale("DK"")), FR(Locale.FRANCE) private Locale locale; ValidLocale(Locale locale) { this.locale=locale; } public Locale getLocale() { return locale; } }An make an EnumPropertyType Property<ValidLocale> A_PROPERTY = new Property<ValidLocale>("a.property.name", new EnumPropertyType<ValidLocale>(ValidLocale.class),"Description for valid locales."); |
How do I discover that one of my properties has invalid value on load time, without checking it manually? |
Where you construct your PropertyCollection you add a PropertyValidationHandler to the constructor.See detailed description of validation handlers here - PropertyValidationHandlers. public class FileDemoProperties extends PropertyStaticCollection implements DemoProperties { private FileDemoProperties(boolean readonly, boolean cached) { super(new FilePropertyIO(new File("c:/app/resources/properties/app.properties",readonly,cached)); } @Override public void preValidation() { //Method that will be called before collection is initialized setPropertyValidationHandler(new MyEmailPropertyValidationHandler("host.mycomp.com")); } private FileDemoProperties instance = null; public static FileDemoProperties getInstance() { if (instance==null) { instance = new FileDemoProperties(false, true); } } } |
How can include other properties in my PropertyIOCollection with out definining them, like including log4j or hibernate properties? |
Construct a CompositePropertyIO, containing both input from your main property resource, and other resource like "log4j.properties and "hibernate.properties". |
How do I a JUnit test validate all my property files for my different environments? |
Let us assume that you have a directory structure like this in your project:
And you have an Interface with all your Property definitions "MyAppPropertiesDefinition". Consider to set:
Use the method FilePropertyIOFactory.findPropertyFiles(new File("/config/environments"),"myapp.properties"), which return all files which name is "myapp.properties". Than your test case will look something like this: public class EnvironmentPropertyDataTest { @Test public void testAllEnvironmentProperties() { //PropertyFrameworkGlobals.setAutoEncryptPasswords(false); //PropertyFrameworkGlobals.setValidateIPathPropertyTypes(false); File[] files = FilePropertyIOFactory.findPropertyFiles(new File("/config/environments"),"myapp.properties"); for (File file : files) { MockTestCollection collection = new MockTestCollection(file); try { collection.validate(); } catch (PropertyException e) { e.printStackTrace(); fail("Property file ["+file.getAbsolutePath()+"] failed with message:"+e.getMessage()); } } } @After public void after() { //PropertyFrameworkGlobals.resetGlobalSettings(); } class MockTestCollection extends PropertyStaticCollection implements MyAppPropertiesDefinition { public MockTestCollection(File file) { super(new FilePropertyIO(file)); } } } |
How do I initialize this from a web context? |
You can do it in the following way: Start by creating a class which implements "ServletContextListener". public class WebContext implements ServletContextListener { @Override public void contextDestroyed(ServletContextEvent arg0) { } @Override public void contextInitialized(ServletContextEvent context) { WebDemoProperties.getInstance(context.getServletContext()); } }Here by you ensure that your properties are loaded when your WAR file is deployed. The class "WebDemoProperties" includes: public class WebDemoProperties extends PropertyStaticCollection { //Your Property definitions.... private static WebDemoProperties instance = null; public WebDemoProperties(ServletContext context) { super(new ServletContextPropertyIO(context,"config/demo.app.properties")); } public static WebDemoProperties getInstance(ServletContext context) { if (instance==null) { instance = new WebDemoProperties(context); } return instance; } public static WebDemoProperties getInstance() { return instance; } }Than your have to add the "WebContext" to your "web.xml" like. <listener> <listener-class>dk.heick.properties.webdemo.WebContext</listener-class> </listener>And you can now access both the properties and the collection. WebDemoProperties.MY_PROPERTY.getTypedValue(); // WebDemoProperties.getInstance().reload(); String backupContense = WebDemoProperties.getInstance().getIO().backup();But is you use annotions you can use. @ApplicationScoped public class WebDemoProperties extends PropertyExposedFinalFieldCollection { //Your Property definitions.... public WebDemoProperties() { super(new ResourceFilePropertyIO("dk/heick/properties/io/demo/resourcefile.properties")); } } |
How do a I make a runtime value change when I use the format ${a.name} in avalue, and how do I stop it?. AKA using System.properties and System.env in values. |
When reading a value, for any PropertyIO, as a String before its validated and converted to a strong type; its passed through StringUtils.replaceInlinedProperties(String) .This replaces any part of the string where the pattern ${name} occurs, with the value of the either System.getProperty(name) or System.getEnv(name).If the value is null it is not replaced.To turn of this behaviour, you can use the PropertyFrameworkGlobals class to override this.
|
How to get commons-logging and log4j to work in my web project? |
First of your need to have to two jars files.
Containing: org.apache.commons.logging.Log=org.apache.commons.logging.impl.Log4JLogger log4j.configuration=log4j.propertiesAdd the file "log4j.properties" in the root of your source directory in the war file. Where your java code is. In the web demo it contains: # # our log4j properties / configuration file # #log4j.configuration=log4j.properties # STDOUT appender log4j.rootLogger=DEBUG,console log4j.logger.logger.name=DEBUG log4j.appender.console=org.apache.log4j.ConsoleAppender log4j.appender.console.layout=org.apache.log4j.PatternLayout log4j.appender.console.layout.conversionPattern=%5p [%t] (%F:%L) - %m%n #log4j.appender.A1.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%nThere are other ways to set this up, consult the documentation for log4j and commons-logging at Apache web site. |
Can a Property have the value NULL or be undefined and still be valid? |
A Property can be constructed with a "nullAllowed" paramenter. The constructor parameters for a Property is:
|
Can Properties be dependent on other Properties? |
A value for a Property can not use a value for another Property directly, you have to implement that in your own code. But Properties can be validated for dependencies, so if Property A is not null an valid, than Property B, C and D also have to be not null and valid. In the PropertyCollection there is a method "postValidation", which you can choose to override. See PropertyCollection documentation on how to do that. |
Where do I setup global framework parameters? |
There is a set of Global Framework Settings. In the PropertyCollection there is a method "preValidation", which you can choose to override. This is where you typically sets your PropertyFrameworkGlobals. See PropertyCollection documentation on how to do that. |
How to use it with a JBoss setup? |
My experience with JBoss is limited, but as far as I know i loads the parameters in "System.getProperties() ".So use the " JBossSystemPropertiesPropertyIO " generate Property definitions with the PropertiesJavaDefinitionPrinter .Than when making your PropertyCollection class do as following. public class MyProperties extends PropertyStaticCollection implements MyJBossPropertiesDef { private static MyProperties instance=null; public MyProperties() { super(new MemoryPropertyIO(System.getProperties(),true)); } public MyProperties getInstance() { if (instance==null) { instance = new MyProperties(); } return instance; } } |
How to perform an action automatically when a Property is changed, or how to alter a Property when another Property is changed? |
All this is possible using the PropertyChangeListeners, which is new in version 1.6. I will just give a quick example on how it can be used. Example: Let us say we have two properties, one for a password and one for the date when the password was last changed. Property<PasswordTypeVO> MY_APP_PASSWORD_PROPERTY = new Property<PasswordTypeVO>("my.app.password", new PasswordPropertyType(new SHA512Encryption())); Property<Date> MY_APP_PASSWORD_LAST_CHANGED = new Property<Date>("my.app.password.last.changed", new DateTimePropertyType(new Date(0)),false,true);Notice that the Property "MY_APP_PASSWORD_LAST_CHANGED" is set to read only, so from the outside no one can set this property. We WANT to update "MY_APP_PASSWORD_LAST_CHANGED" with a new current date, when ever the Property "MY_APP_PASSWORD_PROPERTY" is altered. What you do is in your PropertyCollection setup do the following in your constructor. public class FileDemoProperties extends PropertyStaticCollection implements DemoProperties { private FileDemoProperties(boolean readonly, boolean cached) { super(new FilePropertyIO(new File("c:/app/resources/properties/app.properties",readonly,cached)); } @Overrride public void preValidation() { UpdateLastChangedPropertyChangeListener updateListener = new UpdateLastChangedPropertyChangeListener(DemoProperties.MY_APP_PASSWORD_LAST_CHANGED); DemoProperties.MY_APP_PASSWORD_PROPERTY.addPropertyChangeListener(updateListener); } .... } |
Sometimes I would like to leave a property empty, like an email address, to signify that no emails should be sent, how do I do that? |
You will make two properties.
public final static Property<Color> MYAPP_SEND_EMAIL = new Property<Boolean>("p.myapp.send.email" , new BooleanPropertyType()); public final static Property<String> P_MYAPP_EMAIL = new Property<String>("p.myapp.email",new EmailPropertyType("mydomain.com"),true); public final static Property<List<String>> P_MYAPP_EMAIL_LIST = new Property<List<String>>("p.myapp.email.list", new ListPropertyType<String>(new EmailPropertyType("mydomain.com")),true);In your code you can do the following: if (DemoProperties.MYAPP_SEND_EMAIL.getTypedValue()==true) { //Send email to either String email = DemoProperties.P_MYAPP_EMAIL.getTypedValue(); List<String> emails = DemoProperties.P_MYAPP_EMAIL_LIST.getTypedValue(); // if (email!=null) { //send email } if ((emails!=null) && (emails.size()>0)) { //send emails //NOTE : actual ListPropertyType will always return an empty list } } |
I dont want my PropertyCollection to be registred in PropertyCollectionRegistry, what can I do to avoid this? |
You can turn a specific register for a PropertyCollection in "preValidation" method.
public class FileDemoProperties extends PropertyStaticCollection implements DemoProperties { private FileDemoProperties(boolean readonly, boolean cached) { super(new FilePropertyIO(new File("c:/app/resources/properties/app.properties",readonly,cached)); } @Overrride public void preValidation() { PropertyCollectionRegistry.removeRegister(this); } }Or you can turn off that any PropertyCollection should be registered using the "PropertyFrameworkGlobals". This will clear the registry. public class FileDemoProperties extends PropertyStaticCollection implements DemoProperties { private FileDemoProperties(boolean readonly, boolean cached) { super(new FilePropertyIO(new File("c:/app/resources/properties/app.properties",readonly,cached)); } @Overrride public void preValidation() { PropertyFrameworkGlobals.setAutoRegisterPropertyCollections(false); } } |
When will a default value be used? |
In the scenario when the following conditions is met.
|
Can I have I18N for my property description? |
YES - but you need to implement and set the "PropertyFrameworkGlobals.setPropertyDescriptionLocalizer(..)". Further more, if the property description is null , which it is per default it will use a generated key for I18N lookup. If the property desription is not null , it will the property description as a I18N key if it starts with $, otherwise it is assumed that
the property description is set as is.
|
Do the the framework supports I18N for its internal messages? |
NO - currently the framework only returns messages in english. Maybe in future releases this will change. But message for your own defined Property supports the possibility for I18N. |
How do I make a SFTPUrlValidator? |
Using the libraries "com.jcraft.jsch" and "com.jcraft.jzlib" you can make one like this.
public class SFTPUrlValidator implements URLValidator { private Property<Integer> propertyPort; private Property<String> propertyUsername; private Property<PasswordTypeVO> propertyPassword; private Property<String> propertyRemoteDirectory; private Property<Integer> timeoutProperty; // public SFTPUrlValidator(Property<Integer> propertyPort,Property<String> propertyUsername,Property<PasswordTypeVO> propertyPassword,Property<String> propertyRemoteDirectory,Property<Integer> timeoutProperty) { super(); this.propertyPort=propertyPort; this.propertyUsername=propertyUsername; this.propertyPassword=propertyPassword; this.propertyRemoteDirectory=propertyRemoteDirectory; this.timeoutProperty=timeoutProperty; } public Property<PasswordTypeVO> getPropertyPassword() { return propertyPassword; } public Property<Integer> getPropertyPort() { return propertyPort; } public Property<String> getPropertyUsername() { return propertyUsername; } public Property<String> getPropertyRemoteDirectory() { return propertyRemoteDirectory; } public Property<Integer> getTimeoutProperty() { return timeoutProperty; } public String getPassword() throws PropertyException { return propertyPassword.getTypedValue().getDecryptedValue(); } public int getPort() { return propertyPort.getTypedValue(); } public String getUsername() { return propertyUsername.getTypedValue(); } public String getRemoteDirectory() { return propertyRemoteDirectory.getTypedValue(); } @Override public int getTimeoutMilliseconds() { return getTimeoutProperty().getTypedValue(); } @Override public String testUrl(String name, URL url, Proxy proxy) throws PropertyException { JSch jsch = new JSch(); Session session = null; ChannelSftp sftpChannel = null; try { session = jsch.getSession(getUsername(), url.toString(), getPort()); session.setPassword(getPassword()); session.setConfig("StrictHostKeyChecking", "no"); session.setTimeout(getTimeoutMilliseconds()); // session.connect(); // sftpChannel = (ChannelSftp) session.openChannel("sftp"); sftpChannel.connect(); if (getPropertyRemoteDirectory()!=null) { @SuppressWarnings("unchecked") Vector<LsEntry> vector = sftpChannel.ls(getRemoteDirectory()); return "Successfull connect to [" + url.toString() + "]. [" + vector.size() + "] files in directory."; } else { return "Successfull connect to [" + url.toString() + "]."; } // } catch (Throwable e) { StringBuilder s = new StringBuilder(); s.append("Error connection to ["); s.append(url.toString()); s.append("] with user ["); s.append(getUsername()); s.append("] on port ["); s.append(getPort()); s.append("] with message ["); s.append(e.getMessage()); s.append("]"); throw new PropertyException(s.toString(), e); } finally { if (sftpChannel != null) { sftpChannel.disconnect(); } if (session != null) { session.disconnect(); } } } } |
Im getting an error "Software\JavaSoft\Prefs at root 0x80000002. Windows RegCreateKeyEx(...)", how do I fix this.? |
This problem is only seen on Windows, when testing URLs or domain validating emails. The reason is that we are using Preferences to retrieve system setup for timeout and retries. This will not be problem from version 1.9 and forward. The error looks like this : okt 09, 2014 5:10:29 PM java.util.prefs.WindowsPreferences <init> WARNING: Could not open/create prefs root node Software\JavaSoft\Prefs at root 0x80000002. Windows RegCreateKeyEx(...) returned error code 5. okt 09, 2014 5:10:29 PM java.util.prefs.WindowsPreferences WindowsRegOpenKey1 WARNING: Trying to recreate Windows registry node Software\JavaSoft\Prefs at root 0x80000002. okt 09, 2014 5:10:29 PM java.util.prefs.WindowsPreferences openKey WARNING: Could not open windows registry node Software\JavaSoft\Prefs at root 0x80000002. Windows RegOpenKey(...) returned error code 2. okt 09, 2014 5:10:29 PM java.util.prefs.WindowsPreferences WindowsRegOpenKey1To fix this, do one of the following things:
|
How do I set flush cache time for a specific PropertyIO manually? |
It is now possible to set a cache time for PropertyIO's, the amount of milliseconds before the typed value cache is invalidated and the properties will be automatically reloaded at next access. The default value is set from PropertyFrameworkGlobals to -1, which mean that per default no cache timeout is enabled. The value can be set globally in or for the individual PropertyIO. This is usual done in the method PropertyCollection.preValidation(). If you want to override the default cache time for a PropertyIO, you will typically do either right the constructor of the IO (when you construct the collection) or in the collection @Override public void preValidation() { final long ONE_HOUR = 1000*60*60; getIo().setCacheTime(ONE_HOUR); }or use the new TimeSpan @Override public void preValidation() { getIo().setCacheTime(TimeSpan.HOURS_01.getSpan()); } |