In my mobile application I need to hold a collection of File objects (pictures, documents) that can be accessed throughout the whole application and users can make various operations over the collection:
view all/individual files
upload subsets of the collection to a server
share individual files
...
The collection is initialized only once.
I was wondering if it is a good idea to use a singleton pattern as an object that holds the collection so I do not have to initialize the collection every time user opens a particular screen?
Absolutely, that's the purpose of the singleton pattern.
From Wikipedia, The Singleton Pattern is
useful when exactly one object is
needed to coordinate actions across
the system.
Example:
public class SingletonCollection {
private Collection<File> fileCollection;
private static SingletonCollection instance;
private SingletonCollection() {
fileCollection = new ArrayList<File>();
}
public static SingletonCollection getInstance() {
if (instance == null) {
instance = new SingletonCollection();
}
reutrn instance;
}
public void addFile(File f) {
fileCollection.add(f);
}
public Collection<File> getFiles() {
return fileCollection;
}
}
For Java >=1.5
public enum FileCollector
{
INSTANCE;
private FileCollector()
{
List _temp = new ArrayList();
File f = new File("properties");
_temp.add(f);
fileContainer = Collections.unmodifiableList(_temp);
}
private final Collection<File> fileContainer;
public Collection<File> getFiles() {
return fileContainer;
}
}
If collection is initialized only once then use singleton. No doubt.
If you are using Java ME try RecordStore. You can access it from anywhere in the application.
Related
I stumbled upon a pseudo-singleton class that is responsible for housing a few collections. It looks something like this:
public class PseudoSingleton {
private List<Object> collection1;
private List<Object> collection2;
private static PseudoSingleton instance = null;
public static synchronized PseudoSingleton getInstance() {
if (instance == null) {
instance = new PseudoSingleton();
}
return instance;
}
public static synchronized void reload() {
instance = new PseudoSingleton();
}
private PseudoSingleton() {
load();
}
private void load() {
//parse some files from disk and fill collections
}
}
The reason it is coded like this is that in a few places in code a comparison of collection1 before and after reload needs to be done.
However this way seems like a major code smell to me.
I tried to refactor the code slightly by making the reload() method not static:
public synchronized void reload() {
//clear collections
//load collections
}
In order to be able to compare collection before reload I added a method that needs to be called before reloading the collection:
public List<Object> getCollection1Copy() {
return new LinkedList<>(collection1);
}
However, in review I got a comment that the previous way was better and I should leave it as is. I am not convinced. Should I insist to go my way or leave it? Or is there a better way to code it?
I have created new custom built-ins inside my Java program. They work fine and if I execute them into a ".txt" file making a rule I get the result I expect to .
The problem is that I can use this built-ins only where I have implemented them (in the same file).
For example, I have a java class file which is called "RulesOntology_DiffYear.java" where I have created a built-in called "myDiffDate" which does the difference between two dates and it return the number of years of difference.
If I try to write the rule (using the built-in "myDiffDate") and I try to execute it inside the file "RulesOntology_DiffYear.java", the rule recognises the new built-in and it runs it without problems.
If I try to write the same rule in another file ".java", the built-in I have created in "RulesOntology_DiffYear.java", it is not recognised, of course.
How can I use my custom built-ins in another files ? Like the default built-ins ? Need I to create a library or there is something else to do ?
I have found this Create a library for new built-ins Jena but I do not really know how it works (even if I tried it) and I do not know if it is the easiest solution for my purpose.
In my file "DiffDateLib.java" I have defined my custom built-in "myDiffDateYear".
I have created another file named "MyReasonerFactory.java" with the following code :
public class MyReasonerFactory implements ReasonerFactory {
/** The single global static registry */
public static BuiltinRegistry theRegistry;
private static final String RULE_LOC = "????";
static {
BuiltinRegistry.theRegistry.register(new DiffDateLib());
}
#Override
public Reasoner create(Resource r) {
final GenericRuleReasoner reasoner = new GenericRuleReasoner(this, r);
reasoner.setRules(FBRuleReasoner.loadRules(RULE_LOC));
return reasoner;
}
#Override
public Model getCapabilities() {
return GenericRuleReasonerFactory.theInstance().getCapabilities();
}
#Override
public String getURI() {
return RULE_LOC;
}
}
What can I write into the variable "RULE_LOC" ? Which filepath ?
I have made also another class called "tryNoBuiltin.java" which contains the main of the program :
public class tryNoBuiltin {
public static void main(String[] args) throws OWLOntologyStorageException,
OWLOntologyCreationException, IOException {
String percorsoFile ="./prova_rules_M_rdf.owl";
String ruleFile= "./prova_rules_M_rdf_7_diffDate.txt";
Model rawModel = ModelFactory.createDefaultModel();
MyReasonerFactory MyReas = new MyReasonerFactory();
//create a resource (empty model)
Resource configuration = rawModel.createResource();
// set engine mode
configuration.addProperty(ReasonerVocabulary.PROPruleMode, "hybrid");
// set the rules file
configuration.addProperty(ReasonerVocabulary.PROPruleSet, ruleFile);
List<Rule> rules = Rule.rulesFromURL(ruleFile);
GenericRuleReasoner reasonerRULE = (GenericRuleReasoner) GenericRuleReasonerFactory.theInstance().create(configuration);
reasonerRULE.setRules(rules);
Model modelRULE= FileManager.get().loadModel(percorsoFile);
//create the inference model
InfModel infModelRULE = ModelFactory.createInfModel(reasonerRULE, modelRULE);
//force starting the rule execution
infModelRULE.prepare();
//write down the result in RDFXML form
infModelRULE.write(System.out);
}
}
In the main I can see the output so, the new built-in (which I have used into the rule file "prova_rules_M_rdf_7_diffDate.txt") is recognised .
But I think I did not use correctly the class "MyReasonerFactory". Can you provide me an example ? Where can I use its methods ?
Thank you all!
This should probably work for you. The idea is that the MyReasonerFactory is acting as a way to retrieve a reasoner for your domain. Not only does it register the builtins, but it also gets/sets the rules.
public class MyReasonerFactory implements ReasonerFactory {
private static final String RULE_LOC = "./prova_rules_M_rdf_7_diffDate.txt";
static {
BuiltinRegistry.theRegistry.register(new DiffDateLib());
}
#Override
public Reasoner create(Resource r) {
final GenericRuleReasoner reasoner = new GenericRuleReasoner(this, r);
reasoner.setRules(Rule.rulesFromURL(RULE_LOC));
return reasoner;
}
#Override
public Model getCapabilities() {
return GenericRuleReasonerFactory.theInstance().getCapabilities();
}
#Override
public String getURI() {
// TODO NOTE this is just a suggestion
return "urn:ex:provaRuleReasoner";
}
}
You did a few redundant things while loading the rules. ie: you set it in the config as well as manually retrieved them and parsed them. I removed the extra stuff.
public class tryNoBuiltin {
public static void main(String[] args) throws OWLOntologyStorageException,
OWLOntologyCreationException, IOException {
//Create a configuration model
Resource configuration = ModelFactory.createDefaultModel().createResource();
configuration.addProperty(ReasonerVocabulary.PROPruleMode, "hybrid");
MyReasonerFactory MyReas = new MyReasonerFactory();
GenericRuleReasoner reasonerRULE = (GenericRuleReasoner)MyReas.create(configuration);
Model modelRULE= FileManager.get().loadModel("./prova_rules_M_rdf.owl");
InfModel infModelRULE = ModelFactory.createInfModel(reasonerRULE, modelRULE);
infModelRULE.prepare();
//write down the result in RDFXML form
infModelRULE.write(System.out);
}
}
I'm developing a little project, a web application where I run some analysis on data based on user text input.
To do so, I need to use a Map where I have words and corresponding scores for that word.
This is what I tried:
public class EnDict {
private static Map<String, Integer> map = new HashMap<String, Integer>() {
{
put("abandon", -2);
put("ability", 2);
put("abuse", -3);
//and so on, thousands of pairs
}
}
}
It works, but this way I need to have the key/value pairs hard-coded in my class. So, if I want to add more pairs, I have to write code, instead of just adding pairs do a text file. Doesn't seem good.
So I want to obtain this pairs from a text file. Also, I need this Map to be created when the application starts, so when any user makes a request the Map is already loaded, and can be used by the analysis logic. I mean, the Map must be in memory before the first request happens, and last in memory after that, to be used in subsequent requests. And it need to be visible from anywhere in my application (maybe this part wasn't very clear, but I don't know how to explain it better).
I've tried some research, but haven't found answers to this specific part of keeping the Map in memory since the application start. It's something similar to ASP.NET Application_Start method, in the Global class.
I'm very new to programming and specially to Java, so maybe I'm completely misled about how would be the best way of achieving this task. If that is the case, some tip would be appreciated.
I'm using Servlets, JSP and Tomcat.
Edit:
Actually, it would not be only one Map. There will be several Maps, and those Maps can have some keys that are identical.
Define this map as static - it will be in memory until class loader who loaded this class is not garbage collected.
I say above by refering : http://docs.oracle.com/javase/specs/jls/se5.0/html/execution.html#12.7
Static member are linked to class and above specification says that classes will not be unloaded until class loader is in place.
Whereas objects do get garbage collected. Hence suggested to make map static(make it public too in case needs access from outside).
And for loading file into map
store it in file as
key1=value1
key2=value2
....
....
now use BufferedReader as below
BufferedReader reader = new BufferedReader(new FileReader(new File("pathname")));
String line = null;
Map<String, Integer> map = new HashMap<String, Integer>();// it should be static - whereever you define
while ((line = reader.readLine()) != null) {
if (line.contains("=")) {
String[] strings = line.split("=");
map.put(strings[0], Integer.parseInt(strings[1]));
}
}
Class loader is something which loads classes in memory while starting the application. Tomcat also has its classloader which loads required classes in memory(Classes and not objects). Now we know that static variables are associated with class and not object. So static members are loaded in memory along with class. IN many other cases you would be creating object of the class and use it. If you have millions of objects loaded in memory- You will be soon short of it. So java have something called garbage collector. This garbage collector removes unwanted/old objects from memory to recycle it. Garbage collector removes objects not classes and hence static member still remains in memory.
You can staticaly initialize static variable in static block like this:
private static Map<String, Integer> map = new HashMap<String,Integer>();
static {
fillMap(map, "filename.txt");
}
private static void fillMap(Map<String, Integer> map, String fileName) {
// here comes file reading code with loop
}
How to read file see something like this Reading a plain text file in Java.
As far as its all static map will be initialized on application startup.
Try this for loading the text file into your application: Read from a Text File into a hash map or list
When I was just starting to program, I know I was tempted to use a lot of global variables. As it turns out, this is usually not the best strategy (see http://c2.com/cgi/wiki?GlobalVariablesAreBad).
Perhaps you can load your dictionary first thing in your main method, and pass it through to other methods that need later on.
You can define a Listener on web.xml file:
<listener>
<listener-class>my.Listener</listener-class>
</listener>
and you implement the class:
package my;
public class Listener implements javax.servlet.ServletContextListener {
public void contextInitialized(ServletContext context) {
File file = new File();
fileEntries = ... // load your entries
for (Object[] line : fileEntries) {
YourClass.get().addElement((String) line[0], Integer.parseInt(line[1].toString());
}
}
}
if you want to access your Map application-wide, just create a singleton or use Spring to have the class managed, if a singleton do something like:
public class YourClass {
private static final YourClass INSTANCE = new YourClass();
private Map<String, Integer> yourMap;
private YourClass() {
yourMap = new HashMap<>();
}
public static final YourClass get() {
return INSTANCE;
}
public void addElement(String key, Integer value) {
yourMap.put(key, value);
}
public Integer getValueForKey(String key) {
return yourMap.get(key);
}
}
and so you can access the elements from anywhere in the application via:
YourClass.get().getValueForKey("yourKey");
I would suggest you use Properties to store/load key/value pairs and implement Singleton pattern to access these properties. Something like this:
public class EnDict {
private Properties properties;
private static EnDict enDictInstance;
private EnDict {
properties = new Properties();
FileInsputStream fis = null;
try{
fis = new FileInputStream("yourPropertiesFile.properties");
properties.load(fis);
fis.close();
} catch(IOException ex) {
/* log the exception */
} finally {
try {
fis.close();
} catch (IOException ignored) {}
}
}
public static EnDict getEnDictInstance(){
if(enEdictInstance == null) {
enEdictInstance = new EnEdict();
}
return enEdictInstance;
}
public Integer getValue(String key){
String value = properties.getProperty(key);
return Integer.valueOf(value);
}
public void setNewWord(String word, Integer value){
properties.setProperty(word, value.toString());
}
public void saveProperties() {
FileOutputStream fos = null;
try {
fos = new FileOutputStream("yourPropertiesFile.properties");
properties.store(fos, "Some comments");
fos.close();
} catch (IOException ex) {
/* log the exception */
} finally {
try{
fos.close();
} catch(IOException ignored){}
}
}
}
As #Mauren pointed out just keep in mind Properties doesn't allow null values.
Also instead of .properties files you can use XML files. See Loading Properties from XML
For loading the constants from different resources to different java classes you can use apache commons configuration library http://commons.apache.org/proper/commons-configuration/
For application start up you can use
<servlet>
<servlet-name>StartUp</servlet-name>
<display-name>StartUp Servlet</display-name>
<servlet-class>foo.bar.YourStartUpServlet</servlet-class>
<load-on-startup>0</load-on-startup>
</servlet>
I have a class Player, that needs to get a Location class. Each location class extends Location, which has a method get() that returns a static instance.
If the character has a string referring to the name of the location extension class, how can I get the instance?
Character:
public class Player {
public static Location getLocation() {
try {
//return location
} catch (Exception ex) {
Logger.getLogger(Player.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
}
Location:
public class Location{
protected static Location singleton;
public static Location get() {
return null;
}
Location class:
public class Finleydale extends Location{
public static Location get() {
if (Finleydale.singleton == null) {
Finleydale.singleton = new Finleydale();
}
return singleton;
}
}
I have multiple location extensions, and I have the singleton in the location class, so all location extensions have it; and the singleton is static because there is only one version of the location.
Can someone help me with this?
The way you declared the static field in the base class means you have only one reference in the entire program. If you have more than one subclass, and each one assigns to it, then each one is assigning to the same (static) field in the Location base class. I think you want a separate singleton in each subclass.
If you want to look up a particular location by key (say a string value), then I don't think the Singleton pattern is quite what you are looking for. I would create a "location registry" class, something like this:
public class LocationRegistry
{
private static final Map<String, Location> registry;
static
{
final Map<String, Location> _registry = new HashMap<>();
_registry.put("Finleydale", new Finleydale());
// ...
registry = Collections.unmodifiablemap(_registry);
}
public static Location getLocation(final String id)
{
return registry.get(id);
}
}
Some notes:
You could still use the Singleton pattern to populate the registry
The classic Singleton pattern, as demonstrated in your question, is not thread-safe. A correctly thread-safe version without unnecessary locking is very tricky, if not impossible. A static final field resolves that problem nicely.
It isn't necessary to have the registry explicitly reference each Location subclass. You could have each location register itself. The only trick is to have a mechanism that would load the locations so that they can register themselves.
Are subclasses actually suitable for this use? Do different locations have different behaviors or just different data (ie name)? If the latter, then I would just use a single Location class and a single factory, such as the static initializer above, to create each location.
Something about your object model seems wrong. Why not have an interface Locatable with a getLocation() method on it, and implementers of the interface can return their respective locations. A singleton Location just seems conceptually wrong.
interface Locatable {
Location getLocation();
}
class FinleyLand implements Locatable {
#Override
Location getLocation() {
//whatever it takes to get you there...
}
}
I took the get() function's static modifier away and changed the Player class as shown. All you other guys, your input was great.
String locationS; //Class name
public static Location getLocation() {
return ((Location) Class.forName(locationS).newInstance()).get();
}
I want to build a ApplicationSetting for my application. The ApplicationSetting can be stored in a properties file or in a database table. The settings are stored in key-value pairs. E.g.
ftp.host = blade
ftp.username = dummy
ftp.pass = pass
content.row_pagination = 20
content.title = How to train your dragon.
I have designed it as follows:
Application settings reader:
interface IApplicationSettingReader {
Map read();
}
DatabaseApplicationSettingReader implements IApplicationSettingReader {
dao appSettingDao;
Map read() {
List<AppSettingEntity> listEntity = appSettingsDao.findAll();
Map<String, String> map = new HaspMap<String, String>();
foreach (AppSettingEntity entity : listEntity) {
map.put(entity.getConfigName(), entity.getConfigValue());
}
return new AppSettings(map);
}
}
DatabaseApplicationSettingReader implements IApplicationSettingReader {
dao appSettingDao;
Map read() {
//read from some properties file
return new AppSettings(map);
}
}
Application settings class:
AppSettings {
private static AppSettings instance = new AppSettings();
private Map map;
private AppSettings() {
}
public static AppSettings getInstance() {
if (instance == null) {
throw new RuntimeException("Object not configure yet");
}
return instance;
}
public static configure(IApplicationSettingReader reader) {
this.map = reader.read();
}
public String getFtpSetting(String param) {
return map.get("ftp." + param);
}
public String getContentSetting(String param) {
return map.get("content." + param);
}
}
Test class:
AppSettingsTest {
IApplicationSettingReader reader;
#Before
public void setUp() throws Exception {
reader = new DatabaseApplicationSettingReader();
}
#Test
public void getContentSetting_should_get_content_title() {
AppSettings.configure(reader);
Instance settings = AppSettings.getInstance();
String title = settings.getContentSetting("title");
assertNotNull(title);
Sysout(title);
}
}
My questions are:
Can you give your opinion about my code, is there something wrong ?????
I configure my application setting once, while the application start, I configure the application setting with appropriate reader (DbReader or PropertiesReader), I make it singleton because the application just have one instance of ApplicationSettngs. The problem is, when some user edit the database or file directly to database or file, I can't get the changed values. Now, I want to implement something like ApplicationSettingChangeListener. So if the data changes, I will refresh my application settings. Do you have any suggestions how this can be implementedb ????
I haven't throughly inspected your code, but there seems to be a concurrency issue. The map is thread-unsafe (HashMap), so if you mutate it through config() and have other threads access map, you have a problem.
Though you could use a ConcurrentHashMap instead HashMap, a batch operation on ConcurrentHashMap is not atomic. Meaning that, if you use it, you will see a "half-way" modified config. That could not be okay depending on your app.
So, the solution for this is to use this:
private volatile ImmutableMap map;
public config(){
ImmutableMap newMap = createNewMap();
this.map = newMap;
}
This will change your configs atomically (no intermediate state is visible).
As for updating your config on the fly, log4j does it using a background thread that monitors the config file. You could of course monitor a db table instead by polling it periodically.
In that case, your Config class will have preferably a ScheduledExecutor with a task that will monitor files/db and call config() periodically.
The answer to question #2 is to use a thread and check periodically if the file has been changed or to simply reinitialize your settings with the file contents.