JUnit BeforeClass causes 'java.lang.ExceptionInInitializerError' - java

I have static variables in my test class, which I attempt to initialize using a static #BeforeClass method. However, I keep on getting the java.lang.ExceptionInInitializerError exception, and I cannot figure out what in the world I am doing wrong.
Below is my code - I get the exception at the first line of setupLocators():
package com.stuhrling.warehouse.inventoryTransactions.sales;
import com.stuhrling.warehouse.inventoryObjects.Container;
import com.stuhrling.warehouse.inventoryObjects.InventoryItem;
import com.stuhrling.warehouse.inventoryObjects.InventoryQuantity;
import com.stuhrling.warehouse.inventoryObjects.Location;
import com.stuhrling.warehouse.inventoryObjects.Locator;
import com.stuhrling.warehouse.inventoryTransactions.TransactionStatus;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.apache.log4j.Logger;
import static org.junit.Assert.assertTrue;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
/**
*
* #author Mwaldner
*/
public class SaleTest
{
#SuppressWarnings("unused")
private static final Logger log = Logger.getLogger(SaleTest.class);
Sale sale;
List<InventoryQuantity> inventory;
List<InventoryQuantity> itemsToRemove;
private static Locator l1;
private static Locator l2;
private static InventoryItem i1;
private static InventoryItem i2;
#BeforeClass
public static void setupTest()
{
setupLocators();
setupItems();
}
private static void setupLocators()
{
try
{
l1 = new Location();
l1.setCode("L1");
l2 = new Container();
l2.setCode("C1");
}
catch (Exception e)
{
log.error("error",e);
log.error(e.getStackTrace());
}
}
private static void setupItems()
{
i1 = new InventoryItem();
i1.setBarcode("B1");
i2 = new InventoryItem();
i2.setBarcode("B2");
}
#Before
public void setUp()
{
setupFakeInventory();
}
private void setupFakeInventory()
{
inventory = new ArrayList<InventoryQuantity>();
InventoryQuantity iq1 = new InventoryQuantity();
iq1.setItem(i1);
iq1.setLocator(l1);
iq1.setQuantityOnHand(15);
InventoryQuantity iq2 = new InventoryQuantity();
iq2.setItem(i2);
iq2.setLocator(l2);
iq2.setQuantityOnHand(35);
inventory.add(iq1);
inventory.add(iq2);
}
/**
* <strong>Given</strong><br/>
* a list of <code>InventoryQuantity</code> <br/>
* <strong>Then</strong><br/>
* remove said watches at said location from inventory
*/
#Test
public void testSellWatches() throws Exception
{
try
{
sale = new Sale();
int user = sale.getCreatedBy();
Date date = sale.getDateTimeFulfilled();
sale.inventory = inventory;
SaleLine line1 = new SaleLine(l1, i1, 5);
SaleLine line2 = new SaleLine(l2, i2, 7);
sale.add(line1);
sale.add(line2);
sale.execute(0);
assertTrue(checkInventory(l1, i1) == 10);
assertTrue(checkInventory(l2, i2) == 28);
assertTrue(sale.getStatus() == TransactionStatus.COMPLETED);
assertTrue(sale.toString().equals("Sale performed by '' on "));
assertTrue(line1.toString().equals("Sold 5 of item 'i1' from locator 'l1'"));
assertTrue(line2.toString().equals("Sold 7 of item 'i2' from locator 'l2'"));
}
catch (Exception e)
{
log.error(e.getCause());
log.error(e.getMessage());
log.error("error", e);
}
}
private int checkInventory(Locator locator, InventoryItem item)
{
List<InventoryQuantity> inventory = sale.inventory;
for (InventoryQuantity iq : inventory)
{
if (iq.getLocator().equals(locator) && iq.getItem().equals(item))
{
return iq.getQuantityOnHand();
}
}
return 0;
}
}
Here is the Location class:
package com.stuhrling.warehouse.inventoryObjects;
import com.stuhrling.warehouse.exceptions.LocationsDisabledException;
import javax.persistence.Column;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import com.stuhrling.warehouse.exceptions.ParentContainerException;
import com.stuhrling.warehouse.exceptions.PersistenceException;
import com.stuhrling.warehouse.inventoryObjects.Sequence.LocationSequence;
import com.stuhrling.warehouse.inventoryObjects.locationHeirarchy.LocationNameFactory;
import com.stuhrling.warehouse.persistence.WH_HibernateUtil;
import java.util.List;
import org.apache.log4j.Logger;
import org.hibernate.Session;
import org.hibernate.criterion.Restrictions;
/**
* #author Brian Horn
*/
#Entity
#DiscriminatorValue("L")
public class Location extends Container
{
private static final Logger log = Logger.getLogger(Location.class);
#Column(name = "location_type")
#Enumerated(EnumType.STRING)
private LocationType locationType = LocationType.DEFAULT;
public Location()
{
}
public Location(String code)
{
this.code = code;
}
public Location(String code, String name)
{
this.code = code;
this.name = name;
}
/**
* Create a new <code>Location</code> for storing inventory;<br>
* a unique sequence# is automatically assigned to the <code>Location</code>
* .<br>
* <Strong>Use this method to create new Locations, <i>do not use the
* <code>Location</code> class!</i></Strong>
*
* #return
* #throws PersistenceException
*/
public static Location newLocation() throws PersistenceException
{
Location loc = new Location(LocationSequence.getNext());
return loc;
}
/**
* Create a new <code>Location</code> for storing inventory;<br>
* a unique sequence# is automatically assigned to the <code>Location</code>
* .<br>
* <Strong>Use this method to create new Locations, <i>do not use the
* <code>Location</code> class!</i></Strong>
*
* #param locationType
* #param parent
* #return
* #throws PersistenceException
* #throws com.stuhrling.warehouse.exceptions.ParentContainerException
*/
public static Location newLocation(LocationType locationType, Locator parent) throws PersistenceException, ParentContainerException, LocationsDisabledException
{
Location loc = new Location(LocationSequence.getNext());
loc.addTo(parent);
log.debug(parent.getCode());
loc.setLocationType(locationType);
List<Location> siblings = getSiblings(loc);
LocationNameFactory lFactory = new LocationNameFactory(loc, siblings);
loc.setName(lFactory.getName());
return loc;
}
#SuppressWarnings("unchecked")
private static List<Location> getSiblings(Location location) throws PersistenceException
{
Session session = WH_HibernateUtil.getCurrentSession();
List<Location> l = session.createCriteria(Location.class).add(Restrictions.eq("parent", location.getParent())).add(Restrictions.isNotNull("name")).list();
return l;
}
#Override
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public LocationType getLocationType()
{
return locationType;
}
public void setLocationType(LocationType locationType)
{
this.locationType = locationType;
}
public void createHierarchicalName(LocationNameFactory factory) throws Exception
{
if (!(locationType.equals(LocationType.DEFAULT)))
{
name = factory.getName();
}
}
#Override
public void addTo(Locator locator) throws ParentContainerException, LocationsDisabledException
{
if (locator instanceof Location || locator instanceof Subinventory)
{
super.addTo(locator);
}
else
{
throw new ParentContainerException("Cannot add location to container");
}
}
}
Here is the StackTrace:
java.lang.ExceptionInInitializerError: null
at com.stuhrling.warehouse.inventoryObjects.Location.<clinit> (Location.java:17)
at com.stuhrling.warehouse.inventoryTransactions.sales.SaleTest.setupLocators(SaleTest.java:47)
at com.stuhrling.warehouse.inventoryTransactions.sales.SaleTest.setupTest(SaleTest.java:39)
Thank You in advance for your time.
Edit: BTW, I forgot to mention that Location and Container are subclasses of Locator.

