Java SwingWorker passing arguments and returning - java

I'd like to pass in String s, ArrayList<String> als and return
ArrayList<String> als
Run.java
class Run extends SwingWorker<String, Void>
{
private ArrayList<String> als;
private String s;
public Run(String s, ArrayList<String> als) {
this.s = s;
this.als = als;
}
public String doInBackground()
{
return AnotherClass.doSomething(s, als);
}
public void done()
{
try
{
}
catch (Exception ignore)
{
}
}
}
AnotherClass.java
public class AnotherClass{
public static String doSomething(String ipRange, ArrayList<String> nmapPorts) {
//do some stuff with the strings
try{
ProcessBuilder builder = new ProcessBuilder("someexe", "flag", cmds,
"&cd");
builder.redirectErrorStream(true);
Process pr = builder.start();
//do some stuff with the stream.
return aString;
}catch (IOException e){}
}
}

As you have initialized your class members in constructor you can always use global variables in SwingWorker.
class Run extends SwingWorker<List<String>, Void, Void>
{
private ArrayList<String> als;
private String s;
public Run(String s, ArrayList<String> als) {
this.s = s;
this.als = als;
}
public String doInBackground()
{
//this is right way to do it and you are correct here.
//Following called method must return ArrayList<String>
return AnotherClass.doSomething(s, als);
}
public void done()
{
ArrayList<String> retList = null;
try
{
//When doInBackground finishes done method is called and to get data from doInBackground it uses following method
retList = get();
als = retList;
}
catch (Exception ignore)
{
}
}
}

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 {

Can I add a new child class at run time?

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()?

Strange Null Pointer Exception in my tests passes one but fails other

Trying to use test driven development and ran into a NPE that I can't resolve and obviously because of that one of my tests fail.
In a method to fetch items I pass in a limit int and then instantiate a callback.
this is exactly where it falis the listener returns null I think.
[![enter image description here][1]][1]
Test class
package com.techyourchance.testdrivendevelopment.example11;
#RunWith(MockitoJUnitRunner.class)
public class FetchCartItemsUseCaseTest {
public static final int LIMIT = 10;
public static final int PRICE = 5;
public static final String ID = "id";
public static final String TITLE = "title";
public static final String DESCRIPTION = "description";
FetchCartItemsUseCase SUT;
#Mock
FetchCartItemsUseCase.Listener mListnerMock1;
FetchCartItemsUseCase.Listener mListnerMock2;
#Mock
GetCartItemsHttpEndpoint mGetCartItemsHttpEndpointMock;
#Captor
ArgumentCaptor<List<CartItem>> mAcListCartItem;
#Before
public void setup() throws Exception {
SUT = new FetchCartItemsUseCase(mGetCartItemsHttpEndpointMock);
success();
}
private void success() {
doAnswer(new Answer() {
#Override
public Object answer(InvocationOnMock invocation) throws Throwable {
Object[] args = invocation.getArguments();
Callback callback = (Callback) args[1];
callback.onGetCartItemsSucceeded(getCartItemSchemes());
return null;
}
}).when(mGetCartItemsHttpEndpointMock).getCartItems(anyInt(), any(Callback.class));
}
private List<CartItemSchema> getCartItemSchemes() {
List<CartItemSchema> schemas = new ArrayList<>();
schemas.add(new CartItemSchema(ID, TITLE, DESCRIPTION, PRICE));
return schemas;
}
#Test
public void fetchCartItems_correctLimitPassedToEndPoint() throws Exception {
ArgumentCaptor<Integer> acInt = ArgumentCaptor.forClass(Integer.class);
SUT.fetchCartItemsAndNotify(LIMIT);
verify(mGetCartItemsHttpEndpointMock).getCartItems(acInt.capture(), any(GetCartItemsHttpEndpoint.Callback.class));
assertThat(acInt.getValue(), is(LIMIT));
}
#Test
public void fetchCartItems_success_observersNotifiedWithCorrectData() throws Exception {
SUT.registerListener(mListnerMock1);
SUT.registerListener(mListnerMock2);
SUT.fetchCartItemsAndNotify(LIMIT);
verify(mListnerMock1).onCartItemsFetched(mAcListCartItem.capture());
verify(mListnerMock2).onCartItemsFetched(mAcListCartItem.capture());
List<List<CartItem>> captures = mAcListCartItem.getAllValues();
List<CartItem> capture1 = captures.get(0);
List<CartItem> capture2 = captures.get(1);
assertThat(capture1, is(getCartItems()));
assertThat(capture2, is(getCartItems()));
}
private List<CartItem> getCartItems() {
List<CartItem> cartItems = new ArrayList<>();
cartItems.add(new CartItem(ID, TITLE, DESCRIPTION, PRICE));
return cartItems;
}
//correct limit passed to the endpoint
//success - all observers notified with correct data
//success - unsubscribed observers not notified
//general error - observers notified of failure
//network error - observers notified of failure
}
public class FetchCartItemsUseCase {
private final List<Listener> mListeners = new ArrayList<>();
private final GetCartItemsHttpEndpoint mGetCartItemsHttpEndpoint;
public FetchCartItemsUseCase(GetCartItemsHttpEndpoint mGetCartItemsHttpEndpoint) {
this.mGetCartItemsHttpEndpoint = mGetCartItemsHttpEndpoint;
}
public void fetchCartItemsAndNotify(int limit) {
mGetCartItemsHttpEndpoint.getCartItems(limit, new GetCartItemsHttpEndpoint.Callback() {
#Override
public void onGetCartItemsSucceeded(List<CartItemSchema> cartItems) {
for(Listener listener : mListeners) {
listener.onCartItemsFetched(cartItemsFromSchemas(cartItems));
}
}
#Override
public void onGetCartItemsFailed(GetCartItemsHttpEndpoint.FailReason failReason) {
}
}) ;
}
private List<CartItem> cartItemsFromSchemas(List<CartItemSchema> cartItemSchemas) {
List<CartItem> cartItems = new ArrayList<>();
for(CartItemSchema schema : cartItemSchemas) {
cartItems.add(new CartItem(schema.getId(), schema.getTitle(),
schema.getDescription(), schema.getPrice()));
}
return cartItems;
}
public void registerListener(Listener listener) {
mListeners.add(listener);
}
public interface Listener {
Void onCartItemsFetched(List<CartItem> capture);
}
}
[1]: https://i.stack.imgur.com/r6Sea.png
really lost would appreciate any help
public class FetchReputationUseCaseSync {
private GetReputationHttpEndpointSync mGetReputationHttpEndpointSync;
public FetchReputationUseCaseSync(GetReputationHttpEndpointSync getReputationHttpEndpointSync) {
this.mGetReputationHttpEndpointSync = getReputationHttpEndpointSync;
}
public UseCaseResult fetchReputation() {
GetReputationHttpEndpointSync.EndpointResult result;
try{
result = mGetReputationHttpEndpointSync.getReputationSync();
}catch (NetworkErrorException e) {
e.printStackTrace();
return UseCaseResult.FAILURE;
}
switch(result.getStatus()) {
case SUCCESS:
return UseCaseResult.SUCCESS;
case GENERAL_ERROR:
return UseCaseResult.FAILURE;
default:
throw new RuntimeException("invalid status: " + result);
}
}
public enum UseCaseResult{
SUCCESS, FAILURE
}
}

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);
}
}
}

