Simple Cache mechanizm using decorators - java

I have a simple interface
public interface Text {
String asText() throws IOException;
}
And one implementation
public final class TextFromFile implements Text{
private final String path;
public TextFromFile(final String pth) {
this.path = pth;
}
#Override
public String asText() throws IOException {
final String text = Files.readAllLines(Paths.get(this.path))
.stream()
.collect(Collectors.joining(""));
return text;
}
}
This class is very simple, it reads text from a file then returns it as a string. In order to avoid reading from the file multiple times I want to create a second class that will decorate the original one
public final class CachedText implements Text{
private final Text origin;
private String result;
public CachedText(final Text orgn) {
this.origin = orgn;
}
#Override
public String asText() throws IOException {
if(this.result == null){
this.result = this.origin.asText();
}
return this.result;
}
}
And now it work; however the result is muttable, and in order to work correctly with multiple threads i have created another decorator
public final class ThreadSafeText implements Text{
private final Text origin;
public ThreadSafeText(final Text orgn) {
this.origin = orgn;
}
#Override
public String asText() throws IOException {
synchronized(this.origin){
return this.origin.asText();
}
}
}
But now my program will spend resources on synchronization each time I call asText() .
What is the best implementation of a caching mechanism in my situation?

I would suggest making your cached class synchronized via the Double Check Lock mechanism, instead of using the additional implementation for thread safety:
public final class CachedText implements Text{
private final Text origin;
private String result;
public CachedText(final Text orgn) {
this.origin = orgn;
}
#Override
public String asText() throws IOException {
if(this.result == null){
synchronized(this) {
if(this.result == null){
this.result = this.origin.asText();
}
}
}
return this.result;
}
}
There might be concerns using the DCL as seen here- but if they exist on your end, just comment and I'll post additional support (I believe that modern JVMs are better suited for handling DCLs).
This should be good for your needs.

Related

Calling Methods in Java Constructor For Boolean Value

I'm currently doing dev on an inherited Spring boot app, part of it is sending an API POST request with the boolean of whether a soccer match is finished or not (resulted). I noticed that the design of the class was such:
//parent class
public class Fixture {
private final FixtureType type;
private final Team homeTeam;
private final Team awayTeam;
public Fixture(#JsonProperty("type") final FixtureType type,
#JsonProperty("homeTeam") final Team homeTeam,
#JsonProperty("awayTeam") final Team awayTeam
) {
this.type = type;
this.homeTeam = homeTeam;
this.awayTeam = awayTeam;
}
public boolean isResulted() {
return false;
}
/*
other methods
*/
}
//child class
public class Result extends Fixture {
private final Outcome outcome;
public Result(#JsonProperty("type") final FixtureType type,
#JsonProperty("homeTeam") final Team homeTeam,
#JsonProperty("awayTeam") final Team awayTeam,
#JsonProperty("outcome") final Outcome outcome) {
super(type, homeTeam, awayTeam);
this.outcome = outcome;
}
#Override
public boolean isResulted() {
return true;
}
/*
other methods
*/
}
In the Swagger documentation, the request specifies that "resulted": true needs to be a field in the JSON POST request. Now I can add that field into the constructor, but that would mean changing a load of tests and code that calls this constructor. My solution was to call the isResulted() method in the constructor itself. I've never done this before, but this works. Is there any reason that this design below would create issues in the long run?
public class Result extends Fixture {
private final boolean resulted;
public Result (){
super();
resulted = isResulted();
}
#Override
#JsonProperty("resulted")
public boolean isResulted() {
return true;
}
}
I don't understand what's the purpose of having a private field that is not used anywhere. I'm also not sure I understand the problem you'd like to have solved.
There's a possible approach that is both more flexible and compatible with your previous code:
public class Result extends Fixture {
private final boolean resulted;
public Result (boolean resulted){
super();
this.resulted = resulted;
}
public Result (){
this(true); // sets the default value
}
#Override
#JsonProperty("resulted")
public boolean isResulted() {
return resulted;
}
}

