Java - is dropped into the interface, and then it turns out what a cast type is

I'm struggling a bit with the class. Let me set the scene. I have a Java server code that uses a service level and orchestras. The request enters the service level in bean format (a java class matching the front end representation), and then I have a group of domainBeanMapper classes that take a bean object and translate it into a domain format object. For example, UserBean has dateOfBirth represented by a string, while User has dateOfBirth represented by Date, so UserMapper.java will make the date string into a date object. Therefore, for each object in the system, I have * .java, * Bean.java and * Mapper.java (User.java, UserBean.java, userMapper.java).

in applicationContext, I save the relationship from each object to their cartographer, for example:

<util:map id="domainBeanMappers"> <entry key="UserBean" value-ref="userMapper" /> <entry key="User" value-ref="userMapper" /> ..... 

and then I define mapper:

 <bean id="userMapper" class="com.me.mapping.UserMapper" parent="baseDomainBeanMapper"/> 

I call bean domain mapers like this from my service level:

 UserBean userBean = (UserBean) getDomainBeanMapper().mapDomainToBean(user); 

When I run this code, I find the mapper object that I need as follows:

  DomainBeanMapper mapper = findApplicableMapper(myObject.getClass().getName()); if (mapper == null) { mapper = findApplicableMapper(myObject.getClass().getSimpleName()); } 

where findApplicableMapper works as follows:

 private DomainBeanMapper findApplicableMapper(String string) { return domainBeanMappers.get(string); } 

Over the past few years, it has worked like a charm. For any object that I want on the system, I can easily select the appropriate resolver, and then transfer from my bean format to the domain format and vice versa, based on the call to .getClass () of any instance.

Now I have a new requirement that is causing me problems. I want to be able to translate from my User object into multiple sub-objects based on a parameter. So for some calls, I want to return only id, firstName and lastName. For other calls, I want more fields, but still not the whole object, and then for some calls I want the whole object to be returned as before. I do not want to follow the path of subjects and end with UserLight, UserLightWithName, UserLightWithNameButNoAddress, ... argh nightmare.

So instead, I was hoping to create a bunch of interfaces representing "views." This way, the request comes with ViewType Basic, and that means that I want the user personal data and address. So I wrote the UserBasic interface, got the User to implement it, and added the mapping from UserBasic to UserBasicMapper and from UserBasicBean to UserBasicMapper in the hope that I can make the transfer call as follows:

 UserBasicBean restrictedUserReturn = (UserBasicBean) getDomainBeanMapper().mapDomainToBean((UserBasic)user); 

but this does not work, because getClass () always returns the class of instances, and not the interface to which it was added. I think I can always add another paramater to the mapDomainToBean call, which is the class that I want to use, but the code base is pretty massive, and I will need to touch every call if I make this change.

So basically, I'm looking for a way to cast an instance to an interface type, and then find that interface type? Is this possible ??

crosses fingers ...

+5
source share
4 answers

Instead of creating the interfaces that the user implements, why not make proxy classes that are limited versions? For instance,

 class UserBasic { private User user; public UserBasic(User user) { this.user = user; } public String getFirstName() { return user.getFirstName(); } ... } 

Then you can add getUser() { return user; } getUser() { return user; } to return the full instance.

Thus, you should be able to keep everything else the same and compromise on the class interface.

+3
source

I'm not sure, but you can use the instanceof keyword to check what type of object it is.

0
source

You can do something like writing a few methods that differ with the type of paractor, for example:

 public class Test { public static void n(Number n) { System.out.println("Number"); } public static void n(Integer n) { System.out.println("Integer"); } public static void main(String[] args) { n(3); //will call the n(Integer n); n((Number)3); //will call the n(Number n); } } 

So, you can find out which type you have selected by creating several methods, each of which uses the correct type of the parameter, and then processes it with the corresponding type.

0
source

An interface does not represent a view — it defines behavior. I think you need some kind of factory (ckech these links for inspiration https://en.wikipedia.org/wiki/Factory_method_pattern , https://sourcemaking.com/design_patterns/abstract_factory ) here (or builder) If you say that something about "sub-objects" - try extending the UserBean class

 class BaseUserBean extends UserBean {} class AnotherUserBean extends UserBean {} 

put the common material for all users in the base class, and something really specific for each of your subusers, say, in child classes, and then

  UserBean u = getDomainBeanMapper().mapDomainToBean(user); 

...

 //method mapToDomain should check your param and return the type you need //ViewType can be a part of user or a separate param UserBean mapDomainToBean(User user, ViewType vt) { if (vt == ViewType.BASE) { BaseUserBean obj = BaseUserBean (); // mapping here (set fields you need) return obj; } if (vt == ViewType.ANOTHER) { AnotherUserBean obj = AnotherUserBean (); // mapping here (set fields you need) return obj; } ... } 
0
source

Source: https://habr.com/ru/post/1237722/


All Articles