How to process a JSON using Java - java

I passing a JSON string (inputJson) to my java code (PPProgramAddView) on the server side.
PPProgramAddView:
inputJson: [{"ppl_row":0,"ppl_time":"07:00","ppat_id":"Mw==","ppa_id":"MTI=","ppl_LeadAssist":"Lead"},{"ppl_row":1,"ppl_time":"07:10","ppat_id":"Mg==","ppa_id":"NA==","ppl_LeadAssist":"Assist"}]
When I try to process it I get the following error:
com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "ppl_row" (class client.Profile14), not marked as ignorable (5 known properties: "plTime", "plActivity", "plActivityType", "plRow", "plLeadAssist"])
at [Source: (String)"[{"ppl_row":0,"ppl_time":"07:00","ppat_id":"Mw==","ppa_id":"MTI=","ppl_LeadAssist":"Lead"},{"ppl_row":1,"ppl_time":"07:10","ppat_id":"Mg==","ppa_id":"NA==","ppl_LeadAssist":"Assist"}]"; line: 1, column: 14] (through reference chain: java.lang.Object[][0]->client.Profile14["ppl_row"])
at com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException.from(UnrecognizedPropertyException.java:61)
I have done a search and I can not find '"plTime", "plActivity", "plActivityType", "plRow", "plLeadAssist"' anywhere.
My code is:
//Look through the new program lines and add them.
try {
ObjectMapper mapper = new ObjectMapper();
Profile14[] profiles14 = mapper.readValue(inputJson, Profile14[].class);
for (final Profile14 programLine : profiles14) {
String ppl_row = programLine.getplRow();
String ppl_time = null;
if (programLine.getplTime().length() < 1){
ppl_time = "00:01";
}else{
ppl_time = programLine.getplTime();
}
String ppat_id_encoded = programLine.getplActivityType();
String ppa_id_encoded = programLine.getplActivity();
String ppl_LeadAssist = programLine.getplLeadAssist().substring(0, Math.min(programLine.getplLeadAssist().length(), 45));
byte[] valueDecoded3 = Base64.decodeBase64(ppat_id_encoded);//decoding part
String ppat_id = new String(valueDecoded3);
byte[] valueDecoded4 = Base64.decodeBase64(ppa_id_encoded);//decoding part
String ppa_id = new String(valueDecoded4);
System.out.println("ppID: " + ppID + " ppat_id: " + ppat_id + " ppa_id: " + ppa_id +
" ppl_row : " + ppl_row + " ppl_time: " + ppl_time + " ppl_LeadAssist: " + ppl_LeadAssist);
MySQLConnection.addPPProgramLine(ppID, ppat_id, ppa_id, ppl_row, ppl_time, ppl_LeadAssist);
}
} catch (Exception e) {
e.printStackTrace();
response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Error.");
}
}
}
class Profile14 {
private String ppl_row;
private String ppl_time;
private String ppat_id;
private String ppa_id;
private String ppl_LeadAssist;
public String getplRow() {
return ppl_row;
}
public void setplRow(String ppl_row) {
this.ppl_row = ppl_row;
}
public String getplTime() {
return ppl_time;
}
public void setplTime(String ppl_time) {
this.ppl_time = ppl_time;
}
public String getplActivityType() {
return ppat_id;
}
public void setplActivityType (String ppat_id) {
this.ppat_id = ppat_id;
}
public String getplActivity() {
return ppa_id;
}
public void setplActivity(String ppa_id) {
this.ppa_id = ppa_id;
}
public String getplLeadAssist() {
return ppl_LeadAssist;
}
public void setplLeadAssist(String ppl_LeadAssist) {
this.ppl_LeadAssist = ppl_LeadAssist;
}
#Override
public String toString() {
return "Profile14 [ppl_row=" + ppl_row + ", ppl_time=" + ppl_time + ", ppat_id=" + ppat_id
+ ", ppa_id=" + ppa_id + ", ppl_LeadAssist=" + ppl_LeadAssist + "]";
}
}

