Cannot access the unique properties of a concrete class using polymorphism - java

I am using the factory pattern to create objects of different connections in java version "1.7.0_60"
The problem I am facing is that each concrete class will have unique properties for that particular class. As the factory will use polymorpthism when it return the instance of the concrete class, I cannot access the unique properties. i.e. getHostType() is unique only for SqlServerConnection.
The workaround I have done is to declare getHostType() abstract in the super class and implement it in each concrete class. However, I don't really want to do it that way as the more concrete classes I add that have their unique properties the more abstract methods I will have to include in the super class, and then implement them in each concrete class.
I want to keep my factory pattern and the abstract super class. I am just wondering if there is any other way instead of having the abstract methods in the super class? Any design patterns I can include to get around this?
public abstract class Connection {
private int port;
private int ipAddress;
public Connection() {}
public String description() {
return "Generic";
}
/* Implement in every concrete class, even if the concrete type doesn't have that property */
public abstract int getHostType();
}
public class SqlServerConnection extends Connection {
private int sqlHostType;
public SqlServerConnection() {
sqlHostType = 5060;
}
#Override
public String description() {
return "Created a Sql Server connection type";
}
#Override
public int getHostType() {
return sqlHostType;
}
}
public class OracleConnection extends Connection {
public OracleConnection() {}
#Override
public String description() {
return "Created an Oracle connection type";
}
}
final public class ConnectionFactory {
protected String mType;
public ConnectionFactory(String type) {
mType = type;
}
/* Create the connection we want to use */
public Connection createConnection() {
if(mType.equals("Oracle")) {
return new OracleConnection();
}
else if(mType.equals("SQLServer")) {
return new SqlServerConnection();
}
else {
return null;
}
}
}
public class TestConnection {
public static void main(String[] args) {
ConnectionFactory factory = new ConnectionFactory("SQLServer");
Connection conn = factory.createConnection();
conn = factory.createConnection();
System.out.println(conn.description());
/* need to access the getHostType() */
System.out.println(conn.getHostType());
}
}

You should have a look at the visitor pattern. You need to declare an interface ConnectionVisitor and add an method visit for each of your connection class in your hierarchy.
public interface ConnectionVisitor {
public int visit (Connection connection);
public int visit (SqlServerConnection sqlconnection);
public int visit (OracleConnection oracleConnection)
}
Now you need to add an accept method in your base class connection and that accepts a ConnectionVisitor and then calls visit on it. Your new Connection class will look something like
public abstract class Connection {
private int port;
private int ipAddress;
public Connection() {}
public String description() {
return "Generic";
}
public int accept(ConnectionVisitor visitor){
return visitor.visit(this);
}
}
Notice that the accept method does a dual dispatch. It dispatches on the base of the object on which it is called and the parameter that is passed to this method. This is at the heart of visitor pattern.
You can then implement the ConnectionVisitor interface to define any new functionality without changing your base class.
class DemoVisitor implements ConnectionVisitor{
public int visit(Connection connection){
System.out.println("Visiting Connection");
return 1;
}
public int visit(SqlServerConnection sqlServerConnection){
System.out.println("Visiting SqlServerConnection");
return 1;
}
public int visit(OracleConnection oracleConnection){
System.out.println("Visiting Oracle Connection");
return 1;
}
}
In your TestConnection class you can simply create a new connection object and then call accept method on that object passing a visitor object.
public class TestConnection {
public static void main(String[] args) {
ConnectionFactory factory = new ConnectionFactory("SQLServer");
Connection conn = factory.createConnection();
conn = factory.createConnection();
System.out.println(conn.description());
ConnectionVisitor visitor = new DemoVisitor();
System.out.println(conn.accept(visitor));
}
}
So now any child class specific functionality must not reside in connection class hierarchy instead they must be implemented in new visitors.
Note that this pattern is not going to fit as such in your scenario. One of the limitation of this pattern in that the return type for all the methods in visitor interface must be same. This pattern may or may not fit your needs but it is worth looking into your case as such. You will probably need to modify this pattern to fit your needs. And that is what patterns are all about looking into some common solutions and then modifying those solutions to fit into your problem.

Why do you want that? I mean, I use a Factory to hide specific implementation of factorized object, returning a common abstract class (or an interface).
I wonder why you may want to do something like:
ConnectionFactory factory = new ConnectionFactory("SQLServer");
Connection conn = factory.createConnection();
if(conn.getHostType() == 1 ) {
doSomethingLogic();
}
if(conn.getHostType() == 2) {
doSomethingElseLogic();
}
shouldn't all the ifs be inside the factory?

