Java Extending an Object Except for Some Attributes of Parents - java

I have a class C extends B. and B extends A. A has an attribute name. I don't want to see name attribute at C class.
How can I do that ignore?
PS: If it is not possible at Java: I am working on a Spring project that uses Apache CXF and has a web service capability. I want to get B type object from client and send C type object to client. Because of my design issues I don't want to change my inheritance mechanism. If there is a way can I ignore name field at C class? I am implementing as first-code style.

You can declare name field in A as private and keep both A and B in same Package.
package A;
Class A {
protected String name;
}
Class B extends A{
// B can access A's attribute
}
package C;
Class C extends B{
// C cannot access name attribute defined in A.
}
And keep C is in a different package.

Please read about composition over inheritance. If you need to hide some elements then probably you do not understood properly the Object Oriented code design.
The example provided by you is too narrow to create any better answer. But what is the point of hiding in C when, you can cast it to A and still use it ?

I have a class C extends B. and B extends A. A has an attribute
name. I don't want to see name attribute at C class.
Based on your edit, you are trying to hide an attribute from a superclass (A) in the serialized representation of one of it's subclasses (C). Assuming you are using JAX-WS/JAX-RS, you can do this by overriding the property in the subclass and applying annotations to mark it as not eligible for serialization. The primary annotation to apply will be the JAXB annotation #XmlTransient. You can also #JsonIgnore the property, if you are providing the option to serialize objects as JSON. Pseudo code shown below:
#XmlRootElement
public class A implements Serializable {
private String name;
// ...
}
#XmlRootElement
public class C extends A {
#Override
#XmlTransient
public String getName() {
return super.getName();
}
}

Related

Unkown Class error trying to implement dependency injection