You aren't following JavaBean standards, and without explicit instructions Jackson doesn't know how to map your class.
The Java convention is to name properties like pplRow, and your JSON is using the alternate Ruby style of ppl_row. There are three options:
Switch the entire Jackson engine to use an alternate style. (Not a great idea since it tends to cause collisions.
Tell Jackson to use an alternate style for particular Java classes. (We'll do this.)
Annotate each property with #JsonProperty (works, but lots of extra effort).
Start by using standard Java naming for your properties:
class Profile14 {
private String pplRow;
public String getPplRow() {
return this.pplRow;
}
public void setPplRow(String s) {
this.pplRow = s;
}
}
Note that the naming of the methods is what defines the properties (since the backing field is private and technically doesn't have to exist). Your existing properties both don't match the names (pl instead of ppl) and don't have the proper capitalization.
Now add this annotation to your class:
#JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)
This tells Jackson to use snake_case for naming all of the properties. This should be enough to get your mapping working.

Related

Best Practices to create Message for Logging or Exception in Java

I found this code in Java 6.
String mensajeExcluido = ArqSpringContext.getPropiedad("MENSAJE.EXCLUIDO");
LOG.warn("ERROR: Servicio: " + mensajeExcluido + ":" + someDTO.getProperty() +
",\tsomeValue:" + someDTO.getValue() + "'.");
throw new Exception(mensajeExcluido);
this code
String mensajeExcluido = ArqSpringContext.getPropiedad("REGLA.MENSAJE");
String mensajeWarn = "ALERTA: Otro Servicio: " + mensajeExcluido + ":" +
someDTO.getProperty() + ",\tsomeValue:" + someDTO.getValue() + "'.";
LOG.warn(mensajeWarn);
boolean exclusionVisible = Boolean.valueOf(ArqSpringContext.getPropiedad("EXCLUSION.VISIBLE"));
if (exclusionVisible) {
mensajeWarn = "<br></br>" + mensajeWarn;
} else {
mensajeWarn = "";
}
throw new Exception(mensajeExcluido + mensajeWarn);
an this code
LOG.warn("No se pudo validar Client Service. Code: " +
someDTO.getStatusCode() + ".");
return "No se pudo validar Client Service. Code: " +
someDTO.getStatusCode() + ".";
In order to follow best practices...
What recommendations are applicable?
What changes would they make to the code?
How should texts be handled?
First, try to avoid message creation processing before checking if the log statement should be printed (I.e.: don't concatenate the messages strings before checking the log level.
// Better this
if (LOG.isDebugEnabled())
LOG.debug("This is a message with " + variable + " inside");
// Than this
final String message = "This is a message with " + variable + " inside";
if (LOG.isDebugEnabled())
LOG.debug(message);
Most Java logging frameworks allow a check to know in advance if a log statement is going to be printed based on the given settings.
If you want to save you the burden of writting those checks for each log statement, you can take advantage of Java 8 lambdas and code an utility like this:
import java.util.function.Supplier;
import java.util.logging.Logger;
import static java.util.logging.Level.FINE;
class MyLogger {
public static MyLogger of(final Class<?> loggerClass) {
return new MyLogger(loggerClass);
}
private final Logger logger;
private MyLogger(final Class<?> loggerClass) {
logger = Logger.getLogger(loggerClass.getName());
}
// Supplier will be evaluated AFTER checking if log statement must be executed
public void fine(final Supplier<?> message) {
if (logger.isLoggable(FINE))
logger.log(FINE, message.get().toString());
}
}
static final LOG = MyLogger.of(String.class);
public void example() {
LOG.fine(() -> "This is a message with a system property: " + System.getProperty("property"));
}
And finally, you can take advantage of Java string formatting to format log messages using String.format. I.e.:
final String message = String.format("Print %s string and %d digit", "str", 42);
Those good practices applied to the examples you provided would be:
/*
* Using java.util.logging in JDK8+
*/
import java.util.logging.Level;
import java.util.logging.Logger;
import static java.lang.String.format;
class Dto {
String getProperty() { return "property"; }
String getValue() { return "property"; }
String getStatusCode() { return "statusCode"; }
}
final Logger LOG = Logger.getGlobal();
final Dto someDTO = new Dto();
void example1() throws Exception {
String mensajeExcluido = System.getProperty("MENSAJE.EXCLUIDO");
// Check if log will be printed before composing the log message
if (LOG.isLoggable(Level.WARNING)) {
// Using String.format usually is clearer and gives you more formatting options
final String messageFormat = "ERROR: Servicio: %s:%s,\tsomeValue:%s'.";
LOG.warning(format(messageFormat, mensajeExcluido, someDTO.getProperty(), someDTO.getValue()));
}
// Or using lambdas
LOG.warning(() -> {
final String message = "ERROR: Servicio: %s:%s,\tsomeValue:%s'.";
return format(message, mensajeExcluido, someDTO.getProperty(), someDTO.getValue());
});
throw new Exception(mensajeExcluido);
}
void example2() throws Exception {
String mensajeExcluido = System.getProperty("REGLA.MENSAJE");
String mensajeWarn = format(
// The concatenated message is probably missing a single quote at 'someValue'
"ALERTA: Otro Servicio: %s:%s,\tsomeValue:%s'.",
mensajeExcluido,
someDTO.getProperty(),
someDTO.getValue()
);
LOG.warning(mensajeWarn);
boolean exclusionVisible = Boolean.parseBoolean(System.getProperty("EXCLUSION.VISIBLE"));
String exceptionMessage = exclusionVisible ?
mensajeExcluido + "<br></br>" + mensajeWarn : mensajeExcluido;
throw new Exception(exceptionMessage);
}
String example3() {
// You can compose the message only once and use it for the log and the result
String message =
format("No se pudo validar Client Service. Code: %s.", someDTO.getStatusCode());
LOG.warning(message);
return message;
}

uniVocity doesn't parse the first column into beans

I'm trying to read CSV files from GTFS.zip with help of uniVocity-parsers and run into an issue that I can't figure out. For some reason it seems the first column of some CSV files won't be parsed correctly. For example in the "stops.txt" file that looks like this:
stop_id,stop_name,stop_lat,stop_lon,location_type,parent_station
"de:3811:30215:0:6","Freiburg Stübeweg","48.0248455941735","7.85563688037231","","Parent30215"
"de:8311:30054:0:1","Freiburg Schutternstraße","48.0236251356332","7.72434519425597","","Parent30054"
"de:8311:30054:0:2","Freiburg Schutternstraße","48.0235446600679","7.72438739944883","","Parent30054"
The "stop_id" field won't be parsed correctly will have the value "null"
This is the method I'm using to read the file:
public <T> List<T> readCSV(String path, String file, BeanListProcessor<T> processor) {
List<T> content = null;
try {
// Get zip file
ZipFile zip = new ZipFile(path);
// Get CSV file
ZipEntry entry = zip.getEntry(file);
InputStream in = zip.getInputStream(entry);
CsvParserSettings parserSettings = new CsvParserSettings();
parserSettings.setProcessor(processor);
parserSettings.setHeaderExtractionEnabled(true);
CsvParser parser = new CsvParser(parserSettings);
parser.parse(new InputStreamReader(in));
content = processor.getBeans();
zip.close();
return content;
} catch (Exception e) {
e.printStackTrace();
}
return content;
}
And this is how my Stop Class looks like:
public class Stop {
#Parsed
private String stop_id;
#Parsed
private String stop_name;
#Parsed
private String stop_lat;
#Parsed
private String stop_lon;
#Parsed
private String location_type;
#Parsed
private String parent_station;
public Stop() {
}
public Stop(String stop_id, String stop_name, String stop_lat, String stop_lon, String location_type,
String parent_station) {
this.stop_id = stop_id;
this.stop_name = stop_name;
this.stop_lat = stop_lat;
this.stop_lon = stop_lon;
this.location_type = location_type;
this.parent_station = parent_station;
}
// --------------------- Getter --------------------------------
public String getStop_id() {
return stop_id;
}
public String getStop_name() {
return stop_name;
}
public String getStop_lat() {
return stop_lat;
}
public String getStop_lon() {
return stop_lon;
}
public String getLocation_type() {
return location_type;
}
public String getParent_station() {
return parent_station;
}
// --------------------- Setter --------------------------------
public void setStop_id(String stop_id) {
this.stop_id = stop_id;
}
public void setStop_name(String stop_name) {
this.stop_name = stop_name;
}
public void setStop_lat(String stop_lat) {
this.stop_lat = stop_lat;
}
public void setStop_lon(String stop_lon) {
this.stop_lon = stop_lon;
}
public void setLocation_type(String location_type) {
this.location_type = location_type;
}
public void setParent_station(String parent_station) {
this.parent_station = parent_station;
}
#Override
public String toString() {
return "Stop [stop_id=" + stop_id + ", stop_name=" + stop_name + ", stop_lat=" + stop_lat + ", stop_lon="
+ stop_lon + ", location_type=" + location_type + ", parent_station=" + parent_station + "]";
}
}
If I call the method i get this output which is not correct:
PartialReading pr = new PartialReading();
List<Stop> stops = pr.readCSV("VAGFR.zip", "stops.txt", new BeanListProcessor<Stop>(Stop.class));
for (int i = 0; i < 4; i++) {
System.out.println(stops.get(i).toString());
}
Output:
Stop [stop_id=null, stop_name=Freiburg Stübeweg, stop_lat=48.0248455941735, stop_lon=7.85563688037231, location_type=null, parent_station=Parent30215]
Stop [stop_id=null, stop_name=Freiburg Schutternstraße, stop_lat=48.0236251356332, stop_lon=7.72434519425597, location_type=null, parent_station=Parent30054]
Stop [stop_id=null, stop_name=Freiburg Schutternstraße, stop_lat=48.0235446600679, stop_lon=7.72438739944883, location_type=null, parent_station=Parent30054]
Stop [stop_id=null, stop_name=Freiburg Waltershofen Ochsen, stop_lat=48.0220902613143, stop_lon=7.7205756507492, location_type=null, parent_station=Parent30055]
Does anyone know why this happens and how I can fix it? This also happens in the "routes.txt" and "trips.txt" files that I tested.
This is the GTFS file : http://stadtplan.freiburg.de/sld/VAGFR.zip
If you print the headers you will notice that the first column doesn't look right. That's because you are parsing a file encoded using UTF-8 with a BOM marker.
Basically the file starts with a few bytes indicating what is the encoding. Until version 2.5.*, the parser didn't handle that internally, and you had to skip these bytes to get the correct output:
//... your code here
ZipEntry entry = zip.getEntry(file);
InputStream in = zip.getInputStream(entry);
if(in.read() == 239 & in.read() == 187 & in.read() == 191){
System.out.println("UTF-8 with BOM, bytes discarded");
}
CsvParserSettings parserSettings = new CsvParserSettings();
//...rest of your code here
The above hack will work on any version before 2.5.*, but you could also use Commons-IO provides a BOMInputStream for convenience and a more clean handling of this sort of thing - it's just VERY slow.
Updating to a recent version should take care of it automatically.
Hope it helps.

Get int, float, boolean and string from Properties

I have int, float, boolean and string from Properties file. Everything has loaded in Properties. Currently, I am parsing values as I know expected value for particular key.
Boolean.parseBoolean("false");
Integer.parseInt("3")
What is better way of setting these constants values, If I don't know what could be primitive value datatype for a key.
public class Messages {
Properties appProperties = null;
FileInputStream file = null;
public void initialization() throws Exception {
appProperties = new Properties();
try {
loadPropertiesFile();
} catch (Exception e) {
throw new Exception(e.getMessage(), e);
}
}
public void loadPropertiesFile() throws IOException {
String path = "./cfg/message.properties";
file = new FileInputStream(path);
appProperties.load(file);
file.close();
}
}
Properties File.
messassge.properties
SSO_URL = https://example.com/connect/token
SSO_API_USERNAME = test
SSO_API_PASSWORD = Uo88YmMpKUp
SSO_API_SCOPE = intraday_api
SSO_IS_PROXY_ENABLED = false
SSO_MAX_RETRY_COUNT = 3
SSO_FLOAT_VALUE = 3.0
Constant.java
public class Constants {
public static String SSO_URL = null;
public static String SSO_API_USERNAME = null;
public static String SSO_API_PASSWORD = null;
public static String SSO_API_SCOPE = null;
public static boolean SSO_IS_PROXY_ENABLED = false;
public static int SSO_MAX_RETRY_COUNT = 0;
public static float SSO_FLOAT_VALUE = 0;
}
If you have a class of configuration values, like your Constants class, and you want to load all values from a configuration (properties) file, you can create a little helper class and use reflection:
public class ConfigLoader {
public static void load(Class<?> configClass, String file) {
try {
Properties props = new Properties();
try (FileInputStream propStream = new FileInputStream(file)) {
props.load(propStream);
}
for (Field field : configClass.getDeclaredFields())
if (Modifier.isStatic(field.getModifiers()))
field.set(null, getValue(props, field.getName(), field.getType()));
} catch (Exception e) {
throw new RuntimeException("Error loading configuration: " + e, e);
}
}
private static Object getValue(Properties props, String name, Class<?> type) {
String value = props.getProperty(name);
if (value == null)
throw new IllegalArgumentException("Missing configuration value: " + name);
if (type == String.class)
return value;
if (type == boolean.class)
return Boolean.parseBoolean(value);
if (type == int.class)
return Integer.parseInt(value);
if (type == float.class)
return Float.parseFloat(value);
throw new IllegalArgumentException("Unknown configuration value type: " + type.getName());
}
}
Then you call it like this:
ConfigLoader.load(Constants.class, "/path/to/constants.properties");
You can extend the code to handle more types. You can also change it to ignore missing properties, instead of failing like it does now, such that assignments in the field declaration will remain unchanged, i.e. be the default.
If you know the type of constant, you can use Apache Commons Collections.
For example, you can use some utilities method based on type of your constant.
booelan SSO_IS_PROXY_ENABLED = MapUtils.getBooleanValue(appProperties, "SSO_IS_PROXY_ENABLED", false);
String SSO_URL = MapUtils.getString(appProperties, "SSO_URL", "https://example.com/connect/token");
You can even use default values to avoid errors.
Dambros is right, every thing you store inside a Properties file is as a String value.
You can track your different primitive data types after retrieving properties value as below like ref. -
Java Properties File: How to Read config.properties Values in Java?
package crunchify.com.tutorial;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.Properties;
/**
* #author Crunchify.com
*
*/
public class CrunchifyGetPropertyValues {
String result = "";
InputStream inputStream;
public String getPropValues() throws IOException {
try {
Properties prop = new Properties();
String propFileName = "config.properties";
inputStream = getClass().getClassLoader().getResourceAsStream(propFileName);
if (inputStream != null) {
prop.load(inputStream);
} else {
throw new FileNotFoundException("property file '" + propFileName + "' not found in the classpath");
}
Date time = new Date(System.currentTimeMillis());
// get the property value and print it out
String user = prop.getProperty("user");
String company1 = prop.getProperty("company1");
String company2 = prop.getProperty("company2");
String company3 = prop.getProperty("company3");
result = "Company List = " + company1 + ", " + company2 + ", " + company3;
System.out.println(result + "\nProgram Ran on " + time + " by user=" + user);
} catch (Exception e) {
System.out.println("Exception: " + e);
} finally {
inputStream.close();
}
return result;
}
}
and later convert to primitive -
How to convert String to primitive type value?
I suggest you to track your data types value by putting the key values inside String type switch statement and later retrieve the related data type value by using key name cases.
String type switch case is possible after Java 7.
Not entirely sure whether I exactly understand the problem but a possibility could be to include the type of the property value in the (String) value. So for example the properties you showed would become something like:
SSO_URL = URL:https://example.com/connect/token
SSO_API_USERNAME = STRING:test
SSO_API_PASSWORD = STRING:Uo88YmMpKUp
SSO_API_SCOPE = STRING:intraday_api
SSO_IS_PROXY_ENABLED = BOOLEAN:false
SSO_MAX_RETRY_COUNT = INTEGER:3
SSO_FLOAT_VALUE = FLOAT:3.0
During the parsing of the property values you first determine the type of the property by looking at the part before : and use the part after for the actual parsing.
private static Object getValue(Properties props, String name) {
String propertyValue = props.getProperty(name);
if (propertyValue == null) {
throw new IllegalArgumentException("Missing configuration value: " + name);
} else {
String[] parts = string.split(":");
switch(parts[0]) {
case "STRING":
return parts[1];
case "BOOLEAN":
return Boolean.parseBoolean(parts[1]);
....
default:
throw new IllegalArgumentException("Unknown configuration value type: " + parts[0]);
}
}
}
Follow the dropwizard configuration pattern where you define your constants using YAML instead of Properties and use Jackson to deserialize it into your Class. Other than type safety, dropwizard's configuration pattern goes one step further by allowing Hibernate Validator annotations to validate that the values fall into your expected ranges.
For dropwizard's example...
http://www.dropwizard.io/0.9.2/docs/getting-started.html#creating-a-configuration-class
For more information about the technology involved...
github.com/FasterXML/jackson-dataformat-yaml
hibernate.org/validator/
Spring Boot has ready to use and feature reach solution for type-safe configuration properties.
Definitely, use of the Spring just for this task is overkill but Spring has a lot of cool features and this one can attract you to right side ;)
You can define your configurable parameters as 'static' in your class of choice, and from a static init call a method that loads the parameter values from a properties file.
For example:
public class MyAppConfig {
final static String propertiesPath="/home/workspace/MyApp/src/config.properties";
static String strParam;
static boolean boolParam;
static int intParam;
static double dblParam;
static {
// Other static initialization tasks...
loadParams();
}
private static void loadParams(){
Properties prop = new Properties();
try (InputStream propStream=new FileInputStream(propertiesPath)){
// Load parameters from config file
prop.load(propStream);
// Second param is default value in case key-pair is missing
strParam=prop.getProperty("StrParam", "foo");
boolParam=Boolean.parseBoolean(prop.getProperty("boolParam", "false"));
intParam= Integer.parseInt(prop.getProperty("intParam", "1"));
dblParam=Double.parseDouble(prop.getProperty("dblParam", "0.05"));
} catch (IOException e) {
logger.severe(e.getMessage());
e.printStackTrace();
}
}
}
This might help:
props.getProperty("name", Integer.class);

ClassNotFoundException with readObject() method

I'm trying to read objects from a file in the Internet. I have been given the object class, which is this:
import java.io.Serializable;
public class Sulearvuti extends Arvuti implements Serializable {
private static final long serialVersionUID = 1L;
//isendiväli
private int aku;
//konstruktor
public Sulearvuti(String tootja, String mudel, String lisainfo,
int järjekorraNumber, int raskusaste, boolean kiirtellimus, int aku)
throws ValeRaskusAsteErind {
super(tootja, mudel, lisainfo, järjekorraNumber, raskusaste,
kiirtellimus);
this.aku = aku;
}
// meetod toString, kasutama ülemklassi meetodit
public String toString() {
return "Sülearvuti [aku=" + aku + ", " + super.toString() + "]";
}
// meetodi ülekatmine
double parandamiseAeg(){
return this.getRaskusaste()*2;
}
}
Now when I'm trying to read the objects (Sulearvuti), I get ClassNotFoundException. This is the piece of code :
ObjectInputStream ois =
new ObjectInputStream (
new URL("http://www.ut.ee/~marinai/sulearvutid.dat")
.openConnection()
.getInputStream());
int arv=ois.readInt();
Sulearvuti sülearvuti=(Sulearvuti)ois.readObject();
There's no problem with the Integer, but it won't recognize the class. I've been desperate for the past hour or so...
Also here's the code for the superclass "Arvuti":
import java.io.Serializable;
public class Arvuti implements Serializable, Comparable<Arvuti> {
private String tootja;
private String mudel;
private String lisainfo;
private int jrnumber;
private int vea_raskusaste;
private boolean kiirtellimus;
String getTootja() {
return tootja;
}
String getMudel() {
return mudel;
}
String getLisainfo() {
return lisainfo;
}
int getJrnumber() {
return jrnumber;
}
int getVea_raskusaste() {
return vea_raskusaste;
}
boolean isKiirtellimus() {
return kiirtellimus;
}
void setTootja(String tootja) {
this.tootja = tootja;
}
void setMudel(String mudel) {
this.mudel = mudel;
}
void setLisainfo(String lisainfo)throws WindowsXPErind {
this.lisainfo = lisainfo;
if(lisainfo.contains("WindowsXP"))throw new WindowsXPErind();
}
void setJrnumber(int jrnumber) {
this.jrnumber = jrnumber;
}
void setVea_raskusaste(int vea_raskusaste)throws ValeRaskusAsteErind {
if(vea_raskusaste<1 || vea_raskusaste>10) throw new ValeRaskusAsteErind();
this.vea_raskusaste = vea_raskusaste;
}
void setKiirtellimus(boolean kiirtellimus) {
this.kiirtellimus = kiirtellimus;
}
Arvuti(String tootja, String mudel, String lisainfo, int jrnumber,
int vea_raskusaste, boolean kiirtellimus)throws ValeRaskusAsteErind {
try{
setTootja( tootja);
setMudel(mudel);
setJrnumber(jrnumber);
setVea_raskusaste(vea_raskusaste);
setKiirtellimus(kiirtellimus);
setLisainfo(lisainfo);
}
catch (WindowsXPErind e){
System.out.println("WindowsXPErind");
setVea_raskusaste(vea_raskusaste+2);
}
}
double parandamiseAeg(){
return getVea_raskusaste()*1.5;
}
public String toString() {
return "Arvuti [tootja=" + tootja + ", mudel=" + mudel + ", lisainfo="
+ lisainfo + ", järjekorranumber=" + jrnumber + ", vea raskusaste="
+ vea_raskusaste + ", kiirtellimus=" + kiirtellimus
+ ", parandamise aeg=" + parandamiseAeg() + "]";
}
public int compareTo(Arvuti arvuti){
if(this.isKiirtellimus()==true && arvuti.isKiirtellimus()==false) return -1;
else if(this.isKiirtellimus()==false && arvuti.isKiirtellimus()==true) return 1;
else{
if(this.getJrnumber()<arvuti.getJrnumber())return -1;
else if(this.getJrnumber()>arvuti.getJrnumber())return 1;
else return 0;
}
}
}
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
Unhandled exception type ClassNotFoundException
at Peaklass.main(Peaklass.java:36)
You are missing some classes contained in the .dat file. Lookout for the classname shown in the classnotfound exception.
It is not sufficient to have the "Sulearvuti", you also need "Arvuti" (superclass) and "ValeRaskusAsteErind" (Exception) in your classpath.
BTW the language looks very funny to me, what language is this ?
Is "Sulearvuti" class on the classpath of the application trying to deserialize the object?

How to get rid of PlaceHistoryMapper

Are there any way not to define all Places in the PlaceHistoryMapper?
At this moment I am using Generator in order to generate list of all places automatically, but I am not sure that this is a correct way.
public class AppPlaceHistoryMapper extends AbstractPlaceHistoryMapper<Object> {
#Override
protected PrefixAndToken getPrefixAndToken(Place place) {
if (place instanceof AbstractPlace) {
return new PrefixAndToken(((AbstractPlace) place).getName(), ((AbstractPlace) place).getTokenizer()
.getToken((AbstractPlace) place));
}
throw new RuntimeException("Invalid place: " + place);
}
/**
* This method will be overrided by the gwt-generated class, so any changes made in it will not be executed
*
* #see PlaceMapperGenerator
*/
#Override
protected PlaceTokenizer<?> getTokenizer(String prefix) {
AbstractPlace[] places = {/* List of places generated by PlaceMapperGenerator */};
for (AbstractPlace p : places) {
if (p.getName().equals(prefix)) {
return p.getTokenizer();
}
}
throw new RuntimeException("Unable to find place for provided prefix: " + prefix);
}
}
Generator:
public class PlaceMapperGenerator extends Generator {
// #formatter:off
private static final String GENERATED_METHOD_TEMPLATE =
"protected com.google.gwt.place.shared.PlaceTokenizer<?> getTokenizer(String prefix) {" +
"AbstractPlace[] places = { %s };" +
"for (AbstractPlace p : places) {" +
"if (p.getName().equals(prefix)) {" +
"return p.getTokenizer();" +
"}" +
"}" +
"throw new RuntimeException(\"Unable to find place for provided prefix: \" + prefix);" +
"}"
; // #formatter:on
#Override
public String generate(TreeLogger logger, GeneratorContext context, String typeName) {
JClassType type;
try {
type = context.getTypeOracle().getType(typeName);
} catch (NotFoundException e) {
throw new RuntimeException(e);
}
String implTypeName = type.getSimpleSourceName() + "Impl";
String implPackageName = type.getPackage().getName();
ClassSourceFileComposerFactory composerFactory = new ClassSourceFileComposerFactory(implPackageName,
implTypeName);
composerFactory.setSuperclass(AppPlaceHistoryMapper.class.getName());
#SuppressWarnings("resource")
PrintWriter printWriter = context.tryCreate(logger, implPackageName, implTypeName);
if (printWriter != null) {
SourceWriter sourceWriter = composerFactory.createSourceWriter(context, printWriter);
sourceWriter.print(GENERATED_METHOD_TEMPLATE, getPlaces(context));
sourceWriter.commit(logger);
printWriter.close();
}
return composerFactory.getCreatedClassName();
}
private static String getPlaces(GeneratorContext context) {
JPackage[] packages = context.getTypeOracle().getPackages();
List<String> places = new ArrayList<String>();
for (JPackage p : packages) {
if (p.getName().startsWith(AbstractPlace.class.getPackage().getName())) {
JClassType[] types = p.getTypes();
for (JClassType type : types) {
if (type.getSuperclass() != null
&& type.getSuperclass().getQualifiedSourceName().equals(AbstractPlace.class.getName())) {
places.add("new " + type.getQualifiedSourceName() + "()");
}
}
}
}
return places.toString().replaceAll("^\\[|\\]$", "");
}
}
I'm afraid that the only way to figure out what Places and Tokenizers are in your application, without maintaining a list with them, is with a generator like you are doing.
Anyway instead of maintaining a generator I would use the #WithTokenizers annotation and let GWT generate your PlaceHistoryMapper take a look to the GWT MVP dev-guide
#WithTokenizers({HelloPlace.Tokenizer.class, GoodbyePlace.Tokenizer.class})
public interface AppPlaceHistoryMapper extends PlaceHistoryMapper {}
What I do in my applications is to use a script to generate activities, views, places and update gin modules and mappers based on a template.

Categories

Resources