You need to have the getHostType() method in your Connection class for this method to be called polymorphically.
The only other solution is to type cast the object returned by the factory to the one expected which is not at all a good approach. Reason for this is you will have to keep check on the Class type of the returned object whether it is of ORACLE or MySQL etc through if else statements (unnecessary we have ploymorphism to prevent this). If you just define the method in your Connection class you dont need to worry about the getHostType() method, as it will be called from the correct class polymorphically.
In the oracleConnection class you can just add the method getHostType() that returns null object with an error message in the code you wrote.

I don't know how applicable this approach will be to your specific situation, but you could try grouping related, optional, subclass-specific connection behavior into its own interfaces and then let each concrete class implement the interfaces that are appropriate for it.
In your example, both connection classes implement description() so you could create an Interface called Descriptor and have a method on your abstract class called getDescriptor():
public Descriptor getDescriptor() throws HasNoDescriptorException {
if (self instanceof Descriptor) {
return self;
}
throw new HasNoDescriptorException();
}
And then let interface Descriptor provide the description() method.
You'd get a connector's description like this:
String desc = "";
try {
desc = connector.getDescriptor().description();
} catch (HasNoDescriptorException e) {
// connector doesn't have a description() method;
}
If you don't like exceptions you could just return and test for nulls.
For that matter, your code could simply test to see if the connection instance is an instance of the Descriptor interface and if it is then you know you have full access to any of the methods appropriate for a Descriptor.
To continue the example, you could have a TypedHost interface whose implementing connection classes provide a getSqlHost() method.

I'd do it like this:
Remove the getHostTypeCreate method from the abstract class since not all of the connections have this property. Then add a new interface IHostTypeProvider(you might pick a better name though):
public interface IHostTypeProvider {
int getHostType();
}
Now, make some of the sub-classes implement this interface:
public SqlServerConnection extends Connection implements IHostTypeProvider {
....
public int getHostType() {
return 5060;
}
}
When you actually need access to the property, you fist need to check if it's available for this type of connection:
Connection con = ...;
//Check if host type is available
if (connection instanceof IHostTypeProvider) {
System.out.println(((IHostTypeProvider)con).getHostType());
}
Hope that helps.

