Can I add a new child class at run time? - java

I need to add the following class at run time:
public class MapperFunction extends Mapper<Integer, String, String, Integer> {
public MapperFunction(InputBlock s) {
super(s);
}
#Override
protected void map(Integer key, String value) {
Pattern pattern = Pattern.compile("[a-zA-Z]+");
Matcher matcher;
String str = value;
if (!str.equals("")) {
matcher = pattern.matcher(str);
while (matcher.find()) {
String word = matcher.group();
if (!MapperOut.containsKey(word))
MapperOut.put(word, 1);
else
MapperOut.put(word, (Integer) MapperOut.get(word) + 1);
}
}
}
}
or add the method map() to class during run time. I read the following question on stackoverflow Extending or adding new classes at runtime in Java
but I think my case differs a bit, anyway this is the parent class Mapper:
public abstract class Mapper<keyIn, valueIn, keyOut, valueOut> implements Runnable {
private RecordReader recordReader;
static AtomicInteger numberOfThreadsPerMapper = new AtomicInteger(2);
static Map<Object, Object> MapperOut = null;
static {
MapperOut = Collections.synchronizedMap(new TreeMap<>());
}
Mapper(InputBlock s) {
recordReader = new LineRecordReader(s);
}
protected abstract void map(keyIn key, valueIn value) throws IOException, InterruptedException;
#Override
public void run() {
run2();
}
public void run2() {
try {
while (recordReader.hasNext()) {
map((keyIn) recordReader.getKey(), (valueIn) recordReader.getValue());
}
// System.out.println("Thread out." + numberOfThreads.getAndIncrement());
} catch (Exception e) {
// e.printStackTrace();
}
}
}
Note that the parent class Mapper extends Thread.
My second question: if I can do that how can I create instance from it? Now this my call to create:
#Override
public void update(Observable o, Object arg) {
executorService.submit(new MapperFunction((InputBlock) arg));
}
My last question: if all that can happen is there any disadvantage (performance issue) since the application creates more instances from MapperFunction class()?

Related

Unable to serialize instance variable of a non-serializable superclass from the serializable subclass