How to retrieve a constant value by providing a string?

Considering this class
package com.bluegrass.core;
public class Constants {
public static final String AUTHOR="bossman";
public static final String COMPANY="Bluegrass";
//and many more constants below
}
I want to create a function that goes like this:
getConstantValue("AUTHOR") //this would return "bossman"
Any ideas how this can be done?
You can use reflection:
public static String getConstantValue(String name) {
try {
return (String) Constants.class.getDeclaredField(name).get(null);
} catch (Exception e) {
throw new IllegalArgumentException("Constant value not found: " + name, e);
}
}
UPDATE: Enum solution.
If you can change the Constants class to be an enum, it would be like this instead:
private static String getConstantValue(String name) {
return Constants.valueOf(name).getText();
}
But that requires something like this for Constants:
public enum Constants {
AUTHOR("bossman"),
COMPANY("Bluegrass");
private final String text;
private Constants(String text) {
this.text = text;
}
public String getText() {
return this.text;
}
}
Probably the simplest solution (and also work with enums instead of String is typesafe) is to work with enum, provided you are able to change the public static final fields into an enum.
public enum Constants {
AUTHOR("bossman"),
COMPANY("Bluegrass");
private final String content;
Constants (String content) {
this.content= content;
}
public String getContent() {
return content;
}
public static Constants getConstant(String content) {
for (Constants constant : Constants.values()) {
if (constant.getContent().equals(content)) {
return constant;
}
}
return null; //default value
}
}
Usage:
Constants.valueOf("AUTHOR") == Constants.AUTHOR
Constants.getConstant("bossman") == Constants.AUTHOR
Constants.AUTHOR.getContent() == "bossman"
So instead of OP's getConstantValue("AUTHOR") it would be Constants.valueOf("AUTHOR").getContent()
There is a multitude of methods to solve this.
One way is to use a switch.
Example:
public String foo(String key) throws AnException {
switch (key) {
case case1:
return constString1;
case case2:
return constString2;
case case3:
return constString3;
...
default:
throws NotValidKeyException; //or something along these lines
}
}
The other method is to create a map<string,string> and fill it with the desired key,pairs.

Using POJOs as model layer in JavaFX application