Sounds like a use case for typesafe heterogeneous container. I'll just post my example, I think it's pretty much explaining itself. If there are any questions left, I'll answer them.
The Pros are that it is easily extensible and it supports multiple types.
import java.util.HashMap;
import java.util.Map;
public abstract class Connection
{
/* typesafe heterogeneous container */
private final Map<Property<?>, Object> properties = new HashMap<Property<?>, Object>();
public Connection(String ip, int port)
{
addProperty(ConnectionProperties.IP_ADDRESS, ip);
addProperty(ConnectionProperties.PORT, port);
}
/**
* Gets property in its respective type.
*
* #param p property
* #return value of property.
*/
public <T> T getProperty(Property<T> p)
{
Object obj = properties.get(p);
if (obj == null)
return null;
Class<T> clazz = p.getClazz();
return clazz.cast(obj);
}
/**
* Checks whether property is available
*
* #param p property to check for
* #return <code>true</code>, if property is available
*/
public boolean hasProperty(Property<?> p)
{
return properties.get(p) != null;
}
/* helper method to add properties */
protected <T> void addProperty(Property<T> p, T value)
{
properties.put(p, value);
}
}
class SqlServerConnection extends Connection
{
public SqlServerConnection(String ip, int port)
{
super(ip, port);
addProperty(ConnectionProperties.DESCRIPTION, "Created a Sql Server connection type");
addProperty(ConnectionProperties.SQL_HOST_TYPE, 5090);
}
}
/* all properties are stored here (...there could be more classes if needed) */
final class ConnectionProperties
{
private ConnectionProperties()
{
// private contructor to prevent instantiation of utility class
}
public static final Property<String> IP_ADDRESS = new Property<String>("IP_ADDRESS", String.class);
public static final Property<Integer> PORT = new Property<Integer>("PORT", Integer.class);
public static final Property<String> DESCRIPTION = new Property<String>("DESCRIPTION", String.class);
public static final Property<Integer> SQL_HOST_TYPE = new Property<Integer>("SQL_HOST_TYPE", Integer.class);
}
/* property class that serves as key for typesafe heterogeneous container */
final class Property<T>
{
/* has to be unique */
private final String name;
private final Class<T> clazz;
public Property(String name, Class<T> clazz)
{
this.name = name;
this.clazz = clazz;
}
public String getName()
{
return name;
}
public Class<T> getClazz()
{
return clazz;
}
#Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
#Override
public boolean equals(Object obj)
{
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Property<?> other = (Property<?>) obj;
if (name == null)
{
if (other.name != null)
return false;
}
else if (!name.equals(other.name))
return false;
return true;
}
}
You could also define a interface for Property<T> and for Connection, that would have the future benefit of having the possibility to exchange the implementations, but I left it out to spaer some space here.
If the instantion of properties is to complex, there are also other alternatives. For example following
public final class PropertyV2<T>
{
private static final AtomicInteger KEY_SUPPLY = new AtomicInteger();
/* unique key for property distinction */
private final int key;
private final Class<T> clazz;
private PropertyV2(Class<T> clazz)
{
this.key = KEY_SUPPLY.getAndIncrement();
this.clazz = clazz;
}
/* factory method for string properties */
public static PropertyV2<String> string()
{
return new PropertyV2<String>(String.class);
}
/* factory method for integer properties */
public static PropertyV2<Integer> integer()
{
return new PropertyV2<Integer>(Integer.class);
}
public Class<T> getClazz()
{
return clazz;
}
#Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + key;
return result;
}
#Override
public boolean equals(Object obj)
{
if (obj == null || getClass() != obj.getClass())
return false;
PropertyV2<?> other = (PropertyV2<?>) obj;
if (key != other.key)
return false;
return true;
}
}
class ConnectionPropertiesV2
{
private ConnectionPropertiesV2()
{
// private constructor to prevent instatiation of utiltiy class
}
PropertyV2<String> IP_ADDRESS = PropertyV2.string();
PropertyV2<Integer> PORT = PropertyV2.integer();
}
The problem hereby is, that you lose the name attribute, which can be useful if you want to use the property name at runtime - let's say in an exception.

The more OO approach is to push the implementation details into the child class, rather than expose them in abstract methods (which may not have a well-defined implementation for some children).
For example rather than writing,
System.out.println(conn.description());
/* need to access the getHostType() */
System.out.println(conn.getHostType());
Instead, write
conn.printTo(System.out);
Then provide a printTo method for each child. In this way, you've refactored the code to hide all of the implementation details of the Connection objects and how it prints itself to a stream.

Related

Cleanest pattern for filtering objects of unknown type?