I'm using generics to get my code reusable and to utilize dependency injection.
I have two Interfaces: DataParserImplementation and ObjectImplementation. I have classes that implement each: SalesRepbyId implements DataParserImpl (it parses the data into objects and puts those objects into collections). SalesRep implements Objectimpl (It is the object for a specific dataset).
I'm trying to get it so that I can select which kind of Objectimpl I use in my SalesRepbyId class so I can remove the coupling.
I know there is something called reflection that I've been told is the method I need to use. I also have heard about a "Factory Pattern" and a "Properties file" that allows me to do what I want to do. A lot of this is very confusing so please explain it like I'm five.
Here is the code with where it stops working:
EDIT: Revisions based on comments: I want to specify the type of DataObject (D) my class uses by passing it through the constructor via a common interface and using generic types. When I try and use it instead of a concrete implementing class, I get the error. I can't find anything about this error.
public class SalesRepbyId<D extends ObjectImplementation> implements DataParserImplementation<Map<String,D>> {
private FileParserImplementation<ArrayList<String[]>> FileParser;
private D dataObject;
public SalesRepbyId(FileParserImplementation<ArrayList<String[]>> FileParser,D d){
this.FileParser = FileParser;
this.dataObject = d;
}
#Override
public Map<String, D> Parse() {
try{
//reads the file and returns an array of string arrays
ArrayList<String[]> Salesrep_contactlist = FileParser.ReadFile;
//here it still says "Unknown Class." that's the problem
Map<String, dataObject> SalesrepByIdMap = new HashMap<>();
//I want to be able to put in any class that implements
//dataObject into this class and have it run the same way.
Summary of what I did
I Implemented the Factory Design pattern and created a properties file which allowed me to reflect in the class I wanted instead of trying to use a generic DataObject (or D) type.
Details of Solution
Reflecting the class using the properties file "config.properties" and then casting it to type Objectimplementation allowed me to use any class that implemented that interface (and was implemented in the Factory and set in the properties file). I then refactored all instances of D to type ObjectImplementation since the parent interface is the layer of abstraction needed here rather than a generic concrete class.
Why it didn't work the way I tried it in the question
the reason the generic D type doesn't work with reflection is because reflection uses a concrete classtype determined at runtime and the generic D type is specified before runtime. Thus I was trying to reflect in the classtype and its methods/instances without properly using reflection and the code was telling me that the classtype was unknown at the time I needed it.
Code example to compare to the Question code
Example of the working code:
public class SalesRepbyId implements
DataParserImplementation<Map<String,ObjectImplementation>> {
private FileParserImplementation<ArrayList<String[]>> FileParser;
//the Factory class that creates instances of the reflected class I wanted
private ObjectFactory Factory = new ObjectFactory();
public Map<String, ObjectImplementation> Parse() {
//the proeprties object which then loads properties from a file and reflects the classtype I want
Properties prop = new Properties();
//loading in the classtype and casting it to the subclass of ObjectImplementation that it actually is
prop.load(SalesRepbyId.class.getResourceAsStream("config.properties"));
Class<? extends ObjectImplementation> Classtouse = Class.forName(prop.getProperty("ObjectImplementation")).asSubclass(ObjectImplementation.class);
//construct instances of 'Classtouse' and parse the data into these dynamically typed objects
//return the map that holds these objects
}

Programmatically assess relationship between type variables in class hierarchy

Suppose I have a Java class hierarchy defined as follow:
interface Bar<T> {}
class Foo<A,B> implements Bar<B> {}
How can I programmatically assess (using reflection) that the type parameter of Bar in Foo is the second of foo's parameters and not the first (B instead of A)?
I've tried using TypeVariable#getName() in order to compare the names, but when I apply getGenericInterfaces() to Foo<A,B> I get Bar<T> and not Bar<B>
Solution (thanks to #LouisWasserman): use Foo.class.getGeenricInterfaces()[0].getActualTypeParameters() returns the correct TypeVariable (B instead of T, in the previous example)
well using TypeVariable#getName() return the type as it appears in the source code in your case it's normal to get Bar<T>. TypeVariable Doc
Using reflection in generic Classes can't help, because of Type Erasure. Erasure of Generic Types
I've the same issue in some personal projects, I tried to change the design of my class, have a look at the example below:
Instead of this:
public class Mapper<T> {
public Mapper(){
}
}
I used this:
public class Mapper {
private Class<?> entityClazz;
public Mapper(Class<?> entity){
this.entityClazz = entity
//Here I've donne all reflection issues i want !
}
}
You can use Class#isAssignableFrom() Doc to test assignability between Class Objects.
I hope this helps, good luck !

Single Element Name mapping for all instances of a java class using jaxb

I have a class named A which is used in some other classes like B,C in different variable names ,
#XmlRootElement(name="global")
public class A{
}
#XmlRootElement
public class B{
#XmlElement
private A first;
}
#XmlRootElement
public class C{
#XmlElement
private A second;
}
Now when I marshall class B I got the A element like
<b:first>...........</b:first>
And when I marshall class C I got the A element like
<c:second>...........</c:second>
But I want to get the name "glabal" for all the occurences of class A in whichever class it is . I know i can use #XmlElement(name="global") in B and C . But i don't want to use any parameter like name,namespaces in #XmlElement field .
How can I annotate class A so that whenever any other class declares an instance of A , every time it will marshaled as <b:global></b:global> or <c:global><c:global>
If the target class is annotated with #XmlRootElement then instead of #XmlElement you can use #XmlElementRef. In this way you can define the element information once. Since the element info is defined once it will have one namespace URI associated with it. If you want the namespace info to be different then you will need to use #XmlElement.

#Any: Not supported yet

I'm working in a project that's already grown up, so I won't be able change any version of any of the used frameworks or libraries.
Actually, I had a particular situation that I managed to resolve with two entities and #Inheritance, #DiscriminatorColumn and #DiscriminatorValue. Now, I have an entity with references to both classes in the inheritance, like this:
#Entity
//Other annotations
public class A implements IA {
//Class body
}
#Entity
//Other annotations
public class B extends A implements IB { //Note: `IB` extends `IA`.
//Class body
}
#Entity
//Other annotations
public class Container {
private IA object1;
private IA object2;
}
The problem here is that I'm trying to use #Any annotation, because either object1 and/or object2 can be of type A or B. What I've done is this:
#Any(metaColumn=#Column(name="objectOneType", length=3),fetch=FetchType.EAGER)
#AnyMetaDef(idType="long",metaType="string", metaValues={
#MetaValue(targetEntity=A.class, value="A"),
#MetaValue(targetEntity=B.class, value="B")
}
)
#JoinColumn(name = "relatedObjectId")
private IA object1;
As stated here, Hibernate's #Any annotation family has no counterpart in JPA 2 and, since I can't switch to Hibernate 4.1, I'm stuck here trying to figure out a way to make it work or what should I do to fix it.
A "not so elegant" way would be to create a new entity and copy the fields from A to B, erasing the inheritance and fixgin the particular cases.
Maybe, I'm losing some particular feature in JPA that I don't know yet, so I'm currently open to and thank any kind suggestion that might point me in the right direction.
You don't need any #Any annotation. B extends A, so B is an A. So the following is sufficient:
public class Container {
#ManyToOne
private A object1;
#ManyToOne
private A object2;
}
(assuming the association is a ManyToOne. It could also be a OneToOne)
Hibernate will figure out the concrete type of both objects all by itself, and will initialize object1 and object2 with an instance of A or B.

Cast an object dynamically from a string

I'm writing a servlet-filter as the solution of this question:
Is it a good idea to filter inside a JSF template?
now, the idea is to create a big filter to check all privilegies and give the access or not to a certain user.
I create a Map to contains all privilegies for all sub applications and it has the sub application's id (a Long value) as Key and for the value another Map that contains other important informations.
The controller classes are named class1Controller, class2Controller ecc and the subapplications are stored in many folder named class1, class2 ecc...
The last thing that I must say is that all classes have a parameter called applicationID that is the same key of the Map that I mentioned previously.
So, what I would do?
I can retrieve the subapplication visited by the user using getRequestURI() method from HttpServletRequest, the problem is that I should take the application id from the class linked to that application, so I wrote this code:
Long id= ((Class.forName(packageName+applicationName+"Controller"))session.getAttribute(applicationName+"Controller")).getApplicationId();
The problem is that the compiler returns that it can't find method getApplicationId()!
Can I do something to resolve this problem? Or I must find another way to do that?
The last thing that I must say is that all classes have a parameter called applicationID
It sounds like you want an interface with the getApplicationId method in; make all the controllers implement that interface, and then all you need to do is cast to that interface.
// TODO: Work out a better interface name than "Application" :)
Object attribute = session.getAttribute(applicationName+"Controller");
Long id = ((Application) attribute).getApplicationId();
(You might want to use an abstract base class as described by BalusC - they're variations on the same theme, really.)
You're calling getApplicationId() on a Class instance, but it does not have that method at all.
The normal approach is to let all those classes extend some common base abstract class or an interface which has the method definied and then cast to that base abstract class or interface instead.
E.g. with a base abstract class:
public class FooController extends BaseController {}
public class BarController extends BaseController {}
etc..
Where the base abstract class look like this:
public abstract class BaseController {
public Long getApplicationId() {
return applicationId;
}
}
Then you can get it as follows:
Long id = ((BaseController) session.getAttribute(applicationName + "Controller")).getApplicationId();

Categories