I'm creating simple JavaFX application. I want my model layer to be completely independent from JavaFX - no StringProperty, IntegerProperty and etc. as fields. I want it to be POJO. Main reason to do so is that I want it to be Serializable.
I've created DataRepository - simple CRUD-like interface and some implementations of it, so I can at anytime change where I store my data - XML file, SQLite database or anything else. I also have to somehow connect my data storage with JavaFX (to display its content in TableView), so I decided to create my implementation of ObservableList which wraps my repository. My question is - is there any other way? ObservableList contains about 30 methods to implement and it looks like I'm doing something wrong.
My (simplified) model:
public class Movie implements Serializable {
private String title;
private String director;
public Movie() {
}
public Movie(String title, String director) {
this.title = title;
this.director = director;
}
// Getters and setters, equals etc...
}
MovieRepository:
public interface MovieRepository {
public void add(Movie movie);
public void remove(String title);
public void remove(int index);
public Movie get(String title);
public Movie get(int index);
public List<Movie> getAll();
}
Controller for my main view:
public class MainController {
#FXML
private TableView<Movie> movieTable;
#FXML
private TableColumn<Movie, String> movieTitleColumn;
#FXML
private Label titleLabel;
private MovieRepository movies = new DBMovieRepository(); //MovieRepository implementation which uses SQLite DB to store data
private MainApp app;
#FXML
private void initialize() {
movieTable.setItems(new ObservableMovies(movies));
// ObservableMovies is my implementation of ObservableList
// It basically wraps methods from MovieRepository
// and notifies listeners
showMovieDetails(null);
movieTitleColumn.setCellValueFactory(cellData -> new ReadOnlyStringWrapper(cellData.getValue().getTitle()));
movieTable.getSelectionModel().selectedItemProperty()
.addListener((observable, oldValue, newValue) -> showMovieDetails(newValue));
}
private void showMovieDetails(Movie movie) {
if(movie != null) {
titleLabel.setText(movie.getTitle());
} else {
titleLabel.setText("");
}
}
#FXML
private void handleNew() {
Movie movie = new Movie();
app.showNewMovieDialog(movie);
movieTable.getItems().add(movie);
}
public void setApp(MainApp app) {
this.app = app;
}
}
You have a couple of options here (maybe more), which are covered in other questions on this site. However, for convenience, I'll summarize them here too.
1. Use JavaFX Properties and make the class Serializable
You can do this with a custom serialized form. Make the JavaFX properties transient and implement readObject and writeObject to store the values they wrap:
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Objects;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
public class Movie implements Serializable {
private transient StringProperty title = new SimpleStringProperty();
private transient StringProperty director = new SimpleStringProperty();
public Movie() {
}
public Movie(String title, String director) {
setTitle(title);
setDirector(director);
}
#Override
public int hashCode() {
return Objects.hash(getDirector(), getTitle());
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Movie other = (Movie) obj;
return Objects.equals(getTitle(), other.getTitle())
&& Objects.equals(getDirector(), other.getDirector());
}
public final StringProperty titleProperty() {
return this.title;
}
public final String getTitle() {
return this.titleProperty().get();
}
public final void setTitle(final String title) {
this.titleProperty().set(title);
}
public final StringProperty directorProperty() {
return this.director;
}
public final String getDirector() {
return this.directorProperty().get();
}
public final void setDirector(final String director) {
this.directorProperty().set(director);
}
private void readObject(ObjectInputStream s) throws ClassNotFoundException, IOException {
s.defaultReadObject();
title = new SimpleStringProperty((String) s.readObject());
director = new SimpleStringProperty((String) s.readObject());
}
private void writeObject(ObjectOutputStream s) throws IOException {
s.defaultWriteObject();
s.writeObject(getTitle());
s.writeObject(getDirector());
}
}
2. Use a POJO with "bound properties".
See JavaBean wrapping with JavaFX Properties for details. In brief:
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
public class Movie {
private String title ;
private String director ;
private final PropertyChangeSupport propertySupport ;
public Movie(String title, String director) {
this.title = title ;
this.director = director ;
this.propertySupport = new PropertyChangeSupport(this);
}
public Movie() {
this("", "");
}
public String getTitle() {
return title ;
}
public String setTitle(String title) {
String oldTitle = this.title ;
this.title = title ;
propertySupport.firePropertyChange("title", oldTitle, title);
}
// similarly for director...
public void addPropertyChangeListener(PropertyChangeListener listener) {
propertySupport.addPropertyChangeListener(listener);
}
// hashCode and equals...
}
For wanting to wrap your repository as an observable list, instead wrap it with a repository implementation that uses an observable list:
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
public class ObservableMovieRepository implements MovieRepository {
private final MovieRepository repository ;
private final ObservableList<Movie> movieList;
public ObservableMovieRepository(MovieRepository repository) {
this.repository = repository ;
this.movieList = FXCollections.observableArrayList(repository.getAll());
}
#Override
public void add(Movie movie) {
repository.add(movie);
movieList.add(movie);
}
#Override
public void remove(String title) {
Movie movie = get(title);
repository.remove(title);
movieList.remove(title);
}
#Override
public void remove(int index) {
repository.remove(index);
movieList.remove(index);
}
#Override
public Movie get(String title) {
return repository.get(title);
}
#Override
public Movie get(int index) {
return movieList.get(index);
}
#Override
public ObservableList<Movie> getAll() {
return movieList ;
}
}
This uses the standard ObservableList implementation that copies an existing list on creation, and the implementation keeps that list in sync with the list in the wrapped repository. Now your UI code can do
ObservableMovieRepository movies = new ObservableMovieRepository(new DBMovieRepository());
// ...
movieTable.setItems(movies.getAll());
With the Movie class above, you would just do
movieTitleColumn.setCellValueFactory(cellData -> cellData.getValue().titleProperty());
If you use the POJO version you can do
movieTitleColumn.setCellValueFactory(cellData -> {
try {
return new JavaBeanStringPropertyBuilder()
.bean(cellData.getValue())
.name("title")
.build();
} catch (Exception e) { throw new RuntimeException(e); }
}
There seem to be multiple question in here, so I'm not really sure, if I understood you correctly, but I will try to split it up a bit.
I want my model layer to be completely independent from JavaFX - no
StringProperty, IntegerProperty and etc. as fields. I want it to be
POJO.
You could mark your properties as transient. Then you just need to wrap them around your values and it will be both JavaFX compliant and Serializable. You just have to propagate changes back to your backing attributes.
I also have to somehow connect my data storage with JavaFX (to display
its content in TableView), so I decided to create my implementation of
ObservableList which wraps my repository. My question is - is there
any other way?
Very limited information on this and I really don't know, why you would need to create your own implementation of ObservableList, but to keep it POJO, you could maintain plain java.util.Collections in your bean and provide transient ObservableLists, which you can create on creation by wrapping your java.util.Lists in your POJO. You can find those methods in the FXCollections utility class.
ObservableList contains about 30 methods to implement and it looks
like I'm doing something wrong.
If you really need to implement it, you can inherit from ObservableListBase.

Validate an XML against an XSD in Java / Getting a hold of the schemaLocation

How can one validate an XML file using an XSD in Java? We don't know the schema in advance. I would like to be able to get the schemaLocation, download the XSD, cache it and then perform the actual validation.
The problem is, that with javax.xml.parsers.DocumentBuilder/DocumentBuilderFactory classes I can't seem to be able to get a hold of the schemaLocation in advance. What's the trick for this? Which classes should I look into?
Perhaps there's a more suitable API I can use? The whole problem is that we need to validate dynamically, without (necessarily) having the XSDs locally.
How could one get a hold of the URL of schemaLocation defined in the XSD file?
I know you can set features/attributes, but that's a different thing. I need to get the schemaLocation from the XSD first.
Please advise!
Given that you are using Xerces (or JDK default), have you tried setting this feature to true on the factory: http://apache.org/xml/features/validation/schema. There are other features that you can play with regarding schemas: http://xerces.apache.org/xerces2-j/features.html
UPDATE 2 (for caching):
Implement a org.w3c.dom.ls.LSResourceResolver and set this on the SchemaFactory using the setResourceResolver method. This resolver would either get the schema from cache or fetch it from wherever the location refers to.
UPDATE 3:
LSResourceresolver example (which I think will be a good starting point for you):
/**
* Resolves resources from a base URL
*/
public class URLBasedResourceResolver implements LSResourceResolver {
private static final Logger log = LoggerFactory
.getLogger(URLBasedResourceResolver.class);
private final URI base;
private final Map<URI, String> nsmap;
public URLBasedResourceResolver(URL base, Map<URI, String> nsmap)
throws URISyntaxException {
super();
this.base = base.toURI();
this.nsmap = nsmap;
}
#Override
public LSInput resolveResource(String type, String namespaceURI,
String publicId, String systemId, String baseURI) {
if (log.isDebugEnabled()) {
String msg = String
.format("Resolve: type=%s, ns=%s, publicId=%s, systemId=%s, baseUri=%s.",
type, namespaceURI, publicId, systemId, baseURI);
log.debug(msg);
}
if (type.equals(XMLConstants.W3C_XML_SCHEMA_NS_URI)) {
if (namespaceURI != null) {
try {
URI ns = new URI(namespaceURI);
if (nsmap.containsKey(ns))
return new MyLSInput(base.resolve(nsmap.get(ns)));
} catch (URISyntaxException e) {
// ok
}
}
}
return null;
}
}
The implementation of MyLSInput is really boring:
class MyLSInput implements LSInput {
private final URI url;
public MyLSInput(URI url) {
super();
this.url = url;
}
#Override
public Reader getCharacterStream() {
return null;
}
#Override
public void setCharacterStream(Reader characterStream) {
}
#Override
public InputStream getByteStream() {
return null;
}
#Override
public void setByteStream(InputStream byteStream) {
}
#Override
public String getStringData() {
return null;
}
#Override
public void setStringData(String stringData) {
}
#Override
public String getSystemId() {
return url.toASCIIString();
}
#Override
public void setSystemId(String systemId) {
}
#Override
public String getPublicId() {
return null;
}
#Override
public void setPublicId(String publicId) {
}
#Override
public String getBaseURI() {
return null;
}
#Override
public void setBaseURI(String baseURI) {
}
#Override
public String getEncoding() {
return null;
}
#Override
public void setEncoding(String encoding) {
}
#Override
public boolean getCertifiedText() {
return false;
}
#Override
public void setCertifiedText(boolean certifiedText) {
}
}

Json Jackson deserialization without inner classes

I have a question concerning Json deserialization using Jackson.
I would like to deserialize a Json file using a class like this one:
(taken from http://wiki.fasterxml.com/JacksonInFiveMinutes)
public class User
{
public enum Gender { MALE, FEMALE };
public static class Name {
private String _first, _last;
public String getFirst() { return _first; }
public String getLast() { return _last; }
public void setFirst(String s) { _first = s; }
public void setLast(String s) { _last = s; }
}
private Gender _gender;
private Name _name;
private boolean _isVerified;
private byte[] _userImage;
public Name getName() { return _name; }
public boolean isVerified() { return _isVerified; }
public Gender getGender() { return _gender; }
public byte[] getUserImage() { return _userImage; }
public void setName(Name n) { _name = n; }
public void setVerified(boolean b) { _isVerified = b; }
public void setGender(Gender g) { _gender = g; }
public void setUserImage(byte[] b) { _userImage = b; }
}
A Json file can be deserialized using the so called "Full Data Binding" in this way:
ObjectMapper mapper = new ObjectMapper();
User user = mapper.readValue(new File("user.json"), User.class);
My problem is the usage of the inner class "Name". I would like to do the same thing without using inner classes. The "User" class would became like that:
import Name;
import Gender;
public class User
{
private Gender _gender;
private Name _name;
private boolean _isVerified;
private byte[] _userImage;
public Name getName() { return _name; }
public boolean isVerified() { return _isVerified; }
public Gender getGender() { return _gender; }
public byte[] getUserImage() { return _userImage; }
public void setName(Name n) { _name = n; }
public void setVerified(boolean b) { _isVerified = b; }
public void setGender(Gender g) { _gender = g; }
public void setUserImage(byte[] b) { _userImage = b; }
}
This means to find a way to specify to the mapper all the required classes in order to perform the deserialization.
Is this possible? I looked at the documentation but I cannot find any solution.
My need comes from the fact that I use the Javassist library to create such classes, and it does not support inner or anonymous classes.
Thank you in advance
There should be no difference between the static inner class Name, and the top-level class of the same name. The Jackson runtime should not be able to meaningfully distinguish between the two situations.
Have you tried moving the Name class out of User, changing it into a top-level class? It should still work as before.
edit: I just tried this, and it works fine when Name is a top-level class. The example had it as an inner class for the sake of brevity, I suspect.
mr. Skaffman's answer is right on. The only additional thing to mention is that unlike JAXB, Jackson does not generally require you to specify classes you operate on, except for the root class (and not always even that, if you use Polymorphic Handling).

Categories

Resources