I have an application that takes json objects from a queue, deserializes them to a model, applies a list of filters, and sends the objects that pass all filters through to another queue.
The two complicating criteria are:
The set of filters is determined and injected via Spring profile at startup.
The type of object that the json is being deserialized to is also determined the by the Spring profile at startup.
The following solution is ugly because it involves casting:
public class MessageTypeOne {
public int someField;
}
public class MessageTypeTwo {
public int otherField;
}
public interface MessageFilter {
boolean doesFilterPass(Object object);
}
#Component
#Profile("ProfileOne")
public class OneOfMyMessageFilters implements MessageFilter {
public boolean doesFilterPass(Object object) {
MessageTypeOne message = (MessageTypeOne)object;
if (message.someField == something) {
return false;
} else return true;
}
}
#Component
#Profile("ProfileTwo")
public class AnotherOneOfMyMessageFilters implements MessageFilter {
public boolean doesFilterPass(Object object) {
MessageTypeTwo message = (MessageTypeTwo)object;
if (message.otherField == something) {
return false;
} else return true;
}
}
#Service
public class MessageFilterService {
// injected at runtime via Spring profile
private Set<MessageFilter> messageFilters
#AutoWired
public MessageFilterService(Set<MessageFilter> messageFilters) {
this.messageFilters = messageFilters;
}
public boolean passesAllFilters(Object object) throws IOException {
for (MessageFilter filter : messageFilters) {
if (!filter.doesFilterPass(object)) {
return false;
}
}
return true;
}
}
What's the cleanest pattern for cases like these? I've read about the visitor pattern but I'm not sure that's any better than casting like this.
As far as design pattern is concerned, I think it is of type Strategy pattern. I am not talking about Spring way of implementation. You may have n number of filters, but you have to choose based upon the context. So strategy pattern is best fitted here. Others can provide other patterns. You can strategy pattern in the below link.
https://en.wikipedia.org/wiki/Strategy_pattern
What about visitor pattern with Java reflection? Here is an old article:
https://www.javaworld.com/article/2077602/java-tip-98--reflect-on-the-visitor-design-pattern.html
When you want to decouple messages from filters and relation is many to many you can always use Chain of Responsibility.
#Service
public class MessageFiltersAggregator {
private MessageFilter chainEntryNode;
#AutoWired
public MessageFilterService(Set<MessageFilter> messageFilters) {
this.chainEntryNode = buildChain(messageFilters);
}
public boolean passesAllFilters(Object object) throws IOException {
return chainEntryNode.doesFilterPass(object);
}
}
You need to implement buildChain method which creates chain from collection. Of course, each element in chain should have next property. In this case MessageFilter could look like below:
public abstract class MessageFilter {
private MessageFilter next;
//constructors, setters, etc
public boolean doesFilterPass(Object object) {
boolean res = true;
if (canHandle(object)) {
res = validate(object);
}
return res && next.doesFilterPass(object);
}
public abstract boolean validate(Object object);
public abstract boolean canHandle(Object object);
}
Abstract class contains chain logic you just need to implement two methods in each subclass. One of implementation could look like below:
public class AnotherOneOfMyMessageFilters extends MessageFilter {
public boolean canHandle(Object object) {
return object instanceof MessageTypeTwo;
}
public boolean validate(Object object) {
MessageTypeTwo message = (MessageTypeTwo)object;
return message.otherField == something;
}
}
All above classes are just example created without IDE so could have issues in syntax but should give you an idea how it should work.
See also:
Chain of Responsibility in Java
Chain of Responsibility Design Pattern in Java
If I understand your problem correctly, then it's possible to configure your Spring profile in a way that makes your filters throw ClassCastExceptions.
Assuming that you configuration options are the way you want, then it demonstrates the only real problem with your design -- your filters can be applied to any Object, and that's what the interface says -- doesFilterPass( Object ) -- but your filters only really work with certain types of objects.
That's what you need to fix. If the filter is applied to a strange type of object, does it pass or fail? You can decide this on a per-filter basis and then just fix it like this:
public boolean doesFilterPass(Object object) {
if (!(object instanceOf MessageTypeTwo)) {
return true;
}
MessageTypeTwo message = (MessageTypeTwo)object;
if (message.otherField == something) {
return false;
} else return true;
}
Easy peasy.
I know you don't like the cast, but it's a direct result of the configuration options you provide -- the profile can be configured to apply filters to any kind of object. You just need to support that, and that means there has to be casting somewhere.
This became much cleaner with generics. Since I know what type of Object each filter can handle I can just do this, eliminating the casting:
public class MessageTypeOne {
public int someField;
}
public class MessageTypeTwo {
public int otherField;
}
public interface MessageFilter<T> {
boolean doesFilterPass(T message);
}
#Component
#Profile("ProfileOne")
public class OneOfMyMessageFilters<T extends MessageTypeOne> implements MessageFilter<T> {
public boolean doesFilterPass(MessageTypeOne message) {
if (message.someField == something) {
return false;
} else return true;
}
}
#Component
#Profile("ProfileTwo")
public class AnotherOneOfMyMessageFilters<T extends MessageTypeTwo> implements MessageFilter<T> {
public boolean doesFilterPass(MessageTypeTwo message) {
if (message.otherField == something) {
return false;
} else return true;
}
}
#Service
public class MessageFilterServiceImpl<T> implements MessageFilterService<T> {
// injected at runtime via Spring profile
private Set<MessageFilter<T>> messageFilters
#AutoWired
public MessageFilterService(Set<MessageFilter<T>> messageFilters) {
this.messageFilters = messageFilters;
}
public boolean passesAllFilters(T message) throws IOException {
for (MessageFilter filter : messageFilters) {
if (!filter.doesFilterPass(message)) {
return false;
}
}
return true;
}
}
public interface MessageFilterService<T> {
boolean passesAllFilters(T rawEvent) throws IllegalArgumentException;
}

How to create a 'getter' using a lambda expression

