Suppose I have a base class (which i'm simplifying):
public class GenericException extends Exception {
private Map<String,Object> map;
//...
public GenericException(String message, String[] params, Object... values) {
super(message);
map = createMap(params, values);
}
//... other stuff
public String getType() {
getClass().getName();
}
}
This class may be extended by clients but there is no point in adding members to any of its sub-classes, because the class and its sub-classes, when thrown, will result in some Json streamed to some client, containing only the map, the type, and the message
A typical sub-class may be something like
public class Exception1 extends GenericException {
private String message = "something";
private String params = new String[] {"foo", "bar"};
//...
public Exception1(Object... values) {
super(message, params, values);
}
//... other stuff
}
At some other point in the code there is a need to take the Json representation of any GenericException (or its sub-class) and create an instance of that class. The type attribute may be used to figure out which class needs to be instantiated, and the map is in the Json representation so the params and values can be obtained.
If every sub-class could be forced to implement a constructor having the parameters
String message, String[] params, Object... values
then it would be easy.
But every sub-classs, although eventually it must call the constructor in GenericException, may have various unknown constructors.
I'm looking for some magic that would allow me to inject such a [virtual] constructor into every sub-class of GenericException,
so that the code that needs to create the exeption from Json
can call this "virtual" constructor perhaps by reflection...
Is it possible to create this magic by somehow annotating the class and doing some Spring Aspect annotation? (Spring is used in this project))
Or is there some other way to do it?
Additional information added 10/16/2018
Thanks to all the commenters. I guess I need to add more information:
1) I'm using Spring Boot
2) i don't want to add setters. I think exceptions should be immutable. Let's not argue about that.
3) sure there could be directive that you must implement some additional constructor in every extension of the base class. But i prefer not to do that.
4) I know I need to use AspectJ. But how is that done?
So think about it this way: people are writing sub-classes of GenericExceptions and i don't have any control over their code. I own GenericException and i am responsibile for some infrastructure code which is supposed to reconstruct any sub-class of GenericExceptions which is in the classpath but does not have any setters.
Related
During deserialization, how can I pass in an extra object that's needed to initialize some class member? If I were doing deserialization "manually," the implementation might look like:
public class MyClass {
private MyDocumentObject do;
private String food;
public MyClass(JsonNode node, MyDocument document) {
this.do = document.createMyDocumentObject();
this.food = node.get("food").asText();
}
public String getFood() {
return this.food;
}
}
But I'd like to use Jackson's automatic mapping facilities and use a decorated constructor or custom deserializer, etc. and avoid implementing the deserialization within the class itself. Looking at example implementations using #JsonCreator or extending StdDeserializer, I can't see a way of saying "hey, please use this MyDocument object when you call the constructor." I'd like to avoid implementing and exposing a separate method that accepts a MyDocument that I have to invoke on every object that gets deserialized, e.g.
public createDocumentObject(MyDocument document) {
this.do = document.createMyDocumentObject();
}
I don't want to have this method at all, but if I had to, I'd want Jackson to call this method for me right after deserialization. That means I'd still have to somehow tell Jackson which MyDocument to use.
I'm implementing a factory a class in charge of managing tokens across an application. I'll explain the problem I'm facing after this simplified example:
Suppose we have our factory class:
TokenManagerFactory.java:
public class TokenManagerFactory {
public static TokenManager create(String tokenType)
{
if ("JWT".equals(tokenType))
return new JwtTokenManagerImpl();
return null;
}
}
Then our abstract interface:
public abstract interface TokenManager {
public String generateToken();
public boolean verifyToken();
}
And finally the implementation JwtTokenManagerImpl:
public class JwtTokenManagerImpl implements TokenManager {
//..Implementation of methods defined in interface (generateToken() and
// verifyToken())
public String aMethodNotDefinedInInterface() {
return "A very cool String";
}
}
Now in our main we want to create an instance of JwtTokenManager:
main {
TokenManager tm = TokenManagerFactory.create("JWT");
tm.aMethodNotDefinedInInterface(); // <-- Compilation error.
}
The method aMethodNotDefinedInInterface() is undefined for the type
TokenManager
How do I adjust this design pattern so this error does not occur? Downcasting for when doing such calls seems like a harsh solution, is there a higher level adjustment I could make to accommodate this scenario?
Thanks.
I marked the solution I ended up using.
How do I adjust this design pattern so this error does not occur?
You have to make a choice : either working with a base common type to manipulate all subclasses in an uniform way from the API of the base common type or casting it to a specific type to be able to invoke specific method of a subclass.
Some ideas to solve your issue :
Add the method in the interface.
If the method is expected for some implementations but not for all you could add it in the interface with a default implementation (that throws UnsupportedOperationException for example). You could override it in the subclass that wants to support it.
It will work but will also do your code more brittle as the exception would be throw only at runtime.
Provide an additional factory method that returns the concrete subclass in its declaration.
Or as alternative enrich the actual method to return a generic type inferred by the target type specified in the return of the invoker. It is not type safe but it spares an explicit cast.
It would give something like :
#SuppressWarnings("unchecked")
public static <T extends TokenManager> T create(String tokenType) {
if ("JWT".equals(tokenType)) {
return (T) new JwtTokenManagerImpl();
}
return null;
}
That you invoke :
JwtTokenManagerImpl token = create("JWT");
Use the decorator pattern to enrich the behavior of some objects if it matches to your need. You should rely on a common method in TokenManager that the decorator will enrich.
You could so write something like :
TokenManager tm = new TokenFooDecorator(TokenManagerFactory.create("JWT"));
You could change TokenManagerFactory to accept an interface instead?
public interface JwtTokenManager extends TokenManager {
String aMethodNotDefinedInInterface();
}
public class TokenManagerFactory {
public static <T extends TokenManager> T create(Class<T> managerInterface) {
if (managerInterface == JwtTokenManager.class) {
return (T) new JwtTokenManagerImpl();
}
return null;
}
}
Then where you use the factory can be something like:
public static void main(String[] args) {
JwtTokenManager tm = TokenManagerFactory.create(JwtTokenManager.class);
tm.aMethodNotDefinedInInterface();
}
If aMethodNotDefinedInInterface() is required for all Token managers, then it should be added to the interface.
Otherwise, this suggests that you need a different flow for each Token Manager, in which case you might want to use the Bridge design pattern.
In this case, the Implementor hierarchy will be the token managers, and the Abstraction hierarchy will consist of the different flows implementations.
Then you can match the flow you want with the token implementation you want.
You'll still need to add the method to the interface, and either:
Add an empty implementation where its not relevant.
Throw UnsupportedOperationException exception, indicating that the flow/token manager combination is illegal.
I am going to talk about what is wrong with your design first:
Here is your code:
TokenManager tm = TokenManagerFactory.create("JWT");
tm.aMethodNotDefinedInInterface(); // <-- Compilation error.
The question is, why does the create method take a token when you only have one possible value for that token? You might as well always return the concrete type.
You are going to tell me that you might want to do this:
String token = getTokenFromSomewhere(); // it may or may not be JWT
TokenManager tm = TokenManagerFactory.create(token);
tm.aMethodNotDefinedInInterface(); // <-- Compilation error.
In that case, you don't know what type of TokenManager you have returned, so you can't call a method on it unless it is in the interface.
You might now say that you would want to do either of the two cases - with a known token or an unknown token. In this case, the known token case is a bit of a mis-use of the factory method since its design is to return any type of token. You are using the factory in two different ways. You could therefore either create a specific factory method for the particular token, or just use a cast.
A method Not Defined In the Interface, cannot be invoked using the Interface type. So the reference variable tm of Interface type TokenManager has to be cast to one of the sub type, before invoking the specific method(that is not in the interface, but in the specific class).
if (tm instanceof JwtTokenManagerImpl ) {
JwtTokenManagerImpl jwtTm = (JwtTokenManagerImpl) tm;
jwtTm.aMethodNotDefinedInInterface();
}
I've got a Kotlin class, similar to
data open class MyDto (
var property: String? = null
// ...
)
and a Java class extending this class, similar to
class MySpecificDto extends MyDto {
private String field;
// getter/setter for "field"
public MySpecificDto(final MyDto prototype)
{
super(prototype);
}
}
What is missing in Kotlin's DTO for the "super(prototype)" statement to compile?
MyDto's constructor takes a single parameter of type String, and you are trying to pass it a MyDto.
I think you are looking for --
super(prototype.getProperty());
Data classes seem a like logical base for a hierarchy of DTOs. Unfortunately, they do not play well with inheritance, so doing so is not a good idea. See this answer.
Update to address comment --
For a Kotlin side solution, you need to remember Kotlin classes only allow for a single constructor. For data classes, the format of that constructor is already defined, so you cannot just pass an object and have it work, or define a different constructor. Also, as noted by #bashor in comment to your original question, there is no copy constructor. You can, however, create a separate function to initialize your object if you want --
data open class MyDto (var property: String? = null //...) {
fun init(dto: MyDto) {
property = dto.property
//... rest of the properties
}
}
and the in your Java constructor call init instead of super.
public class MySpecificDto extends MyDto {
private String field;
public MySpecificDto(final MyDto prototype)
{
init(prototype);
}
}
The caveat on this solution is that your data class must provide default values for all of its properties because there is an implicit call to the constructor with zero parameters.
I often find I want to do something like this:
class Foo{
public static abstract String getParam();
}
To force a subclasses of Foo to return a parameter.
I know you can't do it and I know why you can't do it but the common alternative of:
class Foo{
public abstract String getParam();
}
Is unsatisfactory because it requires you to have an instance which is not helpful if you just want to know the value of the parameter and instantiating the class is expensive.
I'd be very interested to know of how people get around this without getting into using the "Constant Interface" anti pattern.
EDIT: I'll add some more detail about my specific problem, but this is just the current time when I've wanted to do something like this there are several others from the past.
My subclasses are all data processors and the superclass defines the common code between them which allows them to get the data, parse it and put it where it needs to go.
The processors each require certain parameters which are held in an SQL database. Each processor should be able to provide a list of parameters that it requires and the default values so the configuration database can be validated or initialised to defaults by checking the required parameters for each processor type.
Having it performed in the constructor of the processor is not acceptable because it only needs to be done once per class not once per object instance and should be done at system startup when an instance of each type of class may not yet be needed.
The best you can do here in a static context is something like one of the following:
a. Have a method you specifically look for, but is not part of any contract (and therefore you can't enforce anyone to implement) and look for that at runtime:
public static String getParam() { ... };
try {
Method m = clazz.getDeclaredMethod("getParam");
String param = (String) m.invoke(null);
}
catch (NoSuchMethodException e) {
// handle this error
}
b. Use an annotation, which suffers from the same issue in that you can't force people to put it on their classes.
#Target({TYPE})
#Retention(RUNTIME)
public #interface Param {
String value() default "";
}
#Param("foo")
public class MyClass { ... }
public static String getParam(Class<?> clazz) {
if (clazz.isAnnotationPresent(Param.class)) {
return clazz.getAnnotation(Param.class).value();
}
else {
// what to do if there is no annotation
}
}
I agree - I feel that this is a limitation of Java. Sure, they have made their case about the advantages of not allowing inherited static methods, so I get it, but the fact is I have run into cases where this would be useful. Consider this case:
I have a parent Condition class, and for each of its sub-classes, I want a getName() method that states the class' name. The name of the sub-class will not be the Java's class name, but will be some lower-case text string used for JSON purposes on a web front end. The getName() method will not change per instance, so it is safe to make it static. However, some of the sub-classes of the Condition class will not be allowed to have no-argument constructors - some of them I will need to require that some parameters are defined at instantiation.
I use the Reflections library to get all classes in a package at runtime. Now, I want a list of all the names of each Condition class that is in this package, so I can return it to a web front end for JavaScript parsing. I would go through the effort of just instantiating each class, but as I said, they do not all have no-argument constructors. I have designed the constructors of the sub-classes to throw an IllegalArgumentException if some of the parameters are not correctly defined, so I cannot merely pass in null arguments. This is why I want the getName() method to be static, but required for all sub-classes.
My current workaround is to do the following: In the Condition class (which is abstract), I have defined a method:
public String getName () {
throw new IllegalArugmentException ("Child class did not declare an overridden getName() method using a static getConditionName() method. This must be done in order for the class to be registerred with Condition.getAllConditions()");
}
So in each sub-class, I simply define:
#Override
public String getName () {
return getConditionName ();
}
And then I define a static getConditionName() method for each. This is not quite "forcing" each sub-class to do so, but I do it in a way where if getName() is ever inadvertently called, the programmer is instructed how to fix the problem.
It seems to me you want to solve the wrong problem with the wrong tool. If all subclasses define (can't really say inherit) your static method, you will still be unable to call it painlessly (To call the static method on a class not known at compile time would be via reflection or byte code manipulation).
And if the idea is to have a set of behaviors, why not just use instances that all implement the same interface? An instance with no specific state is cheap in terms of memory and construction time, and if there is no state you can always share one instance (flyweight pattern) for all callers.
If you just need to couple metadata with classes, you can build/use any metadata facility you like, the most basic (by hand) implementation is to use a Map where the class object is the key. If that suits your problem depends on your problem, which you don't really describe in detail.
EDIT: (Structural) Metadata would associate data with classes (thats only one flavor, but probably the more common one). Annotations can be used as very simple metadata facility (annotate the class with a parameter). There are countless other ways (and goals to achieve) to do it, on the complex side are frameworks that provide basically every bit of information designed into an UML model for access at runtime.
But what you describe (processors and parameters in database) is what I christened "set of behaviors". And the argument "parameters need to be loaded once per class" is moot, it completely ignores the idioms that can be used to solve this without needing anything 'static'. Namely, the flyweight pattern (for having only once instance) and lazy initialization (for doing work only once). Combine with factory as needed.
I'm having the same problem over and over again and it's hard for me to understand why Java 8 preferred to implement lambda instead of that.
Anyway, if your subclasses only implement retrieving a few parameters and doing rather simple tasks, you can use enumerations as they are very powerful in Java: you can basically consider it a fixed set of instances of an interface. They can have members, methods, etc. They just can't be instanciated (as they are "pre-instanciated").
public enum Processor {
PROC_IMAGE {
#Override
public String getParam() {
return "image";
}
},
PROC_TEXT {
#Override
public String getParam() {
return "text";
}
}
;
public abstract String getParam();
public boolean doProcessing() {
System.out.println(getParam());
}
}
The nice thing is that you can get all "instances" by calling Processor.values():
for (Processor p : Processorvalues()) {
System.out.println(String.format("Param %s: %s", p.name(), p.getParam()));
p.doProcessing();
}
If the processing is more complex, you can do it in other classes that are instanciated in the enum methods:
#Override
public String getParam() {
return new LookForParam("text").getParam();
}
You can then enrich the enumeration with any new processor you can think of.
The down side is that you can't use it if other people want to create new processors, as it means modifying the source file.
You can use the factory pattern to allow the system to create 'data' instances first, and create 'functional' instances later. The 'data' instances will contain the 'mandatory' getters that you wanted to have static. The 'functional' instances do complex parameter validation and/or expensive construction. Of course the parameter setter in the factory can also so preliminary validation.
public abstract class Processor { /*...*/ }
public interface ProcessorFactory {
String getName(); // The mandatory getter in this example
void setParameter(String parameter, String value);
/** #throws IllegalStateException when parameter validation fails */
Processor construct();
}
public class ProcessorA implements ProcessorFactory {
#Override
public String getName() { return "processor-a"; }
#Override
public void setParameter(String parameter, String value) {
Objects.requireNonNull(parameter, "parameter");
Objects.requireNonNull(value, "value");
switch (parameter) {
case "source": setSource(value); break;
/*...*/
default: throw new IllegalArgumentException("Unknown parameter: " + parameter);
}
}
private void setSource(String value) { /*...*/ }
#Override
public Processor construct() {
return new ProcessorAImpl();
}
// Doesn't have to be an inner class. It's up to you.
private class ProcessorAImpl extends Processor { /*...*/ }
}
I have a parser class "MessageParser" which i pass a message which is of type "String" to it for it to be parsed. The parsing method signature for the class is
public void parse(String message);
I need to pass an instance of "Properties" to it but i dont want to change the signature of the method to add a new argument to it. I have been struggling with this for the last couple of days and have tried a couple of options - see Sending in an object of type Object instead of String - Polymorphism
The class that calls the parsing method "ParserManager" knows of the properties object. Is there a way for the MessageParser to find the properties object without it being passed to it?
Edit
Here is some example code.
I would like the "MessageCparser" to access the "prop" object in "ParserManager" without changing anything in the "Parser" interface or the "ParserManager" class. Is this possible?
public interface Parser{
public void parse(String message);
}
public class MessageCParser implements Parser{
public void parse(String message){
MessageObject mobject = (MessageObject)message;
System.out.println("Parsing C" + mobject.getMessage());
}
public void parse(String m){}
}
import java.util.HashMap;
public class ParserManager{
Properties prop = null;
public ParserManager() {
prepare();
prop = new Properties()
}
HashMap parsers = new HashMap();
public void prepare(){
parsers.put("A",new MessageCParser());
}
public void parseMessage(String msgType, String message){
((Parser)parsers.get(msgType)).parse(message);
}
}
Thanks
The most evident solution would be to add a reference to the Properties object as a field in the ParserManager, and then either provide the ParserManager with the properties object as a constructor argument or through a setter-method as shown below:
class ParserManager {
...
Properties props;
public void setParsingProperties(Properties props) {
this.props = props;
}
public void parse(String message) {
// props available here, without being passed as agurment.
}
}
class CallingParserManager {
...
void someMethod() {
...
parserManager.setParsingProperties(propertiesToUse);
parserManager.parse(theString);
...
}
...
}
Looking at your previous question, I'd say it would be fine if you added a setParsingProperties in the Parser interface. The method can be implemented as an empty method for those parser that don't need the properties.
Regarding your edit: No, it's not possible to solve it like that.
MessageObject mobject = (MessageObject) message;
Will only work if MessageObject is a subtype of String (but since String is final (can't be extended) that cannot be the case).
The dirty quick-fix would be to check (with instanceof) if the Parser is an instance of MessageCParser and cast it and then use a MessageCParser specific parse method that takes the Properties as an argument.
Well, there are four ways of getting information, broadly speaking:
It could be part of the state of the object that the method is called on (e.g. it could be passed to the constructor and then retained in a field)
It can be a parameter of the method itself
It could be accessed statically, e.g. via a singleton
It could be accessed via a thread-local variable
All of these can be used with indirection of course - for example, if something else which knows about the Properties is available via one of the above mechanisms, then you can get to that and then find out about the Properties. But you can't just find out the calling object and ask that.
What do you need to do with the Properties in question? Would the Properties vary on a call-by-call basis for the same MessageParser? If so, it really should be a parameter. You say you don't want to change the signature of the method - but if you want to pass more information in, that's exactly what you should do.
If you have only one instance of your "Properties" object, you can use something like the Singleton pattern.
You can also add a reference to the ParserManager somewhere in your MessageParser and then call a method on ParserManager which will return the Properties, but without some code snippets it's impossible to help you further than this.