Avoid two passes over a list of validators - java

I am validating the parameters passed to a series of commands in a file using the following code:
for (Parameter p : s.getCommand(idx).getParameters()) {
for (ValidationFactory.TYPES validationType : ValidationFactory.TYPES.values()) {
validator = ValidationFactory.getValidator(validationType, errors);
try {
validator.validate(p);
} catch (ValidationException e) {
Report.logErrorMessage("Failed to validate: " + validationType);
continue;
}
}
}
Then in the ValidationFactory I have:
public final class ValidationFactory {
public enum TYPES {
PROPERTIES,
PORTS
};
private ValidationFactory() {
}
public static AbstractValidator getValidator(TYPES validationType,
ValidationErrors errors) {
switch (validationType) {
case PROPERTIES:
return new PropertiesValidator(errors);
case PORTS:
return new PortRangeValidator(errors);
default:
return null;
}
}}
This code works really nicely and allows for new validators to be added at a later date. There is one relatively minor problem though...
The outer for loop iterates over a list of parameters that will be passed to the command, while the inner for loop iterates over a list of validators which can do the validation. Depending on the parameter however, it may not be necessary to continue the validation with the second validator, the first one may have already done the work... So, PropertiesValidator might have done the work needed, and now there is no need to call the second validator, but it is going to call it anyway. I guess I could use a variable to maintain validation state, and then it could skip if already done.. both validators extend an AbstractValidator class which would be the best place for this.
I would like to do the validation in one pass while keeping the structure of the Factory pattern. I was thinking of putting in some sort of delegator class.. I am using java 1.6 so I can't switch on string arguments which would be nice.

Define a Generic Validator, which is going to be common to all the validator, and define specific validation in properties and port validation. So now there is no duplication of validation by moving common logic into generic validator and specific validation in others.

Related

Serializing a POJO based on a runtime whitelist of properties