I have an object in use throughout my codebase, UnsecureObject. This object is auto-generated with no getters/setters, and all member fields are public. So editing is done by doing something like the following:
unsecureObjInstance.firstName = "Jane";
This is not desirable for numerous reasons that I probably don't have to explain here. But using this generated class is required for some other technical details with our messaging pipeline that I won't go into.
I have a desire is to leverage a mapping utility written by someone else on my team to convert this UnsecureObject to a pojo that I am writing.
An example of the mapper in action (with two normal classes w/ getters/setters) would be something like:
new MapperBuilder<>(PojoOne.class, PojoTwo.class)
.from(PojoOne::getName).to(PojoTwo::getFirstName)
.build();
This will map the PojoOne#name field to the PojoTwo#firstName field.
Is there a way to translate this to input my UnsecureObject here? I have tried something like the following:
new MapperBuilder<>(UnsecureObject.class, SecureObject.class)
.from(u -> u.firstName).to(SecureObject::getFirstName)
.build();
But get an error here, something along the lines of 'u -> u.firstName' could not be invoked.
So the question is:
Is there a way to essentially "construct" a getter on the fly using these public members? So in the .from() method, I can construct the call to look like a standard method that will yield my u.firstName?
Thanks for the help!
EDIT:
this is approx what the MapperBuilder class looks like (attempted to edit a bit to take away project specific wrappers/simplify)
/**
* This class is used to convert between POJO getter method references to the corresponding field names.
* #param <B> type
*/
public interface PojoProxy<B> {
/**
* Invokes the given getter method and returns information about the invocation.
* #param getter the getter to invoke
* #return information about the method invoked
*/
<T> GetterInvocation<T> invokeGetter(Function<B, T> getter);
}
/**
* Stores information about a method invocation.
* #param <T> method return type
*/
public interface GetterInvocation<T> {
public Class<T> getReturnType();
public String getFieldName();
}
/**
* A builder class to create {#link Mapper} instances.
* #param <FROM> source type
* #param <TO> target type
*/
public class MapperBuilder<FROM, TO> {
private final Class<FROM> _fromClass;
private final Class<TO> _toClass;
private final PojoProxy<FROM> _fromProxy;
private final PojoProxy<TO> _toProxy;
public MapperBuilder(Class<FROM> fromClass, Class<TO> toClass) {
_fromClass = fromClass;
_toClass = toClass;
//We will pretend there is an impl that provides the proxy.
//Proxies wrap the from and to classes in order to get reflection information about their getter calls.
_fromProxy = PojoProxy.of(fromClass);
_toProxy = PojoProxy.of(toClass);
}
public <FROM_VALUE> ToFieldBuilder<FROM_VALUE> from(Function<FROM, FROM_VALUE> getter) {
GetterInvocation<FROM_VALUE> methodInvocation = _fromProxy.invokeGetter(getter);
return new ToFieldBuilder<>(methodInvocation.getFieldName(), methodInvocation.getReturnType());
}
public class ToFieldBuilder<FROM_VALUE> {
private final String _fromFieldPath;
private final Class<FROM_VALUE> _fromClass;
public ToFieldBuilder(String fromFieldPath, Class<FROM_VALUE> fromClass) {
_fromFieldPath = fromFieldPath;
_fromClass = fromClass;
}
public <TO_VALUE> FromFieldBuilder<FROM_VALUE, TO_VALUE> to(Function<TO, TO_VALUE> getter) {
//similar to above, but now using a FromFieldBuilder.
}
}
public class FromFieldBuilder<FROM_VALUE, TO_VALUE> {
//impl..
}
}
I dont see MapperBuilder.from() method details, you can try this implementation of MapperBuilder.java Function (getter) -> (BiConsumer) setter
public class MapperBuilder<S, D> {
private final S src;
private final D dest;
public MapperBuilder(S src, Class<D> dest) {
this.src = src;
try {
this.dest = dest.newInstance();
} catch (Exception e) {
throw new RuntimeException("Required default constructor for: " + dest);
}
}
//getter - function to get value from source instance
//setter - biConsumer to set value to destination instance
//example - map(SrcClass::getSrcValue, DestClass::setDestValue)
public <V> MapperBuilder<S, D> map(Function<S, V> getter, BiConsumer<D, V> setter) {
setter.accept(dest, getter.apply(src));
return this;
}
public D build() {
return dest;
}
}
SrcClass.java some source class:
public class SrcClass {
private String srcValue;
public String getSrcValue() {
return srcValue;
}
public void setSrcValue(String srcValue) {
this.srcValue = srcValue;
}
}
DestClass.java some destination class:
package com.example.demo;
public class DestClass {
private String destValue;
public String getDestValue() {
return destValue;
}
public void setDestValue(String destValue) {
this.destValue = destValue;
}
}
DemoApplication.java demo:
public class DemoApplication {
public static void main(String[] args) {
SrcClass src = new SrcClass();
src.setSrcValue("someValue");
DestClass dest = new MapperBuilder<>(src, DestClass.class)
.map(SrcClass::getSrcValue, DestClass::setDestValue)
// map another fields
.build();
// for your UnsecureObject case
UnsecureObject unsecureObject = new MapperBuilder<>(src, UnsecureObject.class)
.map(SrcClass::getSrcValue,
(unsecure, srcValue) -> unsecure.unsecureValue = srcValue)
.build();
}
}

