I'm developing a framework in java which relies on a number of XML files with large number of parameters.
When reading the parameters from the XML file, I have to have a large if-else statement to decide what the parameters is and then call appropriate methods.
Is this normal? to have a large if-else statement?
I am thinking that there is a simple and neater way of doing this, e.g. Java XML mapping or Java Reflections? is this the answer? if so, can you please provide examples of how this is done so I don't have to rely on a large if-else statement?
Thanks!
You want to first create an interface:
public interface XMLParameterHandler {
public handle_parameter (String XMLData);
}
Next you want to create a map:
private Map<string, XMLParameterHandler> handlers;
...and initialize it with one of the relevant Map implementations:
this.handlers = new HashMap<>();
You need to implement the interface on a number of classes, one for each parameter you intend to handle. This is a good use of inner classes. Insert each of these implemented handerls into the map:
handlers.put ("Param1", new XMLParam1HandlerImpl());
handlers.put ("Param2", new XMLParam2HandlerImpl());
Then you can call the handler from the xml processing loop:
handlers.get (paramValue).handle_parameter(XmlData);
There is JAXB (http://en.wikipedia.org/wiki/Java_Architecture_for_XML_Binding) for mapping java class to xml.
But you can't map methods with it: you only can map attributes to xml file values (deserialize parameters from xml).
i recommend to use Map, that have parameter as key and xml entry as value(not whole xml)
Reflection would be one approach. Perhaps combined with a custom annotation on the target method to indicate which parameter to pass to that method. This is an advanced technique, though.
A more standard technique would be to use a map, where the key is the attribute name, and the value is an instance of an implementation of some interface you define, like AttributeHandler. The implementations then contain the code for each attribute. This involves writing a lot of little classes, but you can do them as anonymous classes to save space and keep the code inline.
a large if-else statement to decide what the parameters is and then call appropriate methods
You could instead use the Strategy design pattern, with one Strategy object per parameter, and use a map from the parameter name to the Strategy object to use. I've found this approach useful for even a moderately complicated application of XML.
It sounds to me as if you want a data-driven rule-based approach to writing your application, rather like you get in XSLT. One way of achieving this is to write it in XSLT instead of Java - XSLT, after all, was specifically designed for processing XML, while Java wasn't. If you can't do that, you could study how XSLT does it using rules and actions, and emulate this design in your Java code.
N functions with M parameters can always be implemented with a single function with M + 1 parameters.
If you need a big if then else statement to decide which method to dispatch to, then you can just add a parameter to your method and call a single method.
You shouldn't need an if-then-else statement to bind the parameter values.
If there is complex logic dependent on the particular parameter values, you might use a table driven approach. You can map various combinations of paramemter values into equivalence classes, then variouos equivalence class combinations into a row in a table with a unique id, then have a switch statement based on that unique id.
Related
In my application I need to use dynamic localization, so I cannot use Constants interface. I did use Constants for a while, but now I need texts to be changed without compiling so I had to find some other way.
So I am using Dictionary now. The thing is, when I now want to use text in UiBinder, I can only use methods without arguments. So I created class "StringIdentifiers" where I have the same methods I previously had in MyConstants, but I have to specify a body here for every method to return the specified String.
So for example I have:
Dictionary locale = Dictionary.getDictionary("myJsObjectWithStrings");
//and then the methods for returning the actual strings from the JS object
String loading(){
return locale.get("loading");
}
I would like the method to only be
String loading();
since the rest is always the same with the name of the method appearing as String parameter in the get() method. Possibly even returning some default value when the String is missing in the JS object. But I do not know how to do that. I checked the Constants interface, but I do not really understand the code there. Can someone please give me an example how to implement such a thing?
There is no standard feature in GWT to do this, but you could create one yourself. It's a bit of a stretch, but it should work by using the GWT generator mechanisch. In global terms it should work as follows:
Create an interface (say MyMessages) with a the method names.
To use it use MyMessages message = GWT.create(MyMessages.class). Where you need the text message.loading().
Create a generator that generates an class implementing the interface. This class will created at compile time and should contain the implementation of the interface methods, like in your example.
Add a generate-with tag in your gwt.xml file to make it work.
This is a bit of a brief explanation, but I hope it helps. For more background information about generators see: What is the use GWT generator? or http://blog.arcbees.com/2015/05/26/how-to-write-gwt-generators-efficiently/
You could even reuse some of GWT's annotation's of the i18n to add for example default texts. Add the annotation to your interface and in the generator scan the annotation and use it in the code generation part.
I am working on a program that uses XStream to write out to XML. As it stands I have only one class that implements Converter. This single converter takes in my ENTIRE configuration which is a HashMap at its root and the value of each key is an new instance of VMwareServer class which in turn has a HashMap where the value of key is a new instance of VMwareVirtualMachine class. Each of the respective classes have methods for setting and getting things like IP address and port number.
What I am wondering is if this is proper way to implement the XStream converter, or should I create a separate converter to convert each class to XML on it own?
I can show some code if there is still questions about what I mean.
This is somewhat debatable, but I would argue for having a separate converter for each class. This has several benefits: if you later need to return a subset of your complete view, you will be able to easily decompose the structure along class-based lines (perhaps, for example, to limit information by permissions). If you need to return slightly different representations in different contexts, you can do so on a class-by-class basis rather than duplicating all of the presentational logic in your monolithic class.
I'm working with three separate classes: Group, Segment and Field. Each group is a collection of one or more segments, and each segment is a collection of one or more fields. There are different types of fields that subclass the Field base class. There are also different types of segments that are all subclasses of the Segment base class. The subclasses define the types of fields expected in the segment. In any segment, some of the fields defined must have values inputted, while some can be left out. I'm not sure where to store this metadata (whether a given field in a segment is optional or mandatory.)
What is the most clean way to store this metadata?
I'm not sure you are giving enough information about the complete application to get the best answer. However here are some possible approaches:
Define an isValid() method in your base class, which by default returns true. In your subclasses, you can code specific logic for each Segment or FieldType to return false if any requirements are missing. If you want to report an error message to say which fields are missing, you could add a List argument to the isValid method to allow each type to report the list of missing values.
Use Annotations (as AlexR said above).
The benefit of the above 2 approaches is that meta data is within the code, tied directly to the objects that require it. The disadvantage is that if you want to change the required fields, you will need to update the code and deploy a new build.
If you need something which can be changed on the fly, then Gangus suggestion of Xml is a good start, because your application could reload the Xml definition at run-time and produce different validation results.
I think, the best placement for such data will be normal XML file. And for work with such data the best structure will be also XMLDOM with XPATH. Work with classes will be too complicated.
Since java 5 is released this kind of metadata can be stored using annotations. Define your own annotation #MandatoryField and mark all mandatory fields with it. Then you can discover object field-by-field using reflection and check whether not initiated fields are mandatory and throw exception in this case.
I work with a dynamic Dataset model, which (in short) takes in attributes and stores them in a Map like this...
Dataset dataset = new Dataset();
dataset.setAttribute("name", "value");
...for later recovery, like this...
String value = dataset.getAttribute("name");
...and that has worked wonderfully for my purposes. But now I'm in a place where I'd like to use a templating engine to dynamically generate HTML. In the template, it's not ideal for me to do a lot of ${dataset.getAttribute("name")}. It would be rather nice if I could create artificial methods whenever something was added to a Dataset. For instance, if I did this...
dataset.setAttribute("name", "value");
...I'd like to be able to retrieve it like this...
String name;
name = dataset.name;
//or
name = dataset.getName();
...but so far I haven't been able to pull it off. What approach might I take here? Is it even doable?
Edit:
I understand that Velocity offers Property Lookup Rules to try to resolve dataset.name to dataset.get("name"), and that's great, but I need to know how to achieve this in the case that Velocity isn't the target as well.
See http://velocity.apache.org/engine/releases/velocity-1.5/user-guide.html#propertylookuprules
If your method was named get(String attribute) rather than getAttribute(String attribute), you could use the same syntax as for regular properties. So, either refactor your class, or add an additional get method that does the same thing as getAttribute, or transform your object into a Map, which has a get method.
In the past I have generated POJOs dynamically with Objectweb's ASM. This has the benefit that the underlying fields are type safe and much more efficient (esp for privative values)
You can use Dynamic Spring proxies with AOP technology or CGLib proxies. AOP could be used to describe getters like this : execution(public * com.bla.YourClass.get*())")
From what I've seen, it's fairly common for template engines for Java to support both
getters/setters of the form getAttribute, and
implementation of the Map interface
Before you spend too much time looking for a more generic solution (assuming the above won't be supported like it is in Velocity), it's probably worth taking a look at the other engines to see if any of them don't support it. If all your possible targets do, then you're probably fine relying on it.
I'm a big fan of making sure you actually have a problem before you spend the time to solve it.
My Java (JDK6) project uses Spring and JDBCTemplate for all its database access. We recently upgraded from Spring 2.5 to Spring 3 (RC1). The project does not use an ORM like Hibernate nor EJB.
If I need to read a bunch of records, and do some internal processing with them, it seems like there are several (overloaded) methods: query, queryForList and queryForRowSet
What should be the criteria to use one instead of the other? Are there any performance differences? Best practices?
Can you recommend some external references for further research on this topic?
I find that the standard way to access as list is via the query() methods rather than any of the other approaches. The main difference between query and the other methods is that you'll have to implement one of the callback interfaces (either RowMapper, RowCallbackHandler, or ResultSetExtractor) to handle your result set.
A RowMapper is likely what you'll find yourself using most of the time. It's used when each row of the result set corresponds to one object in your list. You only have to implement a single method mapRow where you populate the type of object that goes in your row and return it. Spring also has a BeanPropertyRowMapper which can populate the objects in a list via matching the bean property names to the column names (NB this class is for convenience not performance).
A RowCallbackHandler is more useful when you need your results to be more than just a simple list. You'll have to manage the return object yourself you are using this approach. I usually find myself using this when I need a map structure as my return type (i.e. for grouped data for a tree table or if I'm creating a custom cache based of the primary key).
A ResultSetExtractor is used when you want to control the iteration of the results. You implment a single method extractData that will be the return value of the call to query. I only find myself using this if I have to build some custom data structure that is more complex to build using either of the other callback interfaces.
The queryForList() methods are valuable in that you don't have to implement these callback methods. There are two ways use queryForList. The first is if you're only querying a single column from the database (for example a list of strings) you can use the versions of the method that takes a Class as an argument to automatically give you a list of only objects of those classes.
When calling the other implementations of queryForList() you'll get a list back with each entry being a map of for each column. While this is nice in that you are saved the expense of writing the callback methods, dealing with this data structure is quite unwieldy. You'll find yourself doing a lot of casting since the map's values are of type Object.
I've actually never seen the queryForRowSet methods used in the wild. This will load the entire result of the query into a CachedRowSet object wapped by a Spring SqlRowSet. I see a big downside in using this object in that if you're passing the SqlRowSet around to the other layers of your application, you're coupling those layers to your data access implementation.
You shouldn't see any huge performance differences between any of these calls except as I mentioned with the BeanPropertyRowMapper. If you're working with some complex manipulation of a large result set, you might be able to get some performance gains from writing an optimized ResultSetExtractor for your specific case.
If you want to learn more I would consult the Spring JDBC documentation and the JavaDoc for the classes I've mentioned. You can also take a look at some of the books on the Spring Framework. Though it's a bit dated Java Development with the Spring Framework has a very good section on working with the JDBC framework. Most of all, I would say just try writing some code with each method and see what works best for you.
Since you are in the wonderful Generics land, what you may really want to do is to use SimpleJdbcTemplate and use its query() methods for Lists of objects and queryForObject() for individual objects. Reasoning for this simply is that they're even easier to use than the ones in JdbcTemplate.
One small addition to the excellent answers above: additional methods, like queryForInt, queryForLong, queryForMap, queryForObject, etc. might seem like good options at times if you're running a simple query and expect a single row.
However, if you could get 0 or 1 rows back, the queryForList method is generally easier, otherwise you'd have to catch IncorrectResultSizeDataAccessException. I learned that the hard way.