Pattern to force consuming of queue - java

Currently I have a method to consume events of a Queue. Based on the type I call the appropriate method to handle it.
private void consumeQueue() {
MyQueue myQueue = MyQueue.getInstance();
Iterator mIterator = myQueue.iterator();
while (mIterator.hasNext()) {
Object mEvent = null;
try {
mEvent = mIterator.next();
mIterator.remove();
} catch (NoSuchElementException e) {
return;
}
if (mEvent instanceof EventOne)
handleOne((EventOne) mEvent);
else if (mEvent instanceof EventTwo)
handleTwo((EventTwo) mEvent);
...
}
}
Let's suppose that elsewhere the developer enqueue a new type of event, let's call it EventThree. Doing it in this way I can't be sure that the developer will handle EventThree's consumption properly.
Is there any pattern so I can force (at compile time) the developer, to handle EventThree's consumption?

As far as I understand your MyQueue class implements Queue interfance. You should never use raw types in your code. Consider using your MyQueue as a generic class with some type parameter:
MyQueue<EventOne> myQueue = MyQueue.getInstance();
Ofc you'll have to change getInstance() method too. An elegant solution may look like:
<T> MyQueue<T> getInstance(Class<T> clazz) {
if (clazz == EventOne.class) {
// ...
} else if (clazz == EventTwo.class) {
// ...
}
}
P.S. Unfortunately you can't define two getInstance() methods with different Queue type parameter because of Java's type erasure.

Related

Use enum to create thead-safe factory instances

I write the code for creating multiple instances for the thread-safe factory creation:
public class XWebserviceObjectFactoryCreator {
}
However, the code looks repeating to me and not happy about it. Is it possible to use enum (or something else) to make it more readable?
Since the example shows all the classes have no-argument constructors, you can use the Class.newInstance method, so something like :
private static Map<Class<?>, Object> instances = new HashMap<>();
public static <T extends Object> T getObjectFactoryInstance(Class<T> clazz) {
Object result;
if ((result = instances.get(clazz)) == null) {
synchronized (instances) {
if ((result = instances.get(clazz)) == null) {
try {
result = clazz.newInstance();
instances.put(clazz, result)
} catch (InstantiationException | IllegalAccessException e) {
// do something
}
}
}
}
return (T)result;
}
Apologies if layout or syntax is off, but I’m away from my computer and doing this on the phone - but hope you get the idea !
If any classes do require arguments in their constructors, then you’ll have to use reflection to invoke the constructor.
Finally, note that I’ve modified the declaration of clazz from Class<?> to Class< T>, to let the generics validate the caller by tying the output to the given Class.
you can use the Abstract Factory design Pattern along with Enum where Sales2ObjectFactory, OrderingObjectFactory, Settings2ObjectFactory, and SettingsObjectFactory can be a factory in itself with a common interface.
Then you can use Enum to get the instance of one of those factories.
public static class FactoryMaker {
public enum FactoryType {
SALES2OBJECT, ORDERING,SETTING2OBJECT,SETTINGS
}
public static CommonFactory makeFactory(FactoryType type) {
switch (type) {
case SALES2OBJECT:
return new Sales2ObjectFactory();
case ORDERING:
return new OrderingObjectFactory();
case SETTING2OBJECT:
return new Settings2ObjectFactory();
case SETTINGS:
return new new SettingsObjectFactory();
default:
throw new IllegalArgumentException("FactoryType not supported.");
}
}
}
Please check :: https://java-design-patterns.com/patterns/abstract-factory/

Call method of unknown object