Weld: Generic factory for many service-interfaces extending common super-interface

How can I create a single common factory for hundreds of service-interfaces?
I have a common generic super-interface, which all my service-interfaces extend: BaseDao<T>
There are hundreds of (generated) interfaces sub-classing my BaseDao, e.g. CustomerDao extends BaseDao<Customer>. Of course, I do not want to implement a single factory for every sub-class. Especially, because there is already a DaoFactory, which I need to "glue" into my Weld-environment.
Hence, I implemented this:
#ApplicationScoped
public class InjectingDaoFactory {
#SuppressWarnings("rawtypes") // We *MUST* *NOT* declare a wild-card -- Weld does not accept it => omit the type argument completely.
#Produces
public BaseDao getDao(final InjectionPoint injectionPoint) {
final Type type = injectionPoint.getType();
// ... some checks and helpful exceptions ...
final Class<?> c = (Class<?>) type;
// ... more checks and helpful exceptions ...
#SuppressWarnings("unchecked")
final Class<BaseDao<?>> clazz = (Class<BaseDao<?>>) c;
final BaseDao<?> dao = DaoFactory.getDao(clazz);
return dao;
}
}
In the code requiring such a DAO, I now tried this:
#Inject
private CustomerDao customerDao;
But I get the error org.jboss.weld.exceptions.DeploymentException: WELD-001408: Unsatisfied dependencies for type CustomerDao with qualifiers #Default -- Weld does not understand that my InjectingDaoFactory is capable of providing the correct sub-class to meet the dependency on CustomerDao.
Please note that I (of course) did not have the chance to debug the code of my factory. Maybe I need to use InjectionPoint.getMember() instead of InjectionPoint.getType() -- this is not my problem, now. My problem is that the responsibility of my factory for the sub-interfaces extending BaseDao is not understood by Weld at all.
So, what do I need to do to make Weld understand that one single factory can provide all the implementations of the many sub-interfaces of my BaseDao common DAO-interface?
According to this documentation, I created the following extension, which seems to work fine:
public class InjectingDaoExtension implements Extension {
public InjectingDaoExtension() {
}
private final Set<Class<? extends BaseDao>> injectedDaoInterfaces = new HashSet<>();
public <T> void processInjectionTarget(#Observes ProcessInjectionTarget<T> pit, BeanManager beanManager) {
final InjectionTarget<T> it = pit.getInjectionTarget();
for (InjectionPoint injectionPoint : it.getInjectionPoints()) {
Field field = null;
try {
Member member = injectionPoint.getMember();
field = member.getDeclaringClass().getDeclaredField(member.getName());
} catch (Exception e) {
// ignore
}
if (field != null) {
Class<?> type = field.getType();
if (BaseDao.class.isAssignableFrom(type)) {
if (! type.isInterface()) {
pit.addDefinitionError(new IllegalStateException(String.format("%s is not an interface! Cannot inject: %s", type, field)));
}
#SuppressWarnings("unchecked")
Class<? extends BaseDao> c = (Class<? extends BaseDao>) type;
injectedDaoInterfaces.add(c);
} else {
field = null;
}
}
}
}
public void afterBeanDiscovery(#Observes AfterBeanDiscovery abd, BeanManager beanManager) {
for (Class<? extends BaseDao> daoInterface : injectedDaoInterfaces) {
abd.addBean(createBean(daoInterface, beanManager));
}
}
protected <D extends BaseDao> Bean<D> createBean(final Class<D> daoInterface, final BeanManager beanManager) {
return new Bean<D>() {
private InjectionTarget<D> injectionTarget;
public synchronized InjectionTarget<D> getInjectionTargetOrNull() {
return injectionTarget;
}
public synchronized InjectionTarget<D> getInjectionTarget() {
if (injectionTarget == null) {
D handler = DaoFactory.getDao(daoInterface);
#SuppressWarnings("unchecked")
Class<D> handlerClass = (Class<D>) handler.getClass();
final AnnotatedType<D> at = beanManager.createAnnotatedType(handlerClass);
injectionTarget = beanManager.createInjectionTarget(at);
}
return injectionTarget;
}
#Override
public Class<?> getBeanClass() {
return daoInterface;
}
#Override
public Set<InjectionPoint> getInjectionPoints() {
// The underlying DaoFactory is not yet initialised, when this method is first called!
// Hence we do not use getInjectionTarget(), but getInjectionTargetOrNull(). Maybe this
// causes problems with injections inside the DAOs, but so far, they don't use injection
// and it does not matter. Additionally, they are RequestScoped and therefore the injection
// later *may* work fine. Cannot and do not need to test this now. Marco :-)
InjectionTarget<D> it = getInjectionTargetOrNull();
return it == null ? Collections.emptySet() : it.getInjectionPoints();
}
#Override
public String getName() {
return getBeanClass().getSimpleName();
}
#Override
public Set<Annotation> getQualifiers() {
Set<Annotation> qualifiers = new HashSet<Annotation>();
qualifiers.add(new AnnotationLiteral<Default>() {});
qualifiers.add(new AnnotationLiteral<Any>() {});
return qualifiers;
}
#Override
public Class<? extends Annotation> getScope() {
return RequestScoped.class;
}
#Override
public Set<Class<? extends Annotation>> getStereotypes() {
return Collections.emptySet();
}
#Override
public Set<Type> getTypes() {
Set<Type> types = new HashSet<>();
types.add(daoInterface); // TODO add more types?!
return types;
}
#Override
public D create(CreationalContext<D> creationalContext) {
D handler = DaoFactory.getDao(daoInterface);
InjectionTarget<D> it = getInjectionTarget();
it.inject(handler, creationalContext);
it.postConstruct(handler);
return handler;
}
#Override
public void destroy(D instance, CreationalContext<D> creationalContext) {
InjectionTarget<D> it = getInjectionTarget();
it.preDestroy(instance);
it.dispose(instance);
creationalContext.release();
}
#Override
public boolean isAlternative() {
return false;
}
#Override
public boolean isNullable() {
return false;
}
};
}
}
The idea is that it first collects all sub-interfaces of BaseDao that need to be injected. Then, it provides the factory for each of them.
Important: As already stated in the comments, it is necessary to put this extension in a separate JAR, which does not provide any services. As soon as I placed a class implementing Extension in the same JAR as a service implementation (e.g. published via #RequestScoped), the service was not found, anymore.

Java casting interface but using object methods

I have a question on how to call an objects base member when instantiated through an interface.
Suppose I have the following interface and concrete classes in a framework I am trying to build:
public interface UsedClass {
public boolean getBool();
}
public class User implements UsedClass {
private String userName;
private String userRole;
public User(String userName, String userRole){
this.userName = userName;
this.userRole = userRole;
}
public boolean getBool() {
// some code
}
public int getUserName() {
return userName;
}
public int getUserRole() {
return userRole;
}
And an implementing class:
public class Run implements UsedClass {
private String runName;
private int runNumber;
public Run(String runName, int runNumber){
this.runName = runName;
this.runNumber = runNumber;
}
public boolean getBool() {
// some code
}
public String getRunName() {
return runName;
}
public int getRunNumber() {
return runNumber;
}
}
But I cannot put methods getRunName() or getUserRole() into the interface!
The end goal is to create a FactoryClass to handle the objects passed from a database GUI.
I would like to know if there is a better way then using class reference be able to safely call methods of Run or User such as:
public class EntityFactory {
public static Object getValueAt(int rowIndex, int columnIndex, UsedClass usedClass) {
if (usedClass.getClass().getSimpleName().equals("User")) {
switch (columnIndex) {
case 0:
return ((User) usedClass).getUserName();
case 1:
return ((User) usedClass).getUserRole();
default:
return null;
}
} else if (usedClass.getClass().getSimpleName().equals("Run")) {
switch (columnIndex) {
case 0:
return ((Run) usedClass).getRunName();
case 1:
return ((Run) usedClass).getRunNumber();
default:
return null;
}
}
I have read several SO posts
type casting when objects are of interface references in Java and Java cast interface to class
where it is implied that reference casting is not advised, but since I cannot put all methods into the interface, what would be advised?
static interface ColumnSource<T> {
String getColumn(T value, int index);
}
static Map<Class, ColumnSource> map = new HashMap();
static {
map.put(User.class, new UserNameAndRoleSource<User>() {
public String getColumn(User user, int index) {
switch (index) {
case 0: return user.getUserName();
case 1: return user.getUserRole();
default: throw new RuntimeException();
}
}
});
map.put(Run.class, new ColumnSource<Run>() {
public String getColumn(Run run, int index) {
switch (index) {
case 0: return run.getRunName();
case 1: return run.getRunNumer();
default: throw new RuntimeException();
}
}
});
}
public static Object getValueAt(int rowIndex, int columnIndex, Object o) {
Class type = o.getClass();
ColumnSource source = map.get(type);
if (source == null) throw new RuntimeException(type.getName() + " not supported");
return source.getColumn(o, columnIndex);
}
You should use instanceof rather than looking at the simpleName of the class.
Beyond that you are correct. You either need to have an interface containing the common methods which you can then call them in or you need to identify that the object is an instance of a specific class and then do the cast and make the method call.
You could consider using a Map<Class<? extends UsedClass>, Map<Integer, Function<___>>> handlers.
Then your processing would be
handlers.get(usedClass.getClass()).get(columnIndex).apply(usedClass);
Obviously you would want to consider how to handle the unexpected class/index case. The inner Map<Integer,... could potentially be a List<...> depending on how it is being used.
Two things:
if at all, you use instanceof instead of string / class name comparison
you build your interfaces / classes to be helpful. They are the base of all the things you are doing. If you start with broken abstractions, you are broken. Simple as that.
What I mean is: if there is "common" behavior; then you should express that using a common interface. If not, you start your efforts on an already broken base; and you will be need to create "creative workarounds" all over the place in order to fight the symptoms of that disease.
Maybe one small solution could be to have at least multiple interfaces, like
interface UsedClass { ...
interface SpecialUsedClassA extends UsedClass { ...
interface SpecialUsedClassB extends UsedClass { ...
than you can at least return UsedClass instead of Object.

Generic static factory

I am getting a compilation error. I want my static method here to return a factory that creates and return Event<T> object. How can I fix this?
import com.lmax.disruptor.EventFactory;
public final class Event<T> {
private T event;
public T getEvent() {
return event;
}
public void setEvent(final T event) {
this.event = event;
}
public final static EventFactory<Event<T>> EVENT_FACTORY = new EventFactory<Event<T>>() {
public Event<T> newInstance() {
return new Event<T>();
}
};
}
Generic parameters of a class do not apply to static members.
The obvious solution is to use a method rather than a variable.
public static <U> EventFactory<Event<U>> factory() {
return new EventFactory<Event<U>>() {
public Event<U> newInstance() {
return new Event<U>();
}
};
}
The syntax is more concise in the current version of Java.
It is possible to use a the same instance of EventFactory stored in a static field, but that requires an unsafe cast.
You have:
public final class Event<T> {
...
public final static EventFactory<Event<T>> EVENT_FACTORY = ...
}
You cannot do this. T is a type that is associated with a specific instance of an Event<T>, and you cannot use it in a static context.
It's hard to give you good alternate options without knowing more about what exactly you are trying to do, as this is sort of an odd-looking factory implementation. I suppose you could do something like (put it in a method instead):
public final class Event<T> {
...
public static <U> EventFactory<Event<U>> createEventFactory () {
return new EventFactory<Event<U>>() {
public Event<U> newInstance() {
return new Event<U>();
}
};
};
}
And invoke it like:
EventFactory<Event<Integer>> factory = Event.<Integer>createEventFactory();
Or, if you don't want to be explicit (you don't really need to be, here):
EventFactory<Event<Integer>> factory = Event.createEventFactory();
Why don't you get rid of the whole static member of Event thing and either keep the factories separate, e.g.:
public final class GenericEventFactory<T> extends EventFactory<Event<T>> {
#Override public Event<T> newInstance() {
return new Event<T>();
}
}
And use, e.g., new GenericEventFactory<Integer>() where appropriate?

Categories

Resources