The error means that Java couldn't construct an instance of Location or InventoryItem because of an exception that is thrown in a static block of code. Basically, you have this:
public class Location {
static { throw new RuntimeException("Foo"); }
}
or, more likely,
public class Location {
static Bar BAR = null;
static Foo FOO = BAR.x(); // NPE

if you are using Mac M1 chip and room lib , try this : In project-level build.gradle, add the following configuration in allprojects :
allprojects {
repositories {
// ...
}
// ADD THE FOLLOWING
configurations.all {
resolutionStrategy {
force 'org.xerial:sqlite-jdbc:3.34.0'
}
}

Related

ConcurrentSkipListMap firstKey() throws NoSuchElementException even though it contains data

I wrote a small application that receives data from a web socket, which I store in static ConcurrentSkipListMap.
The application initially creates a new thread where it runs infinitely while loop calling ConcurrentSkipListMap.firstKey(). After a while, this call throws a NoSuchElementException, even though the ConcurrentSkipListMap contains data.
break point in catch block
Example of my application:
I have cacher class that contains websocket implementation and NavigableMap init:
package solvethat.net.triobot.Example;
import com.binance.api.client.BinanceApiCallback;
import com.binance.api.client.BinanceApiClientFactory;
import com.binance.api.client.domain.event.DepthEvent;
import com.binance.api.client.domain.market.OrderBook;
import com.binance.api.client.domain.market.OrderBookEntry;
import java.math.BigDecimal;
import java.util.Comparator;
import java.util.List;
import java.util.NavigableMap;
import java.util.concurrent.ConcurrentSkipListMap;
public class AskCacher {
private long updateId;
private final BinanceApiClientFactory factory;
public AskCacher() {
factory = BinanceApiClientFactory.newInstance();
initAsks();
runWebsocket();
}
/**
* Init data getting order book snapshot
*/
private void initAsks() {
try {
OrderBook orderBook = factory.newRestClient().getOrderBook("btcusdt".toUpperCase(), 10);
updateId = orderBook.getLastUpdateId();
NavigableMap<Double, Double> asks = new ConcurrentSkipListMap<>(Comparator.naturalOrder());
for (OrderBookEntry ask : orderBook.getAsks()) {
asks.put(Double.parseDouble(ask.getPrice()), Double.parseDouble(ask.getQty()));
}
StaticData.ask = asks;
} catch (Exception e) {
System.err.println(e.getMessage());
}
}
private void runWebsocket() {
factory.newWebSocketClient().onDepthEvent("btcusdt", new BinanceApiCallback<>() {
/**
* Set ask price and call analysis method
*/
#Override
public void onResponse(DepthEvent depthEvent) {
if (depthEvent.getFinalUpdateId() > updateId) {
updateId = depthEvent.getFinalUpdateId();
updateOrderBook(depthEvent.getAsks());
}
}
/**
* Just print err message
*/
#Override
public void onFailure(final Throwable cause) {
System.err.println(cause.getMessage());
}
});
}
/**
* Updates an order book (asks) with a delta received from the server.
* Whenever the qty specified is ZERO, it means the price should was removed from the order book.
*/
private void updateOrderBook(List<OrderBookEntry> orderBookDeltas) {
for (OrderBookEntry orderBookDelta : orderBookDeltas) {
Double price = Double.parseDouble(orderBookDelta.getPrice());
BigDecimal qty = new BigDecimal(orderBookDelta.getQty());
if (qty.compareTo(BigDecimal.ZERO) == 0) {
// qty=0 means remove this level
StaticData.ask.remove(price);
} else {
StaticData.ask.put(price, Double.parseDouble(orderBookDelta.getQty()));
}
}
// Print best ask to see if cacher is alive
System.out.println("btc-usdt best ask: " + StaticData.ask.firstKey());
// Edit map length
if (StaticData.ask.size() > 10) {
StaticData.ask.tailMap((Double) StaticData.ask.keySet().toArray()[10], true).clear();
}
}}
Then infinite loop:
package solvethat.net.triobot.Example;
public class InfiniteLoop {
public void loopProcess() {
Analyzer analyzer = new Analyzer();
while (true) {
analyzer.analyze(StaticData.ask.firstEntry());
}
}}
And analyzer class:
package solvethat.net.triobot.Example;
import java.util.Map;
public class Analyzer {
public void analyze(Map.Entry<Double, Double> entry) {
StaticData.AnalyzeObject analyzeObject = new StaticData.AnalyzeObject();
analyzeObject.setBestAsk(entry.getKey());
if (analyzeObject.getBestAsk() > 50000) {
System.out.println("It is a good price!!");
}
}
}
Static data model:
package solvethat.net.triobot.Example;
import java.util.NavigableMap;
public class StaticData {
public static NavigableMap<Double, Double> ask;
public static class AnalyzeObject {
double bestAsk;
public double getBestAsk() {
return bestAsk;
}
public void setBestAsk(double bestAsk) {
this.bestAsk = bestAsk;
}
}
}
Main class for example run:
package solvethat.net.triobot.Example;
public class Main {
public static void main(String[] arguments) {
new AskCacher();
new Thread(new InfiniteLoop()::loopProcess).start();
}
}
The example only shows how the application is composed, but I was not able to use it to raise an error but I opened my repo as public:
https://github.com/Sick-E/TrioBot
Can anyone please help me?
Thank you.
Tomas
You can replace your code with something like that (no exception handling is required)
Optional.ofNullable(trio.getThirdPair().getBids().firstEntry())
.map(Map.Entry::getKey)
.ifPresent(trio.getTrioAnalysis()::setBidThird);

Parsing YAML with arrays of different types

I am trying to read a YAML file and store the result in a list of POJOs.
I cannot modify the YAML file. I use Jackson 2.10.0 but I am open to any other version. I am trying to parse the following script with Jackson:
vehicles-notype.yaml
Vehicles is basically a list of objects with some common properties and some unique to the type of vehicle.
---
vehicles:
- car:
make: "Mercedes-Benz"
model: "S500"
topSpeed: 250.0
seatingCapacity: 5
- truck:
make: "Isuzu"
model: "NQR"
payloadCapacity: 7500.0
Desired outpout
After reading the file, I'd like that, if I introspect the list, I'd like to get:
... App.java:48): -> start()
... App.java:56): class net.jgp.labs.jackson.yaml.lab411_pojos.Car
... App.java:56): class net.jgp.labs.jackson.yaml.lab411_pojos.Truck
The Car and Truck POJOs are pretty obvious:
Car
package net.jgp.labs.jackson.yaml.lab411_pojos;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
public class Car extends Vehicle {
private int seatingCapacity;
private double topSpeed;
#JsonCreator
public Car(
#JsonProperty("make") String make,
#JsonProperty("model") String model,
#JsonProperty("seating") int seatingCapacity,
#JsonProperty("topSpeed") double topSpeed) {
super(make, model);
this.seatingCapacity = seatingCapacity;
this.topSpeed = topSpeed;
}
public int getSeatingCapacity() {
return seatingCapacity;
}
public void setSeatingCapacity(int seatingCapacity) {
this.seatingCapacity = seatingCapacity;
}
public double getTopSpeed() {
return topSpeed;
}
public void setTopSpeed(double topSpeed) {
this.topSpeed = topSpeed;
}
public String getType() {
return "car";
}
}
Truck
package net.jgp.labs.jackson.yaml.lab411_pojos;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
public class Truck extends Vehicle {
private double payloadCapacity;
#JsonCreator
public Truck(
#JsonProperty("make") String make,
#JsonProperty("model") String model,
#JsonProperty("payload") double payloadCapacity) {
super(make, model);
this.payloadCapacity = payloadCapacity;
}
public double getPayloadCapacity() {
return payloadCapacity;
}
public void setPayloadCapacity(double payloadCapacity) {
this.payloadCapacity = payloadCapacity;
}
#Override
public String getType() {
return "truck";
}
}
Fleet
The Fleet POJO is also obvious.
package net.jgp.labs.jackson.yaml.lab411_pojos;
import java.util.List;
public class Fleet {
private List<Vehicle> vehicles;
public void setVehicles(List<Vehicle> vehicles) {
this.vehicles= vehicles;
}
public List<Vehicle> getVehicles() {
return vehicles;
}
}
Vehicle
Vehicle is a bit more tricky, as I am trying to play with #JsonTypeInfo and #JsonSubTypes. You can see the commented code, which is slowly driving me mad:
package net.jgp.labs.jackson.yaml.lab411_pojos;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonSubTypes.Type;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
#JsonTypeInfo(
use = JsonTypeInfo.Id.CLASS,
include = JsonTypeInfo.As.EXTERNAL_PROPERTY
// ,
// property = "className"
)
#JsonSubTypes({
#Type(value = Car.class, name = "car"),
#Type(value = Truck.class, name = "truck")
})
//#JsonSubTypes({
// #Type(value = Car.class, name = "car"),
// #Type(value = Truck.class, name = "truck")
//})
public abstract class Vehicle {
private String make;
private String model;
#JsonProperty("type")
abstract public String getType();
public void setType(String type) {};
protected Vehicle(String make, String model) {
this.make = make;
this.model = model;
}
public String getMake() {
return make;
}
public void setMake(String make) {
this.make = make;
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
}
App
Finally the application code, which is pretty obvious too.
package net.jgp.labs.jackson.yaml.lab411_read_diff_objects;
import java.io.File;
import java.io.IOException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import net.jgp.labs.jackson.yaml.lab411_pojos.Fleet;
import net.jgp.labs.jackson.yaml.lab411_pojos.Vehicle;
/**
* What does it do?
*
* #author jgp
*/
public class ReadListVehicleNoTypeApp {
private static final Logger log =
LoggerFactory.getLogger(ReadListVehicleNoTypeApp.class);
/**
* main() is your entry point to the application.
*
* #param args
*/
public static void main(String[] args) {
ReadListVehicleNoTypeApp app = new ReadListVehicleNoTypeApp();
try {
app.start();
} catch (JsonProcessingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* The processing code.
*
* #throws IOException
*/
protected boolean start() throws IOException {
log.debug("-> start()");
ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
Fleet fleet = mapper.readValue(new File("data/vehicles-notype.yaml"),
Fleet.class);
for (Vehicle v : fleet.getVehicles()) {
log.debug("{}", v.getClass());
}
return true;
}
}
I am pretty sure there is something to play with the #Json family of attributes, but I am slowly losing it ;-).
car and truck are a field names, properties. I am not aware about Jackson annotation which allows to set types from different fields.
If Yaml file can not be modified, we can use Streaming API to read type property and deserialise Vehicle. In pseudocode it could look like:
while token != EOF
while token != FIELD_NAME
nextToken()
fieldName = nextFieldName();
clazz = convertToClass(fieldName);
vehicles.add(read(clazz));
Luckily, field name which defines type is a first field name and we can read it manually and use Jackson to read type after that. I removed JsonSubTypes and JsonTypeInfo annotation from Vehicle class and with Streaming API it could look like below:
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import com.fasterxml.jackson.dataformat.yaml.YAMLParser;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
public class YamlApp {
public static void main(String[] args) throws Exception {
File yamlFile = new File("./resource/test.yaml").getAbsoluteFile();
FleetDeserializer deserializer = new FleetDeserializer();
Fleet fleet = deserializer.readValue(yamlFile);
System.out.println(fleet);
}
}
class FleetDeserializer {
private YAMLFactory factory = new YAMLFactory();
private ObjectMapper mapper = new ObjectMapper(factory);
public Fleet readValue(File yamlFile) throws IOException {
Fleet fleet = new Fleet();
fleet.setVehicles(new ArrayList<>());
YAMLParser parser = factory.createParser(yamlFile);
while (parser.nextToken() != null) {
if (parser.getCurrentToken() != JsonToken.START_OBJECT) {
continue;
}
// skip everything until a field name
while (parser.nextToken() != JsonToken.FIELD_NAME) ;
Class<? extends Vehicle> type = getType(parser.getCurrentName());
if (type == null) {
continue;
}
// skip field name
parser.nextToken();
parser.nextToken();
// read next vehicle
fleet.getVehicles().add(mapper.readValue(parser, type));
}
return fleet;
}
private Class<? extends Vehicle> getType(String fieldName) {
Objects.requireNonNull(fieldName);
switch (fieldName) {
case "car":
return Car.class;
case "truck":
return Truck.class;
default:
return null;
}
}
}
Above code prints:
Fleet{vehicles=[Car{seatingCapacity=5, topSpeed=250.0, make='Mercedes-Benz', model='S500'}, Truck{payloadCapacity=7500.0, make='Isuzu', model='NQR'}]}

Create a null-safe BooleanBinding with JavaFX 8

I need help creating a null-safe BooleanBinding. It has to be null-safe since I can not provide default values for all attributes in the model (one reason: the model contains enumerations). My first approach has been as follows:
executeButtonDisabled.bind(missionProperty().isNotNull().and(missionProperty().get().statusProperty().isNotEqualTo(MissionStatus.CREATED)));
final BooleanBinding isNotExecutingBinding = missionProperty().isNotNull().and(missionProperty().get().statusProperty().isNotEqualTo(MissionStatus.EXECUTING));
completeButtonDisabled.bind(isNotExecutingBinding);
cancelButtonDisabled.bind(isNotExecutingBinding)
But that approach does not work because the complete expression is evaluated which results in a NullPointerException (but it correctly updates the buttons, when a property is provided). Now I am trying to use the Bindings class as suggested in JavaFX binding and null values, but I can't make it work. Here's my current approach:
final BooleanBinding isNotCreatedBinding = Bindings.createBooleanBinding(
() -> mission.isNull().getValue()
? true
: missionProperty().get().statusProperty().isNotEqualTo(MissionStatus.CREATED).getValue());
final BooleanBinding isNotExecutingBinding = Bindings.createBooleanBinding(
() -> mission.isNull().getValue()
? true
: missionProperty().get().statusProperty().isNotEqualTo(MissionStatus.EXECUTING).getValue());
executeButtonDisabled.bind(isNotCreatedBinding);
completeButtonDisabled.bind(isNotExecutingBinding);
cancelButtonDisabled.bind(isNotExecutingBinding);
But this does not work and I do not understand why. It seems that the property binding for modelProperty() does not work here! Can you explain to me how-to convert the first working solution (at least without null) to a proper null-safe solution?
Edit 2016-04-26: The suggested solution does not work, therefore I created a simple fully-working example:
Mission.java:
package de.florianwolters.example.javafx.bindings;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
public class Mission {
enum Status {
CREATED,
EXECUTING,
COMPLETED,
CANCELED;
}
private final StringProperty shortName = new SimpleStringProperty();
private final ObjectProperty<Status> status = new SimpleObjectProperty<>();
public Mission(final String shortName) {
this.setShortName(shortName);
this.setStatus(Status.CREATED);
}
public String getShortName() {
return shortNameProperty().get();
}
public void setShortName(final String shortName) {
shortNameProperty().set(shortName);
}
public StringProperty shortNameProperty() {
return shortName;
}
public Status getStatus() {
return statusProperty().get();
}
public void setStatus(final Status status) {
statusProperty().set(status);
}
public ObjectProperty<Status> statusProperty() {
return status;
}
}
MissionDetailsViewModel.java:
package de.florianwolters.example.javafx.bindings;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.BooleanBinding;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.ReadOnlyBooleanProperty;
import javafx.beans.property.ReadOnlyBooleanWrapper;
import javafx.beans.property.SimpleObjectProperty;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public final class MissionDetailsViewModel {
/**
* The logger used for logging in the `MissionDetailsViewModel` class.
*/
private static final Logger LOGGER = LoggerFactory.getLogger(
MissionDetailsViewModel.class);
private ObjectProperty<Mission> mission = new SimpleObjectProperty<>();
private final ReadOnlyBooleanWrapper executeButtonDisabled = new ReadOnlyBooleanWrapper(true);
private final ReadOnlyBooleanWrapper completeButtonDisabled = new ReadOnlyBooleanWrapper(true);
private final ReadOnlyBooleanWrapper cancelButtonDisabled = new ReadOnlyBooleanWrapper(true);
/**
* Constructs a `MissionDetailsViewModel`.
*/
public MissionDetailsViewModel(final ObjectProperty<Mission> mission) {
this.mission.bind(mission);
// partialWorkingBinding();
notWorkingBinding();
}
private void notWorkingBinding() {
final BooleanBinding isNotCreatedBinding = Bindings.createBooleanBinding(
() -> missionProperty().isNull().get()
? true
: missionProperty().get().statusProperty().isNotEqualTo(Mission.Status.CREATED).get(),
missionProperty());
final BooleanBinding isNotExecutingBinding = Bindings.createBooleanBinding(
() -> mission.isNull().get()
? true
: missionProperty().get().statusProperty().isNotEqualTo(Mission.Status.EXECUTING).get(),
missionProperty());
executeButtonDisabled.bind(isNotCreatedBinding);
completeButtonDisabled.bind(isNotExecutingBinding);
cancelButtonDisabled.bind(isNotExecutingBinding);
}
private void partialWorkingBinding() {
executeButtonDisabled.bind(missionProperty().isNotNull().and(missionProperty().get().statusProperty().isNotEqualTo(Mission.Status.CREATED)));
final BooleanBinding isNotExecutingBinding = missionProperty().isNotNull().and(missionProperty().get().statusProperty().isNotEqualTo(Mission.Status.EXECUTING));
completeButtonDisabled.bind(isNotExecutingBinding);
cancelButtonDisabled.bind(isNotExecutingBinding);
}
public boolean isExecuteButtonDisabled() {
return executeButtonDisabledProperty().get();
}
public ReadOnlyBooleanProperty executeButtonDisabledProperty() {
return executeButtonDisabled;
}
public boolean isCompleteButtonDisabled() {
return completeButtonDisabledProperty().get();
}
public ReadOnlyBooleanProperty completeButtonDisabledProperty() {
return completeButtonDisabled;
}
public boolean isCancelButtonDisabled() {
return cancelButtonDisabledProperty().get();
}
public ReadOnlyBooleanProperty cancelButtonDisabledProperty() {
return cancelButtonDisabled;
}
public Mission getMission() {
return missionProperty().get();
}
public void setMission(final Mission mission) {
missionProperty().set(mission);
}
public ObjectProperty<Mission> missionProperty() {
return mission;
}
}
MissionDetailsViewModelTest.java:
package de.florianwolters.example.javafx.bindings;
import static eu.lestard.assertj.javafx.api.Assertions.assertThat;
import javafx.beans.property.SimpleObjectProperty;
import org.junit.Before;
import org.junit.Test;
public final class MissionDetailsViewModelTest {
private Mission mission;
private MissionDetailsViewModel viewModel;
#Before
public void setUp() {
mission = new Mission("My Short Name");
viewModel = new MissionDetailsViewModel(new SimpleObjectProperty<Mission>(mission));
}
#Test
public void testInitialValues() {
assertThat(viewModel.executeButtonDisabledProperty()).isFalse();
assertThat(viewModel.completeButtonDisabledProperty()).isTrue();
assertThat(viewModel.cancelButtonDisabledProperty()).isTrue();
}
#Test
public void testMissionStatusSetToExecuting() {
mission.setStatus(Mission.Status.EXECUTING);
assertThat(viewModel.executeButtonDisabledProperty()).isTrue();
assertThat(viewModel.completeButtonDisabledProperty()).isFalse();
assertThat(viewModel.cancelButtonDisabledProperty()).isFalse();
}
#Test
public void testMissionStatusSetToCompleted() {
mission.setStatus(Mission.Status.COMPLETED);
assertThat(viewModel.executeButtonDisabledProperty()).isTrue();
assertThat(viewModel.completeButtonDisabledProperty()).isTrue();
assertThat(viewModel.cancelButtonDisabledProperty()).isTrue();
}
#Test
public void testMissionStatusSetToCanceled() {
mission.setStatus(Mission.Status.CANCELED);
assertThat(viewModel.executeButtonDisabledProperty()).isTrue();
assertThat(viewModel.completeButtonDisabledProperty()).isTrue();
assertThat(viewModel.cancelButtonDisabledProperty()).isTrue();
}
}
The unit test fails with the code above (the method notWorkingBinding() is used) but works with the method partialWorkingBinding(). What am I doing wrong?
You set up the calculation function for isNotCreatedBinding, but you didn't set the dependencies for the binding. You need to add mision as dependency:
Bindings.createBooleanBinding(
() -> mission.isNull().getValue()
? true
: missionProperty().get().statusProperty().isNotEqualTo(MissionStatus.CREATED).getValue(), mission);
EDIT
You need to listen to the statusProperty instead of missionProperty, which will not work with createBooleanBinding when missionProperty().get() == null.
But you can use a When binding:
(is causing a NullPointerException as already mentioned in the question)
BooleanBinding isNotCreatedBinding = new When(mission.isNotNull()).then(mission.get().statusProperty().isNotEqualTo(Mission.Status.CREATED)).otherwise(false);
Or a more low-level solution:
missionProperty().addListener((ov, m, m1) -> {
if (m1 != null) {
executeButtonDisabled.bind(m1.statusProperty().isNotEqualTo(Mission.Status.CREATED));
}else {
executeButtonDisabled.unbind();
executeButtonDisabled.set(false);
}
});
Tomas Mikula's ReactFX framework (v 2.0) has this functionality built in:
import org.reactfx.value.Val;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleObjectProperty;
public class NestedBindingTest {
public static void main(String[] args) {
BooleanProperty disable = new SimpleBooleanProperty();
disable.addListener((obs, wasDisabled, isNowDisabled) ->
System.out.println("disable: "+wasDisabled+" -> "+isNowDisabled));
ObjectProperty<Item> item = new SimpleObjectProperty<>();
Val<Item.Status> status = Val.flatMap(item, Item::statusProperty);
disable.bind(status.map(s -> s == Item.Status.PENDING).orElseConst(true));
Item i = new Item();
System.out.println("Setting item");
item.set(i);
System.out.println("Setting item status to PENDING");
i.setStatus(Item.Status.PENDING);
System.out.println("Setting item status to READY");
i.setStatus(Item.Status.READY);
System.out.println("Setting item to null");
item.set(null);
}
public static class Item {
public enum Status {PENDING, READY}
private final ObjectProperty<Status> status = new SimpleObjectProperty<>();
public final ObjectProperty<Status> statusProperty() {
return this.status;
}
public final NestedBindingTest.Item.Status getStatus() {
return this.statusProperty().get();
}
public final void setStatus(final NestedBindingTest.Item.Status status) {
this.statusProperty().set(status);
}
}
}

Java & XML: Fixing a few things

I'm making an attempt to load my npc drops for a game via xml. I've started the loading processes but I'm encountered a few problems. First of all, I can only have 1 drop per npc without creating another case of 'newNpc' with the same npc id or I get a load error. I'd like to have multiple drops per npc. Also I need help reading and using a definition by rarity. Example:
if (Math.random(100) > 95) {
// Drop VERY_RARE item here
|
My XStreamUtil Class (loads xml files):
package server.engine.util;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import server.game.entity.npc.impl.drops.NpcDropDefinition;
import server.game.entity.npc.impl.drops.NpcDropDefinition.LoadDropDefinitions;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.converters.reflection.Sun14ReflectionProvider;
public class XStreamUtil {
private static XStreamUtil instance = new XStreamUtil();
private static XStream xStream = new XStream(new Sun14ReflectionProvider());
public static XStreamUtil getInstance() {
return instance;
}
public static XStream getxStream() {
return xStream;
}
static {
xStream.alias("newNpc", NpcDropDefinition.class);
}
public static void loadAllFiles() throws IOException {
LoadDropDefinitions.load();
}
public static void writeXML(Object object, File file) throws IOException {
FileOutputStream out = new FileOutputStream(file);
try {
xStream.toXML(object, out);
out.flush();
} finally {
out.close();
}
}
}
My Xml Definition Class:
package server.game.entity.npc.impl.drops;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.List;
import server.engine.util.XStreamUtil;
/**
* NpcDropDefinition.java
*
* #author Notorious
*/
public class NpcDropDefinition {
private int npcId, itemId, itemAmount;
private DropRarity dropRarity;
enum DropRarity {
CONSTANT,
COMMON,
UNCOMMON,
RARE,
VERY_RARE;
}
/**
* #return the npcId
*/
public int getNpcId() {
return npcId;
}
/**
* #return the itemId
*/
public int getItemId() {
return itemId;
}
/**
* #return the itemAmount
*/
public int getItemAmount() {
return itemAmount;
}
public DropRarity getDropRarity() {
return dropRarity;
}
public static class LoadDropDefinitions {
/**
* Holds all of the definitions for prayer
*/
private static NpcDropDefinition[] def = null;
public static NpcDropDefinition[] getDefinitions() {
return def;
}
/**
* Loads the definitions of pvm points from the XML file
*
* #throws FileNotFoundException
*/
public static void load() throws FileNotFoundException {
#SuppressWarnings("unchecked")
List<NpcDropDefinition> XMLlist = (List<NpcDropDefinition>) XStreamUtil
.getxStream().fromXML(
new FileInputStream("./data/xml/npcDrops.xml"));
def = new NpcDropDefinition[XMLlist.size()];
for (int i = 0; i < def.length; i++) {
def[i] = XMLlist.get(i);
}
if (def.length > 1 || def.length < 1)
System.out.println("[Npc-Drops]: " + def.length
+ " npc drops have been loaded..");
else
System.out
.println("[Npc-Drops]: Only one npc drop has been loaded..");
}
}
}
My Drop Handler class:
package server.game.entity.npc.impl.drops;
import server.Server;
import server.game.entity.Client;
import server.game.entity.npc.NpcHandler;
import server.game.entity.player.PlayerHandler;
/**
* NpcDropHandler.java
*
* #author Notorious
*/
public class NpcDropHandler {
public void dropItems(int i) {
Client c = (Client) PlayerHandler.players[NpcHandler.npcs[i]
.getKillerIndex()];
if (c != null) {
Server.itemHandler.createGroundItem(c, 1, NpcHandler.npcs[i].absX,
NpcHandler.npcs[i].absY, 1, c.playerId);
}
}
}
My Current Xml file:
<list>
<newNpc>
<npcId>1265</npcId>
<itemId>995</itemId>
<itemAmount>10</itemAmount>
<dropRarity>COMMON</dropRarity>
</newNpc>
</list>

javax.enterprise.event.Event: How to initialize the pushEvent

I am currently working CDI pushevent. I plan to trigger the pushevent by backend Java code instead of frontend jsf by commandButton.
Here is the code for PushCdiBean.java
import java.io.Serializable;
import java.util.UUID;
import javax.annotation.PostConstruct;
import javax.enterprise.event.Event;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.inject.Inject;
import org.richfaces.application.push.MessageException;
import org.richfaces.application.push.TopicKey;
import org.richfaces.application.push.TopicsContext;
import org.richfaces.cdi.push.Push;
/**
* #author Lukas Fryc
*/
#javax.inject.Named("pushCdiBean")
#javax.enterprise.context.RequestScoped
//#ManagedBean(name="pushCdiBean")
//#ViewScoped
public class PushCdiBean implements Serializable {
/**
*
*/
private static final long serialVersionUID = -5241937306040858158L;
private static final String CDI_PUSH_TOPIC = "pushCdi";
private String userIdentifier;
private String message;
#Inject
#Push(topic=CDI_PUSH_TOPIC)//i thought that the topic is initialized with this ?!
private Event<String> pushEvent;
#PostConstruct
public void initialize() {
if(userIdentifier == null) {
userIdentifier = UUID.randomUUID().toString().replace("-", "");
}
TopicsContext topicsContext = TopicsContext.lookup();
topicsContext.getOrCreateTopic(new TopicKey(CDI_PUSH_TOPIC, userIdentifier));//initialize the topic and make the troublesome message disappears
}
public synchronized void sendMessage() throws MessageException {
pushEvent.fire(message);
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public Event<String> getPushEvent() {
return pushEvent;
}
public void setPushEvent(Event<String> pushEvent) {
this.pushEvent = pushEvent;
}
public String getUserIdentifier() {
return userIdentifier;
}
public void setUserIdentifier(String userIdentifier) {
this.userIdentifier = userIdentifier;
}
When I try to create the PushCdiBean class and call sendMessage() function, however, pushEvent.fire fails.
The code is here.
/**
*
*/
public void run() {
while (running) {
try {
PushCdiBean pushTest = new PushCdiBean();
pushTest.setMessage("This is CDI push Test");
pushTest.sendMessage();
}
catch (Exception e) {
System.out.println("Exception: " + e.getMessage());
}
sleep(4000);
}
}
Could you please give me some suggestions? Thank you very much.
You have to #Inject the CDI bean, not instantiate it on your own via new.

Categories

Resources