Save an enum in RandomAccessFile

Ok, I have a class called Encuadernacion.java
public enum Encuadernacion {
NONE("Ninguno"),
RUSTICA("Rustica"),
CARTONE("Cartone"),
PIEL("Piel"),
ESPIRAL("Espiral"),
GRAPADA("Grapada");
private final String ENCUADERNAR;
Encuadernacion(String descripcion){
this.ENCUADERNAR = descripcion;
}
public String getDescripcion(){
return ENCUADERNAR;
}
}
and then the book creation called Libro.java
public class Libro implements Serializable{
private Encuadernacion encuadernado;
public void setEncuadernado(int encuadernar){
this.encuadernado = Encuadernacion.values()[encuadernar];
//this encuadernar index is handled on another class.
}
public String getEncuadernacion(){
return encuadernado.getDescripcion();
}
#Override
public String toString(){
return encuadernado.getDescripcion();
}
and then the main class named Test.java
public class Test{
public static void main(String[] args)throws IOException{
RandomAccessFile fichero = null;
try {
fichero = new RandomAccessFile("BIBLIO.DAT", "rw");
}catch (FileNotFoundException e){
System.out.printf("Mensaje: %s", e.getMessage());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
When I write the enum into BIBLIO.DAT, it gets written as a string, It's Ok until this step. But when I want to read it, I create a new book while read those words.
Listar.java
public class Listar {
public static void lista(RandomAccessFile fichero)throws IOException, ClassNotFoundException{
try{
while(true){
Libro libro=new Libro();
libro.setEncuadernado(fichero.readUTF());
System.out.println(libro.toString());
}
}catch(EOFException e){
if(fichero!=null) fichero.close();
}
}
}
In this libro.setEncuadernado(fichero.readUTF()); This is not possible because this has to be a value from Encuadernacion SOMETHING;
How can I solve that? Transforming this string into enum value, or writing in diferent way the enum into BIBLIO.DAT, but RandomAccessFile has not a method to do that.
the code is cut for better reading.
I think it is worth to try:
public void setEncuadernado(String encuadernar){
this.encuadernado = Encuadernacion.valueOf(encuadernar);
//this encuadernar index is handled on another class.
}
in a Libro class. But as your code is not a MCVE, I didn't test it.
Solved like this.
public static String listarEncuadernados(){
Scanner scann=new Scanner(System.in);
int i =0;
for (Encuadernacion tipos: Encuadernacion.values()){
System.out.printf("\n%d.- %s", i, tipos.getDescripcion());
i++;
}
System.out.println();
int op = scann.nextInt();
return Encuadernacion.values()[op].getDescripcion();
}
public class Libro implements Serializable{
public void setEncuadernado(String encuadernar){
this.encuadernado = Encuadernacion.valueOf(encuadernar.toUpperCase());
}
#Override
public String toString(){
return encuadernado.getDescripcion();
}
}
public class Listar {
public static void lista(RandomAccessFile fichero)throws IOException, ClassNotFoundException{
try{
while(true){
Libro libro=new Libro();
libro.setEncuadernado(fichero.readUTF());
System.out.println(libro.toString());
}
}catch(EOFException e){
if(fichero!=null) fichero.close();
}
}
}

Categories