New to this topic and right now I'm stuck at a brick wall. I have 2 classes, parent class: Controller.java and subclass: GreenhouseControls.java. I need to serialize a GreenhouseControls object but also an instance variable (eventList) from its superclass Controller.java.
My serialization happens when an inner class of GreenhouseControls.java throws a custom ControllerException, which is caught in the main method. Before terminating the program, the GreenhouseControls object should be saved (including the field from its superclass).
Why is a NotSerializableException thrown by the inner class WindowMalfunction of GreenhouseControls? Anyone have any ideas, as I am seriously stuck?
What I tried is the following:
Implement serializable on Controller.java. This is because if the superclass is serializable, then subclass is automatically serializable, however this throws java.io.NotSerializableException: GreenhouseControls$WindowMalfunction, (WindowMalfunction is the inner class that throws the initial exception to begin the serialization processs).
Implement serializable on GreenhouseControls.java and implement custom serialization by overriding writeObject() and readObject() to save the field from the superclass. This approach yet again throws the same exception as the approach 1.
private void writeObject(ObjectOutputStream out) throws IOException {
out.defaultWriteObject();
out.writeObject(super.eventList);
}
private void readObject(ObjectInputStream in) throws IOException,
ClassNotFoundException {
in.defaultReadObject();
Object obj = in.readObject();
List<Event> x = cast(obj);
super.eventList = x;
}
Controller.java
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.*;
public class Controller {
// THIS IS THE VARIABLE I NEED TO SAVE
protected List<Event> eventList = new ArrayList<Event>();
public void addEvent(Event c) {
eventList.add(c);
}
public void run() throws ControllerException {
while (eventList.size() > 0)
// Make a copy so you're not modifying the list
// while you're selecting the elements in it:
for (Event e : new ArrayList<Event>(eventList))
if (e.ready()) {
System.out.println(e);
e.action();
eventList.remove(e);
}
}
public static void shutDown() { }
}
GreenhouseControls.java class (note I have removed the inner classes and other code from it and only left related info)
public class GreenhouseControls extends Controller implements Serializable {
private int errorcode = 0;
public class WindowMalfunction extends Event {
public WindowMalfunction(long delayTime) {
super(delayTime);
}
public void action() throws ControllerException {
windowok = false;
throw new ControllerException("Window malfunction");
}
public String toString() {
return "Window malfunction";
}
}
public class PowerOut extends Event {
public PowerOut(long delayTime) {
super(delayTime);
}
public void action() throws ControllerException {
poweron = false;
throw new ControllerException("Power out");
}
public String toString() {
return "Power out";
}
}
// Various other inner classes that extend event exist
public static void serializeObject(GreenhouseControls gc) {
FileOutputStream fileOut;
ObjectOutputStream out;
try {
fileOut = new FileOutputStream("dump.out");
out = new ObjectOutputStream(fileOut);
out.writeObject(gc);
System.out.println("WERRROR code: " + gc.getError());
out.close();
fileOut.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private void writeObject(ObjectOutputStream out) throws IOException {
out.defaultWriteObject();
out.writeObject(super.eventList);
}
private void readObject(ObjectInputStream in) throws IOException,
ClassNotFoundException {
in.defaultReadObject();
Object obj = in.readObject();
List<Event> x = cast(obj);
super.eventList = x;
}
#SuppressWarnings("unchecked")
public static <T extends List<?>> T cast(Object obj) {
return (T) obj;
}
public int getError() {
return errorcode;
}
public Fixable getFixable(int errorcode) {
switch (errorcode) {
case 1:
return new FixWindow();
case 2:
return new PowerOn();
default:
return null;
}
}
public static void main(String[] args) {
GreenhouseControls gc = null;
try {
String option = args[0];
String filename = args[1];
if (!(option.equals("-f")) && !(option.equals("-d"))) {
System.out.println("Invalid option");
printUsage();
}
// gc = new GreenhouseControls();
if (option.equals("-f")) {
gc = new GreenhouseControls();
gc.addEvent(gc.new Restart(0, filename));
}
gc.run();
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("Invalid number of parameters");
printUsage();
} catch (ControllerException e) {
String errormsg;
if (e.getMessage().equals("Window malfunction")) {
gc.errorcode = 1;
errormsg = "Window malfunction event occurred Error code: " + gc.errorcode;
} else {
gc.errorcode = 2;
errormsg = "Power out event occurred Error code: " + gc.errorcode;
}
logError(errormsg);
serializeObject(gc);
gc.displayEventList();
shutDown();
}
}
}
Event.java
public abstract class Event {
private long eventTime;
protected final long delayTime;
public Event(long delayTime) {
this.delayTime = delayTime;
start();
}
public void start() { // Allows restarting
eventTime = System.currentTimeMillis() + delayTime;
}
public boolean ready() {
return System.currentTimeMillis() >= eventTime;
}
public abstract void action() throws ControllerException;
Event has to be Serializable too.
Change
public abstract class Event {
to
public abstract class Event implements Serializable {

How do I create a event that fires up every time a new element is added to ArrayList

I want to create an method that fires up every time a new message is added to the groupchat arraylist.
Pseudo code:
public void listenForChange(){
while(true){
if(new message is added to the groupchat){
System.out.println(print the last added message);
}
}
}
What I have tried, but doesn't work:
public class Groupe{
ArrayList<String> groupechat;
int liveChange;
public void listenForChange() {
while(true){
if (groupchat.size() > liveChange){
liveChange= gruppenchat.size();
System.out.println(gruppenchat.get(liveChange-1));
}
}
}
Test class:
public class testGruppen extends Thread {
Gruppe gruppe;
public TestGroup(){
gruppe= new Gruppe("Monday");
}
public void run() {
System.out.println("listen");
gruppe.listenForChange();
}
public static void main(String[] args) {
testGruppen test = new testGruppen();
test.start();
test.gruppe.write("1"); // write just adds a new String to groupchat
test.gruppe.write("2");
test.gruppe.write("3");
test.gruppe.write("4");
}
}
Output: 4 instead of 1\n 2\n 3\n 4\n
What about using decorator:
public static void main(String... args) {
List<Integer> group = new FireEventListDecorator<>(new ArrayList<>());
for (int i = 0; i < 3; i++)
group.add(i);
}
public static class FireEventListDecorator<E> extends AbstractList<E> {
private final List<E> delegate;
public FireEventListDecorator(List<E> delegate) {
this.delegate = delegate;
}
#Override
public void add(int index, E element) {
delegate.add(index, element);
fireEvent(element);
}
#Override
public E get(int index) {
return delegate.get(index);
}
#Override
public int size() {
return delegate.size();
}
private void fireEvent(E element) {
System.out.println("add: " + element);
}
}
To avoid a CPU wasteful while (true) loop with polling, use a call-back method via an observer/listener pattern. One way to do this is to give your class that holds the ArrayList a PropertyChangeSupport instance, allow it to accept listeners, and then in the method that changes the ArrayList, notify listeners.
e.g.,
public class Group {
// property listened to: ADD_TEXT
public static final String ADD_TEXT = "add text";
// the support object
private PropertyChangeSupport support = new PropertyChangeSupport(this);
private List<String> chatText = new ArrayList<>();
public void addPropertyChangeListener(PropertyChangeListener listener) {
support.addPropertyChangeListener(ADD_TEXT, listener);
}
public void addText(String text) {
String oldValue = "";
String newValue = text;
chatText.add(text + "\n");
// notify listeners
support.firePropertyChange(ADD_TEXT, oldValue, newValue);
}
}
And then it can be used like so:
public class TestGroupChat {
public static void main(String[] args) {
final Group group = new Group();
group.addPropertyChangeListener(new GroupListener());
final String[] texts = {"Monday", "Tuesday", "Wednesday", "Thursday", "Friday"};
new Thread(() -> {
for (String text : texts) {
group.addText(text);
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {}
}
}) .start();
}
private static class GroupListener implements PropertyChangeListener {
#Override
public void propertyChange(PropertyChangeEvent evt) {
// call back method that is called any time the listened-to
// property has been changed
System.out.println("Notification: "+ evt.getNewValue());
}
}
}
You should take a look at LinkedBlockingQueue class.
This class is useful when you want to wake up a thread when a new element is added to a queue. In the example below, everytime you add a new message to the queue, the thread will print the message and wait for the next message.
public class Foo extends Thread {
LinkedBlockingQueue<String> messagesQueue;
public Foo(LinkedBlockingQueue<String> messagesQueue) {
this.messagesQueue = messagesQueue;
}
#Override
public voir run() {
while(true) {
String message = messagesQueue.take();
//The thread will sleep until there is a new message in the queue.
System.out.println(message);
}
}
}

How do use ConcurrencyHashmap another class or main method?

public class keyClientHandler extends ChannelInboundHandlerAdapter{
public static ConcurrentHashMap<String, String> keyTable = new ConcurrentHashMap<>();
String information;
String hashMapKey;
String hashMapValue;
#Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
// do something
keyTable.put(hashMapKey, hashMapValue);
System.out.println(keyTable.size()); //size = 268
}
public static ConcurrentHashMap<String,String> getKeyTable() {
return keyTable;
}
Another class use:
public static void main(String[] args) {
ConcurrentHashMap<String, String> map = keyClientHandler.getKeyTable();
System.out.println(map.size()); //size=0
}
When i try to use stuffed concurrentMap on another class or in the main method, it returns empty.
How can i use Concurentmap from another classes?
How we interpreted your problem?
public static ConcurrentHashMap<String, String> keyTable = new ConcurrentHashMap<>();
static concurrentHashMap has been defined in class KeyClientHandler. You intended to retrieve the map object and print the size of the map from main method of another class. Now as you said, your program runs and it prints 0 as the output. This means you are alright in terms of accessing the map. You should have got compilation errors, if your concurrentHashMap was not accessible from the said main method of another class.
What can be a possible way to demonstrate that this better?
I think the following improvements are required. Firstly, you don't need to use static map or static methods here. We can demonstrate this without static'ness as well. Try running this example which is a slight modification of your code.
import java.util.concurrent.ConcurrentHashMap;
class ChannelHandlerContext {
// some class
}
class KeyClientHandler{
public ConcurrentHashMap<String, String> keyTable = new ConcurrentHashMap<>();
String information;
String hashMapKey;
String hashMapValue;
KeyClientHandler() {
}
public void setKeyValue(String key, String value){
hashMapKey = key;
hashMapValue = value;
}
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
// do something
keyTable.put(hashMapKey, hashMapValue);
System.out.println(keyTable.size()); //size = 268
}
public ConcurrentHashMap<String,String> getKeyTable() {
return keyTable;
}
}
public class TestConcurrentHashMap {
public static void main(String[] args) {
KeyClientHandler keyClientHandler = new KeyClientHandler();
keyClientHandler.setKeyValue("apples", "fruit");
ConcurrentHashMap<String, String> map = keyClientHandler.getKeyTable();
try {
keyClientHandler.channelRead(null, null); // not the best thing
System.out.println(map.size()); //size=1
} catch (Exception e) {
e.printStackTrace();
}
}
}
Output:
1
My project is socket programming. I use Netty Framework. I send TCP client and received message send other client.
Server :
public class KeyClient {
static final String HOST = System.getProperty("host", "...");
static final int PORT = Integer.parseInt(System.getProperty("port", "..."));
public static void keyClientStart() throws InterruptedException {
EventLoopGroup group = new NioEventLoopGroup();
try {
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(group)
.channel(NioSocketChannel.class)
.option(ChannelOption.TCP_NODELAY, true)
.handler(new keyClientInitializer());
ChannelFuture future = bootstrap.connect(HOST, PORT).sync();
future.channel().closeFuture().sync();
} finally {
group.shutdownGracefully();
}
}
}
KeyClientInitializer :
public class keyClientInitializer extends ChannelInitializer<SocketChannel> {
#Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new LoggingHandler(LogLevel.INFO));
pipeline.addLast(new FixedLengthFrameDecoder(32));
pipeline.addLast(new keyClientHandler());
}
}
KeyClientHandler :
public class keyClientHandler extends ChannelInboundHandlerAdapter{
public static ConcurrentHashMap<String, String> keyTable = new ConcurrentHashMap<>();
String information;
String hashMapKey;
String hashMapValue;
#Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ByteBuf buffer = (ByteBuf) msg;
byte[] receivedKey = byteBufToByteArray(buffer);
information = DatatypeConverter.printHexBinary(receivedKey);
// do something
// ...
keyTable.put(hashMapKey, hashMapValue); //map has elements
}
#Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
}
public static ConcurrentHashMap<String,String> getKeyTable() {
return keyTable;
}
private byte[] byteBufToByteArray(ByteBuf buffer) {
byte[] receivedKey;
int offset;
int length = buffer.readableBytes();
if (buffer.hasArray()) {
receivedKey = buffer.array();
offset = buffer.arrayOffset();
} else {
receivedKey = new byte[length];
buffer.getBytes(buffer.readerIndex(), receivedKey);
offset = 0;
}
return receivedKey;
}
}
Test class:
public class AppMain {
public static void main(String[] args) throws InterruptedException {
KeyClient.keyClientStart();
ConcurrentHashMap<String, String> map = keyClientHandler.getKeyTable(); // is empty
}
When i add 'System.out.println(keyTable);' in keyClientHandler, i see map values.
Output
On my case it's OK to hold the CHM object on other class, you can check:
Is the System.out.println(keyTable.size()); called after channelRead(...) ? you print the key on which class? if the next channel handler, should you call ctx.fireChannelRead(msg); ?
Other way you can print the CHM hashCode(), if they are the same, that means same object.

Passing a value between classes

I need to pass a string from class to another class in Java (Bukkit), I have already read some similar questions, but I can't solve the problem.
I have a Main class
public class Main extends JavaPlugin {
#Override
public void onEnable() {
new PlayerListener(this);
this.saveDefaultConfig();
String bannedBlocksString = this.getConfig().getString("bannedBlocks");
}
#Override
public void onDisable() {
}
}
And another class "PlayerListener"
public class PlayerListener implements Listener {
public PlayerListener(Main plugin) {
plugin.getServer().getPluginManager().registerEvents(this, plugin);
}
// public static final String bannedBlocksString = "DIAMOND_BLOCK; EMERALD_BLOCK";
public static final String[] bannedBlocks = bannedBlocksString.split("; ");
public static boolean isBannedBlock(String[] bannedBlocks, String blockPlaced) {
boolean returnValue = false;
for (String bannedBlock : bannedBlocks) {
if(blockPlaced.equalsIgnoreCase(bannedBlock)){
returnValue = true;
}
}
return returnValue;
}
#EventHandler
public void onBlockPlace(BlockPlaceEvent event) {
String blockPlaced = event.getBlockPlaced().getType().toString();
if(!event.getPlayer().hasPermission("antibuild.block.noplace") && isBannedBlock(bannedBlocks, blockPlaced)) {
event.setCancelled(true);
event.getPlayer().sendMessage(ChatColor.RED + "You can not place this block.");
}
}
}
How can I get the value of bannedBlocksString in Main from the class "PlayerListener"?
Try this, I hope it works:
From Main:
PlayerListener pl = new PlayerListener(this);
this.saveDefaultConfig();
String [] bannedBlocksString = pl.getBannedBlocks();
From PlayerListener you have to declare get method:
public String [] getBannedBlocks(){
return this.bannedBlocks;
}
If you uncomment the bannedBlocksString in the PlayerListener then you can always access it in the Main class using PlayerListener.bannedBlocksString as the variable is static.
If you want to do it the other way arround and assign the value you need to remove the final from the variable and use the code beneath.
PlayerListener.bannedBlocks = bannedBlocksString.split("; ");

How to build a function on the fly in java?

I'm parsing a text file that is being mapped to some java code like such:
public void eval(Node arg)
{
if(arg.data.equals("rand"))
{
moveRandomly();
}
else if(arg.data.equals("home"))
{
goHome();
}
else if(arg.data.equals("iffood"))
{
ifFoodHere(arg.left, arg.right);
}//snip..
This is going to need to be re-evaluated about a thousand times and I'd rather not have to traverse the whole thing every time. Is there any way to make this traversal once and then have it be a function that is called every other time?
You could make a Map of Runnables:
Map<String, Runnable> methods = new HashMap<String, Runnable>();
methods.put("rand", new Runnable()
{
public void run()
{
moveRandomly();
}
});
...
then in your method
public void eval(Node arg)
{
Runnable command = methods.get(arg.data);
command.run();
}
Create an anonymous inner class.
Something like:
public Callable<Void> eval(Node arg)
{
if(arg.data.equals("rand"))
{
return new Callable<Void>{ public Void call() { moveRandomly(); return null; } };
}
...
}
Callable<Void> f = eval(a);
f.call();
If you know all the arguments/commands you can expect, i might do it like this:
enum Args {
home, rand, iffood;
private Method method;
private Args () {
try {
this.method = Commands.class.getMethod(this.name(), Node.class);
} catch (final Exception e) {}
}
public void invoke (final Node args)
throws IllegalArgumentException, IllegalAccessException,
InvocationTargetException {
this.method.invoke(null, args);
}
public static Args valueOf (final Node arg) {
return valueOf(arg.data);
}
public static void eval (final Node arg)
throws IllegalArgumentException, IllegalAccessException,
InvocationTargetException {
valueOf(arg).invoke(arg);
}
}
Command implementations are:
class Commands {
public static void home (final Node arg) {
goHome(); // Call the implementation
// or simply make these bodies the implementations.
}
public static void iffood (final Node arg) {
ifFoodHere(arg.left, arg.right);
}
public static void rand (final Node arg) {
moveRandom();
}
//...
}
your eval() then becomes, simply:
try {
Args.eval(arg);
} catch (IllegalArgumentException e) {
// Handle unknown arg.data
}

Categories