Is it possible to serialize a whitelisted subset of a POJO's properties (where the whitelist is known only at runtime) using Jackson?
All the solutions I know of so far (Views, #JsonIgnoreProperties etc.) are static, compile-time solutions.
Further, my backend returns results in the following format:
{
"outcome": "SUCCESS", // an enum
"message": "Success.", // a message for the developer
"result": {
// Some result that's different for each call
}
}
So I am looking for a solution that can be applied to only parts of the object graph (like the contents of the result property).
You probably want to look at #JsonFilter.
See this tutorial on serializing only fields that meet some criteria which includes details of this, and a couple of other methods.
For completeness
#JsonFilter("pojo-filter")
class Pojo {
public int foo;
}
FilterProvider filters = new SimpleFilterProvider()
.addFilter("pojo-filter", new SimpleBeanPropertyFilter() {
#Override
protected boolean include(PropertyWriter writer) {
return "foo".equals(writer.getName())
? Random.nextBoolean()
: true;
}
});
new ObjectMapper().writer().filters(filters).write(new Pojo());
Globally you can use ObjectMapper.setFilterProvider

Best practice - exception handling

I don't know what are the best practices in my case :
1:
public class garage {
private List<Car> cars = new ArrayList<Cars>();
public String getCarSeatSomething(String carName, String brandName) {
for(Car car : cars){
if(car.getName().equals(carName)){
Seats seats = car.getSeats();
List<Brand> brands = seats.getBrands();
for(Brand brand: brands ){
if(brand.getName().equals(brandName)){
return brand.something();
}
}
}
}
return null;
}
...
}
I have many method like this, so I will have some redundant code with this solution.
Moreover, in my program, it's not "normal" that we don't find the car, so I think I have to use Exception no ?
2 :
public class Garage {
private List<Car> cars = new ArrayList<Car>();
public Something getCarSeatSomething(String carName, String brandName) {
Car car = searchCar(carName);
if(car == null)
return null;
else{
Seats seats = car.getSeats();
return seats.getSomething(brandName);
}
}
...
}
public class Seats {
private List<Brand> brands = new ArrayList<Brand>();
protected Something getSomething(brandName){
Brand brand = searchBrand(brandName);
if(brand == null)
return null;
else
return brand.something();
}
...
}
Less redundant code and less code for each method of the class Garage because the search are only in searchBrand and searchCar.
But I have allways the problem of exceptions.
So, my last solution, is to throw exception in the searchBrand and searchCar methods, add throws at all the methods (like getCarSeatSomething) which use searchBrand/searchCar and try ... catch when I use these methods (like getCarSeatSomething).
Is that correct ?
If not, have you got better ideas ?
It looks like car name and brand name will be user provided input. In that case, you should expect users to provide names that do not exist. It is not exceptional. Return null and in the top layer, return an error message to the user. It seems reasonable that you might try to "get" something and not get it at all. null is appropriate here. But make sure you are consistent about this behavior across your application and you document it.
If an entity must contain a particular attribute then getter methods for that attribute should throw an exception if the entity cannot provide the attribute.
If it is optional for an entity to contain the attribute, then getter methods should not throw an exception.
Some scenarios will involve both cases, where in some contexts access to the attribute is mandatory and in other contexts it is optional. Then you should provide two "getter" methods, one that will throw an exception if the attribute cannot be returned, and the other an Optional value. I recommend using the method naming convention of getEntity for mandatory getter methods and findEntity for optional getter methods.
In the case where an entity must contain a particular attribute and the getter method cannot complete the request, you have a malformed entity. If your entity is throwing exceptions because it cannot return mandatory attributes you have a bug or problems with how you created the entity.
Entities should never be created without mandatory attributes. Constructors and factories should enforce mandatory attributes. For entities that must be created and not fully formed (like Data Access Objects) separate validation should be applied to the entities before being used. Or separate your domain entity and DAO into separate but equivalent types.
To describe the situation: you have a elaborate data hierarchy, with possibly a chained access:
x.getLiat().get(3).getAs().lookupB("a1").getC();
This may lead to a design with either expectable NullPointerExceptions to be handled (ugly) or Excptions.
Java 8 proposes Optional<T> to explicitly handle in one expression what otherwise could be a null.
x.getA().orElse(a).getB().orElseThrow(() -> new XException()).getC();
Better yet is to use java 8's streams, with filtering, mapping, find any/first capabilities.
private List<Car> cars = new ArrayList<>();
public Optional<String> getCarSeatSomething(String carName, String brandName) {
return cars.stream()
.filter((car) -> car.getName().equals(carName))
.flatMap{(car) -> car.getSeats())
.flatMap((seats) -> seats.getBrands())
.filter((brand) -> brand.getName().equals(brandName))
.findFirst();
}

How to map a database row to a class

Lets assume I have a database table like:
Table Building
ID int (primary key)
title varchar
And to fetch this, I have a Java Class like:
class Building{
private Integer ID;
private String title;
...
}
(Add some JPA annotations in your imagination if that helps you).
But now, depending on the actual Building, I want to execute some logic.
My first thought was to create a big switch/case like:
switch(building.getId()){
case 1:
BuildingA buildingLogic = new BuildingA(building);
break;
case 2:
BuildingB buildingLogic = new BuildingB(building);
break;
...
}
buildingLogic.doBuildingSpecificStuff();
But that would end in an endless switch/case, which would not be very clear to "read".
My next thougt (already covered by the answer of Mark Elliot) was to write the actual Class name into the database as an additional field (BuildingClass) and with some (to me currently unknown) java magic, create the object from the building.getBuildingclass() String, but I already assume that would have some sort of disadvantages...
So I thought maybe you people could give me some more ideas or comments on my thoughts.
Supposing you did have the class name, you could use reflection to instantiate a new instance, though there are some security and performance risks for going down this path.
String className = "com.foo.bar.Baz";
// gets the actual class (might throw an Exception if the class doesn't exist)
Class<?> clazz = Class.forName(className);
// probably want to have some common interface these conform to, so
// let's assume you have one, you can test this is the right kind of class
CommonBuildingType buildingLogic = null;
if (CommonBuildingType.class.isAssignableFrom(clazz)) {
// get the constructor to invoke (might throw if no match)
Constructor constructor = clazz.getDeclaredConstructor(Building.class);
// safe to cast, we checked above
buildingLogic = (CommonBuildingType) constructor.newInstance(building);
} else {
// throw an exception?
}
You should use hibernate to achieve it more sophistically

can annotation get context object?

Maybe title "can annotation get context object?" is not correct, but I don't know how to give it a right and clear one.
I use Spring AOP + Java Annotation to save log, here is my code:
CategoryAction.java :
#ServiceTracker(methodDesp="save category, category name:"+this.category.getName())
public String save() throws Exception
{
this.categoryService.save(this.category);
this.setJsonDataSimply(null);
return "save";
}
TrackAdvice.java :
public Object trackAround(ProceedingJoinPoint point) throws Throwable
{
String log = "success";
ServiceTracker tracker = null;
Method method = null;
AbstractAction action = null;
try
{
Object result = point.proceed();
action = (AbstractAction) point.getTarget();
MethodSignature signature = (MethodSignature) point.getSignature();
method = signature.getMethod();
tracker = method.getAnnotation(ServiceTracker.class);
return result;
}
catch (Exception e)
{
log = e.getMessage();
throw e;
}
finally
{
if (tracker != null)
{
String userId = (String) ActionContext.getContext().getSession().get(Constant.USERID);
if (userId == null)
{
userId = "unknown";
}
TrackLog t = new TrackLog();
t.setWhen(new Date());
t.setUserId(userId);
t.setResult(log);
t.setMethodName(action.getClass().getCanonicalName() + "." + method.getName());
t.setMethodDesp(tracker.methodDesp());
this.trackService.save(t);
}
}
}
ServiceTracker is my own annotation, in my TrackAdvice class, I get the current executing method, if the method has a ServiceTracker annotation, then save the methodDesp in annotation to database.
Now the question is the methodDesp in annotation is dynamic, I want to get this object and retrieve its category property.
It seems that Java Annotation doesn't support this, maybe it supports but I don't know how.
What you can do is use some sort of expression language in the annotation value and then run some interpreter in your advice code. One example using SPEL could look like this:
#ServiceTracker(methodDesp="save category, category name: #{category.name}")
And in your advice code, you can then extract the expression token, make use of a SpelExpression and pass it the target reference as root object (you may want to check what's available out of the box in the SPEL API for supporting your use-case(s)).
It seems that Java Annotation doesn't support this
You are correct - there is no way to do this in pure java.
The reason is that because annotations are static metadata that is wired into classes and defined at compile-time (this start to exist only at run-time, not compile-time).
In other words there is no straightforward way to make methodDesp of some annotated method of some class dynamic, since it's value has to be resolved statically, at compile-time.
However, technically there is a way to do something like you want. What I talk about is using javassist to either manipulate or create your classes (and annotations applied to them) at runtime. But be warned that this is rather hacky way and I generally would not recommend to go there.

Trigger Spring argument mapping manually?

I've a nicely working Spring argument mapping for my arguments, unfortunately I've one component which isn't passed through the DispatcherServlet and I struggle to find a way to get the mapping to run somehow manually.
An example would look like this:
public class Bar {
public Bar(#RequestParam("map") String map) {
System.out.println("Found: " + map); // Expected result "Found: value
}
}
public class Foo {
public static void main(String[] args) {
context = new ClassPathXmlApplicationContext("META-INF/context.xml");
String pseudoUrl = "/?map=value"
Bar bar = context.getBeans('bar', pseudoUrl);
}
}
It that something which could work somehow? As you can imaging the passed around data has a more complex structure and therefore I'd like to avoid that I've to write an parser on my own.
Cheers.
You could basically follow the same algorithm that DispatcherServlet.doDispatch() does:
for each HandlerMapping in the context, (line 1058 of DispatcherServlet in spring-webmvc.jar 3.1.2-RELEASE), test if HandlerMapping.getHandler(request) returns non-null
for each HandlerAdapter in the context, (line 1091) test if HandlerAdapter.supports(handlerMapping) returns true
execute HandlerAdapter.handle(request, ...) and handle the output (line 923)
This would require you to bundle up your pseudoUrl into a pseudo-HttpServletRequest, etc.
On the other hand, if you know that you always want to get a specific bean from the context in your main() method, I would just ask Spring for that bean and invoke the method explicitly, rather than dealing with mapping beans to a URL (which I assume does not change).

Categories

Resources