I have two ArrayLists - ArrayList1 and ArrayList2. Each of them is filled with objects - Object1 and Object2, respectively.
Both of these objects have method 'getText'.
Object1:
public String getText() { return "1";}
Object2:
public String getText() { return "2";}
At certain point I would like to loop through each of these lists using the same method (just with different parameter).
loopThroughList(1)
loopThroughList(2)
What is the syntax if I want to call a method, but I don't know which object it is going to be? This is the code I have so far:
for (Object o : lists.getList(listNumber)) {
System.out.println(o.getText());
}
It says Cannot resolve method getText. I googled around and found another solution:
for (Object o : lists.getList(listNumber)) {
System.out.println(o.getClass().getMethod("getText"));
}
But this gives me NoSuchMethodException error. Even though the 'getText' method is public.
EDIT: To get the correct list, I am calling the method 'getList' of a different object (lists) that returns either ArrayList1 or ArrayList2 (depending on the provided parameter).
class Lists
public getList(list) {
if (list == 1) {
return ArrayList1;
}
else if (list == 2) {
return ArrayList2;
}
}
Define an interface for the getText method
public interface YourInterface {
String getText();
}
Implement the interface on the respective classes
public class Object1 implements YourInterface {
#Override
public String getText() {
return "1";
}
}
public class Object2 implements YourInterface {
#Override
public String getText() {
return "2";
}
}
Modify your getList method to return List<YourInterface>
public static List<YourInterface> getList(int list){
List<YourInterface> result = new ArrayList<>();
if(list == 1){
// your initial type
List<Object1> firstList = new ArrayList<>();
result.addAll(firstList);
} else {
// your initial type
List<Object2> secondList = new ArrayList<>();
result.addAll(secondList);
}
return result;
}
Declaration for loopThroughList
public static void loopThroughList(List<YourInterface> list){
list.forEach(yourInterface -> System.out.println(yourInterface.getText()));
}
Sample usage.
public static void main(String[] args) {
loopThroughList(getList(1));
loopThroughList(getList(2));
}
Interfaces work great here, but there a couple of other options if you're dealing with legacy code and cannot use interfaces.
First would be to cast the list items into their respective types:
for (Object o : lists.getList(listNumber)) {
if(o instanceof Object1) {
Object1 o1 = (Object1)o;
System.out.println(o1.getText());
}
else if(o instanceof Object2) {
Object1 o2 = (Object2)o;
System.out.println(o2.getText());
}
else {
System.out.println("Unknown class");
}
}
You can also use reflection to see if the object has a getText method and then invoke it:
for (Object o : lists.getList(listNumber)) {
try {
System.out.println(o.getClass().getDeclaredMethod("getName").invoke(o));
}
catch(Exception e) {
System.out.println("Object doesn't have getText method");
}
}
This is awful. Can you elaborate on what specifically you are trying to do? Java is strong typed by design, and you are trying to get around it. Why? Instead of Object, use the specific class, or interface as previously suggested. If that's not possible, and you must use lists of Objects, use instanceof and casting eg:
for (Object o : lists.getList(listNumber)) {
if (o instanceof Object1) {
Object1 o1 = (Object1) o;
System.out.println(o1.getText());
} else if (o instanceof Object2) {
Object2 o2 = (Object2) o;
System.out.println(o2.getText());
}
}
This is where interfaces come in.
interface HasText {
public String getText();
}
class Object1 implements HasText {
#Override
public String getText() {
return "1";
}
}
class Object2 implements HasText {
#Override
public String getText() {
return "2";
}
}
private void test() {
List<HasText> list = Arrays.asList(new Object1(), new Object2());
for (HasText ht : list) {
System.out.println(ht);
}
}
If one of your objects is not in your control you can use a Wrapper class.
class Object3DoesNotImplementHasText {
public String getText() {
return "3";
}
}
class Object3Wrapper implements HasText{
final Object3DoesNotImplementHasText it;
public Object3Wrapper(Object3DoesNotImplementHasText it) {
this.it = it;
}
#Override
public String getText() {
return it.getText();
}
}
private void test() {
List<HasText> list = Arrays.asList(new Object1(), new Object2(), new Object3Wrapper(new Object3DoesNotImplementHasText()));
for (HasText ht : list) {
System.out.println(ht);
}
}
Just to add more to this answer and give you some more to think on this (Will try to do it in a simple, non-formal way). Using interfaces is the proper way of doing such operation. However, I want to stand on the "bad idea":
for (Object o : lists.getList(listNumber)) {
System.out.println(o.getClass().getMethod("getText"));
}
What you are doing here, is using a mechanism called Reflection:
Reflection is a feature in the Java programming language. It allows an
executing Java program to examine or "introspect" upon itself, and
manipulate internal properties of the program. For example, it's
possible for a Java class to obtain the names of all its members and
display them.
What you actually attempted, is using that mechanism, to retrieve the method through a Class reflection object instance of your Class (sounds weird, isn't it?).
From that perspective, you need to think that, if you want to invoke your method, you now have, in a sense, a meta-Class instance to manipulate your objects. Think of it like an Object that is one step above your Objects (Similarly to a dream inside a dream, in Inception). In that sense, you need to retrieve the method, and then invoke it in a different (meta-like) way:
java.lang.reflect.Method m = o.getClass().getMethod("getText");
m.invoke(o);
Using that logic, you could possibly iterate through the object list, check if method exists, then invoke your method.
This is though a bad, BAD idea.
Why? Well, the answer relies on reflection itself: reflection is directly associated with runtime - i.e. when the program executes, practically doing all things at runtime, bypassing the compilation world.
In other words, by doing this, you are bypassing the compilation error mechanism of Java, allowing such errors happen in runtime. This can lead to unstable behavior of the program while executing - apart from the performance overhead using Reflection, which will not analyze here.
Side note: While using reflection will require the usage of Checked Exception handling, it still is not a good idea of doing this - as you practically try to duck tape a bad solution.
On the other hand, you can follow the Inheritance mechanism of Java through Classes and Interfaces - define an interface with your method (let's call it Textable), make sure that your classes implement it, and then use it as your base object in your list declaration (#alexrolea has implemented this in his answer, as also #OldCurmudgeon has).
This way, your program will still make the method call decision making at Runtime (via a mechanism called late binding), but you will not bypass the compilation error mechanism of Java. Think about it: what would happen if you define a Textable implementation without providing the class - a compile error! And what if you set a non-Textable object into the list of Textables? Guess what! A compile error again. And the list goes on....
In general, avoid using Reflection when you are able to do so. Reflection is useful in some cases that you need to handle your program in such a meta-way and there is no other way of making such things. This is not the case though.
UPDATE: As suggested by some answers, you can use instanceof to check if you have a specific Class object instance that contains your method, then invoke respectively. While this seems a simple solution, it is bad in terms of scaling: what if you have 1000 different classes that implement the same method you want to call?
your objects have to implement a common interface.
interface GetTextable {
String getText();
}
class One implements GetTextable {
private final String text;
public One(final String text) {
this.text = text;
}
public String getText() {
return this.text;
}
}
class Two implements GetTextable {
private final String text;
public Two(final String text) {
this.text = text;
}
public String getText() {
return this.text;
}
}
#Test
public void shouldIterate() throws Exception {
List<GetTextable> toIterate = Arrays.asList(new One("oneText"), new Two("twoText"));
for(GetTextable obj: toIterate) {
System.out.println(obj.getText());
}
}

Proper way to process different types of unmarshalled XML objects in Java

I'm currently working on a Java application which receives XML messages through sockets. There are different types of XML messages and I'm now looking for the most elegant way/best practice to properly dispatch and handle those.
Currently I have a working test setup with a general Dispatch class containing a process method which receives the already parsed message. For each of these types I then have a specific process method. Works for testing connections etc but not so pretty.
public class Dispatch
public Object process(XMLMessage xml){
Object obj = xml.getXml();
if (obj instanceof AccessCheck)
return processObject((AccessCheck) obj);
else if (obj instanceof Note)
return processObject((Note) obj);
else if (obj instanceof Login)
return processObject((Login) obj);
...
return null;
}
}
Since the ultimate solution contains more message types and should also contain a database connection and cache, I'm looking for a way to group the handling of messages per domain and preferably also eliminate or reduce this large if-statement with explicit casts.
I thought about doing it like this with a facade per domain (which would also allow for a separate cache per domain):
public class Dispatch
public Object process(XMLMessage xml){
Object obj = xml.getXml();
if (obj instanceof AccessCheck)
return AuthorizationDataFacade.process((AccessCheck) obj);
else if (obj instanceof Note)
return SomeOtherDataFacade.process((Note) obj);
else if (obj instanceof Login)
return AuthorizationDataFacade.process((Login) obj);
...
return null;
}
}
public class AuthorizationDataFacade {
public Object processAccessCheck(AccessCheck check){
//do something and return the response
return null;
}
public Object processLogin(Login login){
//do something and return the response
return null;
}
But is there a way to eliminate that large if statement with explicit casts? Or should I rethink my XSD/XML design and merge some messages together (ie. merge AccessCheck and Login into a general Authorization xml)? Any thoughts?
One possible solution is with reflection.
The solution presented here assumes the following
a Processor can handle multiple xml message types (e.g. AuthorizationDataFacade handles AccessCheck and Login messages)
a convention for process methods is enforced: it must be named "process", have one arg that is of type of one xml message and have a known return type. this convention is used in searching for the right process method for a given type of xml msg.
When you need to process a new xml msg, you write its process() method according to the convention (in any class you see fit) and add an entry to the dispatchMap. that's it.
The solution is specified below, I added some comments to clarify things:
import java.lang.reflect.*;
import java.util.*;
public class Dispatcher
{
// the map associates xml msg type to processor type
private static Map<Class<?>, Class<?>> dispatchMap = new HashMap<>();
static
{
dispatchMap.put(AccessCheck.class, AuthorizationDataFacade.class);
dispatchMap.put(Login.class, AuthorizationDataFacade.class);
dispatchMap.put(Note.class, SomeOtherDataFacade.class);
}
public String dispatch(Object obj)
{
Class<?> xmlMsgType = obj.getClass();
// search for xml msg type in dispatch map
if (!dispatchMap.containsKey(xmlMsgType)) {
return "unrecognized message type";
}
// found match, now locate process method
try {
Class<?> ProcessorType = dispatchMap.get(xmlMsgType);
Method[] processorTypeMethods = ProcessorType.getDeclaredMethods();
Method chosenProcssMethod =
Arrays.stream(processorTypeMethods)
.filter(m -> methodFitForXmlMsg(m, xmlMsgType))
.findFirst()
.orElse(null);
if (chosenProcssMethod != null) {
// found match, instantiate processor and invoke method
Object processorInstance = ProcessorType.newInstance();
return (String)chosenProcssMethod.invoke(
processorInstance,
chosenProcssMethod.getParameterTypes()[0].cast(obj));
}
} catch (ReflectiveOperationException e) {
e.printStackTrace();
}
// no match found or error
return "error";
}
// a method is dimmed fit for processing a given xml msg type
// if it is named "process", returns a String, has one arg that is of the given type
private boolean methodFitForXmlMsg(Method m, Class<?> xmlMsgType)
{
return m.getName().equals("process") &&
m.getReturnType() == String.class &&
m.getParameterCount() == 1 &&
m.getParameterTypes()[0].equals(xmlMsgType);
}
public static void main(String... args)
{
Dispatcher d = new Dispatcher();
System.out.println(d.dispatch(new AccessCheck()));
System.out.println(d.dispatch(new Login()));
System.out.println(d.dispatch(new Note()));
System.out.println(d.dispatch("something else"));
}
}

Is Reflection needed to apply the correct generic adapter to my object dynamically

I am currently working on a serialization routine which uses a library of generically typed adapters. If the object being serialized is an instance of one of the specific adapters I have, then I need to call that adapter on the object prior to performing my other serialization procedures.
The following code works:
private final static String serialize(Object obj, Map<Class<?>,
XmlAdapter<?,?>> classToAdapterMap) throws JAXBException
{
Object adaptedObj = null;
for (Class<?> clazz : classToAdapterMap.keySet()) {
if (clazz.isInstance(obj)) {
XmlAdapter<?,?> adapter = classToAdapterMap.get(clazz);
Class<?>[] argTypes = new Class[] {clazz};
try {
Method method = adapter.getClass().getMethod("marshal", argTypes);
adaptedObj = method.invoke(adapter, obj);
break;
} catch (Exception e) {
// handle method retrieval and invocation related exceptions
}
}
}
// serialize
}
However, I had originally thought that I would be able to do this more simply, for example with code like:
/* DOES NOT WORK */
private final static String serialize(Object obj, Map<Class<?>,
XmlAdapter<?,?>> classToAdapterMap) throws JAXBException
{
Object adaptedObj = null;
for (Class<?> clazz : classToAdapterMap.keySet()) {
if (clazz.isInstance(obj)) {
XmlAdapter<?,?> adapter = classToAdapterMap.get(clazz);
adaptedObj = adapter.marshal(clazz.cast(obj));
break;
}
}
// serialize
}
Clearly the problem is that the wildcard generically typed adapter isn't guaranteed to handle an object of type clazz. However, I can't indicate that these two are the same by changing the method signature—as I might otherwise do—to private final static <T> String serialize(Object obj, Map<Class<T>, XmlAdapter<?,T>> classToAdapterMap), because the map needs to hold adapters of all different types.
What would be a better way to do this? Or should I stick with the Reflection based solution?
Thanks in advance,
-Dan
There are several solutions to circumvent this problem.
Most likely, the easiest one is using raw types: don't specify the type parameters for the adapter, and the compiler will happily accept the marshall call (with a raw type warning of course):
XmlAdapter adapter = classToAdapterMap.get(clazz);
adaptedObj = adapter.marshal(obj);
(This is actually roughly the same solution as Bastian's, without the intermediate type)
If you don't like raw types, you may choose the unchecked cast to an Object-parameterized adapter. It's not really better, but it also works (by tricking the compiler…):
XmlAdapter<?, Object> adapter = (XmlAdapter<?, Object>) classToAdapterMap.get(clazz);
adaptedObj = adapter.marshal(obj);
My last solution is to use a type parameter at the method level. This time, what you do is semantically correct (as long as the map itself is correct), and the unchecked cast really means “I know what I am doing here”:
private final static <T> String serialize(T obj, Map<Class<?>,
XmlAdapter<?,?>> classToAdapterMap) throws JAXBException
{
Object adaptedObj = null;
for (Class<?> clazz : classToAdapterMap.keySet()) {
if (clazz.isInstance(obj)) {
try {
XmlAdapter<?, ? super T> adapter = (XmlAdapter<?, ? super T>) classToAdapterMap.get(clazz);
adaptedObj = adapter.marshal(obj);
break;
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
// serialize
}
The semantic correctness comes from the following:
you may consider T to be the actual class of obj since T is a method-bound parameter, not used elsewhere in the signature;
clazz is a super type of the type of T since we checked clazz.isInstance(obj);
adapter can handle instances of clazz or a super-type of it since it is how the map was built;
by consequent, adapter can handle all instances of an (unknown) super type of T, hence the ? super T declaration.
There is a simpler and safer way without using reflection:
At first, we need a small specialization of the XmlAdapter as it allows us to ask the adapter for the type it can handle.
public abstract class TalkingXmlAdapter<ValueType, BoundType> extends XmlAdapter<ValueType, BoundType> {
public abstract Class<BoundType> getBoundType();
}
My custom adapters now need to extend TalkingXmlAdapter:
public class AppleXmlAdapter extends TalkingXmlAdapter<String, Apple> {
#Override
public Class<Apple> getBoundType() {
return Apple.class;
}
#Override
public Apple unmarshal(String v) throws Exception {
System.out.println("Unmarshalling Apple");
return new Apple();
}
#Override
public String marshal(Apple v) throws Exception {
System.out.println("Marshalling Apple");
return "Apple";
}
}
public class BananaXmlAdapter extends TalkingXmlAdapter<String, Banana> {
#Override
public Class<Banana> getBoundType() {
return Banana.class;
}
#Override
public Banana unmarshal(String v) throws Exception {
System.out.println("Unmarshalling Banana");
return new Banana();
}
#Override
public String marshal(Banana v) throws Exception {
System.out.println("Marshalling Banana");
return "Banana";
}
}
That allows us to write a simplified serialization method:
public class SimpleSerializer {
public static final String serialize(Object obj, List<TalkingXmlAdapter> allAdapters) throws Exception {
Object adaptedObj = null;
for (TalkingXmlAdapter adapter : allAdapters) {
if (adapter.getBoundType().isInstance(obj)) {
adaptedObj = adapter.marshal(obj);
break;
}
}
// serialize
System.out.println("Simple serializing for " + obj.toString());
return "Simply serialized " + obj.toString();
}
}
Using the code e.g. like in the subsequent listing shows the behavior you want:
List<TalkingXmlAdapter> allAdapters = new ArrayList<>();
allAdapters.add(new AppleXmlAdapter());
allAdapters.add(new BananaXmlAdapter());
SimpleSerializer.serialize(new Banana(), allAdapters);
SimpleSerializer.serialize("Lemmon", allAdapters);
SimpleSerializer.serialize(new Apple(), allAdapters);
Output:
Marshalling Banana
Simple serializing for generic.adapter.Banana#659e0bfd
Simple serializing for Lemmon
Marshalling Apple
Simple serializing for generic.adapter.Apple#2a139a55
To sum this up, the solution gives you following advantages:
You don't need reflection which simplifies your code.
You need fewer generic programming in your serialization routine which simplifies your code.
The solution is more safe. Note that no type cast is needed. Every adapter accepts the type Object. However by using the generic method getBoundType() you can ensure the specific runtime type is the correct one. When building your map as in the reflection solution, a wrongly mapped class results in a runtime exception. In the proposed solution the super class TalkingXmlAdapter enforces each adapter to state their correct type by using generics.
The price you pay is:
Introduction of a new super type.
Requires small adaptions for your custom adapters.
Hope that helps!

Superclass of String (or T) and Enum

I have some small logging system and it can process Strings, which is all working fine.
Now I want to add the ability to signal that I want a new line, and due to my structure I think it is best to use a special flag, some example code:
public class BaseLogger implements Runnable, LogConsumer {
//....
private final BlockingQueue<String> queue;
//....
#Override
public void run() {
while (running) {
try {
if (consumers.isEmpty()) {
synchronized(consumersEmptyLock) {
consumersEmptyLock.wait();
}
}
String message = queue.take();
for (LogConsumer consumer : consumers) {
consumer.consume(message);
}
} catch (InterruptedException ex) {
handleInterrupt();
}
if (requestShutdown && queue.isEmpty()) {
running = false;
}
}
}
public void log(String message) {
if (message == null) {
throw new IllegalArgumentException("customlogger.CustomLogger.log: message == null");
}
queue.offer(message);
}
So now I want to add an enum, let's say LogFlagEnum, which includes a flag called NEW_LINE.
However currently my queue is of type String, and I would like it to include both String (or perhaps T for a more general answer) and LogFlagEnum.
I know I could use Object as type, but that is not the smallest possible type and definatey not safe and what I want.
What would be the best way to implement the specified behaviour?
Solution 1: use Object. It's no big deal since it's just internal implementation.
Solution 2: use CharSequence; have the enum implement CharSequence. Not exactly very helpful. But in general CharSequence is better than String for accepting text arguments.
Solution 3: every problem in Java can be solved by introducing a new type. You queue can be a queue of LogEntry's, and LogEntry can contain String/enum/whatever.

Categories

Resources