Conflict Between StaticWriter and Writer Classes - java

As of our recent move from WSED 5.2 to RAD 7.5, an application-wrecking bug has appeared in our code.
RAD 7.5 marks it thusly, all at the declaration of the class header (public class FoStringWriter extends StringWriter implements FoWriter {)
- Exception IOException in throws clause of Writer.append(CharSequence, int, int) is not compatable with StringWriter.append(CharSequence, int, int)
- Exception IOException in throws clause of Writer.append(char) is not compatable with StringWriter.append(char)
- Exception IOException in throws clause of Writer.append(CharSequence) is not compatable with StringWriter.append(CharSequence)
Every piece of literature I have been able to find on the web points to this being a 'bug' in Eclipse, yet my developer should already have the most recent version of Eclipse software on it. So I am left not knowing what to make of this error. Is there a fix from IBM that I simply haven't yet updated to? Or is there a code-fix that could rectify this error?
public class FoStringWriter extends StringWriter implements FoWriter {
public void filteredWrite(String str) throws IOException {
FoStringWriter.filteredWrite(str,this);
}
public static void filteredWrite(String str, StringWriter writer) throws IOException {
if (str == null) str = "";
TagUtils tagUtils = TagUtils.getInstance();
str = tagUtils.filter(str);
HashMap dictionary = new HashMap();
dictionary.put("&#","&#");
str = GeneralUtils.translate(str,dictionary);
writer.write(str);
}
}
Editory Note:
The process that this runs creates PDF documents for our app. In WSED 5.5, it worked, had a few errors but nothing that stopped the PDF from being written.

Slap me in the forehead, because this is another "Error" solved by a seemingly completely obvious answer.
Just by adding the listed methods that throw "errors", I can eliminate the error throwing when calling this class.
Copying them straight from StringWriter actually worked, without editing them in any way.
public StringWriter append(char c) {
write(c);
return this;
}
public StringWriter append(CharSequence csq) {
if (csq == null)
write("null");
else
write(csq.toString());
return this;
}
public StringWriter append(CharSequence csq, int start, int end) {
CharSequence cs = (csq == null ? "null" : csq);
write(cs.subSequence(start, end).toString());
return this;
}
I'm both pleased that this worked, and at the same time frustrated that it was so glaringly simple a fix that it took nearly a full week to figure out.
I suppose the reason behind this error was likely a conflict in implementation. FoStringWriter extends StringWriter, but that itself extends Writer, and both classes have their own "append" methods that overwrite one another. By creating them explicitly, this error is resolved.

Related

Who throws AssertionError in JAVA? JVM or by API developer/Programmer?

I learning exception handling in JAVA, I found that exceptions/errors can also be classified on the basis of who throws or raises it.
Exceptions raised by JVM
Exceptions raised by API developer/programmer
My question is who is responsible for raising AssertionError?
The responsibility lies at the programmer regardless of whether they use, e.g.
throw new AssertionError("unreachable code");
or
assert condition;
Note that the assert statement is so called “syntactic sugar”.
When you write
class ClassWithAssert {
public ClassWithAssert() {
assert toString() != null;
}
}
It gets compiled to the equivalent of
class ClassWithAssert {
static final boolean $assertionsDisabled
= !ClassWithAssert.class.desiredAssertionStatus();
public ClassWithAssert() {
if(!$assertionsDisabled && toString() == null)
throw new AssertionError();
}
}
So the implicit throwing is not different to the explicit one, technically.

Test throws NullPointerException instead of RandomCustomException, but only in some environments

I am working on a project with more people and branches. There is a test, written by someone else, which weirdly passes in some of the environments and fails in some other ones.
We are working on separate branches but we made sure that we see the same version of the project with
git pull origin develop
The code looks like:
#Test(expected = RandomCustomException.class)
public void saveReturnsWithCustomException() throws
RandomCustomException {
xService.save(notValidX);
}
In some environments it throws a NullPointerException, thus fails, in some other ones it throws a RandomCustomException.
We've checked it, and it's weird, but all the related codes seem to be exactly the same in all the environments.
My xService looks like:
public X saveX(X x) throws RandomCustomException {
if (!validXName(X.getName())) {
throw new RandomCustomException("The given name wasn't correct or the field is empty!");
}
return xRepository.save(x);
xRepository is mocked in the test.
xRepository:
public interface xRepository extends JpaRepository<X, Long> {
X findByApplicationUser(ApplicationUser applicationUser);
}
Does anyone have a suggestion what can the problem be?
The problem is that in this method the x variable is not gurantied to be Not Null so it probably is giving the NullPointerException when you call the method getName.
public X saveX(X x) throws RandomCustomException {
if (!validXName(X.getName())) {
throw new RandomCustomException("The given name wasn't correct or the field is empty!");
}
return xRepository.save(x);
I can only speculate the cause might be if 'x' is a bean. It might not meet all the requirements in this environment to instantiate. You can try turning the logs to debug is look for it.

Using monads in Springboot application to catch exceptions

So our project back-end is a Java 8 Springboot application, springboot allows you to do some stuff really easily. ex, request validation:
class ProjectRequestDto {
#NotNull(message = "{NotNull.DotProjectRequest.id}")
#NotEmpty(message = "{NotEmpty.DotProjectRequest.id}")
private String id;
}
When this constraint is not meet, spring (springboot?) actually throws a validation exception, as such, we catch it somewhere in the application and construct a 404 (Bad Request) response for our application.
Now, given this fact, we kinda followed the same philosophy throughout our application, that is, on a deeper layer of the application we might have something like:
class ProjectService throws NotFoundException {
DbProject getProject(String id) {
DbProject p = ... // some hibernate code
if(p == null) {
Throw new NotFoundException();
}
return p;
}
}
And again we catch this exception on a higher level, and construct another 404 for the client.
Now, this is causing a few problems:
The most important one: Our error tracing stops being useful, we cannot differentiate (easily) when the exception is important, because they happen ALL the time, so if the service suddenly starts throwing errors we would not notice until it is too late.
Big amount of useless logging, on login requests for example, user might mistyped his password, and we log this and as a minor point: our analytics cannot help us determine what we are actually doing wrong, we see a lot of 4xx's but that is what we expect.
Exceptions are costly, gathering the stack trace is a resource intensive task, minor point at this moment, as the service scales up with would become more of a problem.
I think the solution is quite clear, we need to make an architectural change to not make exceptions part of our normal data flow, however this is a big change and we are short on time, so we plan to migrate over time, yet the problem remains for the short term.
Now, to my actual question: when I asked one of our architects, he suggested the use of monads (as a temporal solution ofc), so we don't modify our architecture, but tackle the most contaminating endpoints (ex. wrong login) in the short term, however I'm struggling with the monad paradigm overall and even more in java, I really have no idea on how to apply it to our project, could you help me with this? some code snippets would be really good.
TL:DR: If you take a generic spring boot application that throws errors as a part of its data flow, how can you apply the monad pattern to avoid login unnecessary amount of data and temporarily fix this Error as part of data flow architecture.
The standard monadic approach to exception handling is essentially to wrap your result in a type that is either a successful result or an error. It's similar to the Optional type, though here you have an error value instead of an empty value.
In Java the simplest possible implementation is something like the following:
public interface Try<T> {
<U> Try<U> flatMap(Function<T, Try<U>> f);
class Success<T> implements Try<T> {
public final T value;
public Success(T value) {
this.value = value;
}
#Override
public <U> Try<U> flatMap(Function<T, Try<U>> f) {
return f.apply(value);
}
}
class Fail<T> implements Try<T> {
// Alternatively use Exception or Throwable instead of String.
public final String error;
public Fail(String error) {
this.error = error;
}
#Override
public <U> Try<U> flatMap(Function<T, Try<U>> f) {
return (Try<U>)this;
}
}
}
(with obvious implementations for equals, hashCode, toString)
Where you previously had operations that would either return a result of type T or throw an exception, they would return a result of Try<T> (which would either be a Success<T> or a Fail<T>), and would not throw, e.g.:
class Test {
public static void main(String[] args) {
Try<String> r = ratio(2.0, 3.0).flatMap(Test::asString);
}
static Try<Double> ratio(double a, double b) {
if (b == 0) {
return new Try.Fail<Double>("Divide by zero");
} else {
return new Try.Success<Double>(a / b);
}
}
static Try<String> asString(double d) {
if (Double.isNaN(d)) {
return new Try.Fail<String>("NaN");
} else {
return new Try.Success<String>(Double.toString(d));
}
}
}
I.e. instead of throwing an exception you return a Fail<T> value which wraps the error. You can then compose operations which might fail using the flatMap method. It should be clear that once an error occurs it will short-circuit any subsequent operations - in the above example if ratio returns a Fail then asString doesn't get called and the error propagates directly through to the final result r.
Taking your example, under this approach it would look like this:
class ProjectService throws NotFoundException {
Try<DbProject> getProject(String id) {
DbProject p = ... // some hibernate code
if(p == null) {
return new Try.Fail<DbProject>("Failed to create DbProject");
}
return new Try.Succeed<DbProject>(p);
}
}
The advantage over raw exceptions is it's a bit more composable and allows, for example, for you to map (e.g. Stream.map) a fail-able function over a collection of values and end up with a collection of Fails and Successes. If you were using exceptions then the first exception would fail the entire operation and you would lose all results.
One downside is that you have to use Try return types all the way down your call stack (somewhat like checked exceptions). Another is that since Java doesn't have built-in monad support (al la Haskell & Scala) then the flatMap'ing can get slightly verbose. For example something like:
try {
A a = f(x);
B b = g(a);
C c = h(b);
} catch (...
where f, g, h might throw, becomes instead:
Try<C> c = f(x).flatMap(a -> g(a))
.flatMap(b -> h(b));
You can generalise the above implementation by making the error type an generic parameter E (instead of String), so it then becomes Try<T, E>. whether this is useful depends on your requirements - I've never needed it.
I have a more fully-implemented version here, alternatively the Javaslang and FunctionalJava libraries offer their own variants.

PowerkMock-ing BufferedReader runs interminately

What I want to do is to mock newly created instance of BufferedReader. Here's the code that should be tested:
A.java
...
#Override
public String read(String fileName) throws IOException {
...
try {
fileReader = new FileReader(fileName);
bufferedReader = new BufferedReader(fileReader);
String tmp;
StringBuilder builder = new StringBuilder();
while ((tmp = bufferedReader.readLine()) != null) {
builder.append(tmp);
}
return builder.toString();
} catch (IOException e) {
...
} finally {
...
}
}
...
What I have to do, is to PowerMock both FileReader creation and BufferedReader creation.
ATest.java
#RunWith(PowerMockRunner.class)
#PrepareForTest(A.class)
public class ATest {
#Mock
private FileReader fileReader;
#Mock
private BufferedReader bufferedReader;
...
#Test
public void test() throws Exception {
PowerMockito.whenNew(FileReader.class).withArguments(FILE_NAME).thenReturn(fileReader);
PowerMockito.whenNew(BufferedReader.class).withAnyArguments().thenReturn(bufferedReader);
PowerMockito.doAnswer(new Answer() {
public Object answer(InvocationOnMock invocation) throws Throwable {
return "test";
}
}).when(bufferedReader).readLine();
assertArrayEquals(reader.read(FILE_NAME), new String[]{"test"});
}
}
But then the test never terminates. I can't even debug it.
As soon as PowerMockito.doAnswer() is removed the code is executed (and is available for debugging). I've also tried to use Mockito.mock() instead of PowerMockito.doAnswer(), it doesn't help.
What may cause interminate execution of the test?
Just a different perspective: one could say that your real problem in your code are those two calls to new() for FileReader / BufferedReader.
What if you passed a Reader to this method; instead of a String denoting a file name?
What if you passed a "ReaderFactory" to the underlying class that contains this method read(String)? (where you would be using dependency injection to get that factory into your class)
Then: you would be looking at an improved design - and you would not need to use PowerMock. You could step back and go with Mockito or EasyMock; as there would be no more need to mock calls to new.
So, my answer is: you created hard-to-test code. Now you try to fix a design problem using the big (ugly) PowerMock hammer. Yes, that will work. But it is just the second best alternative.
The more reasonable option is to learn how to write testable code (start here for example); and well, write testable code. And stop using PowerMock ( I have done that many months back; after a lot of PowerMock-induced pain; and I have never ever regretted this decision ).
The problem was, that I also had to mock value after first bufferedReader.readLine(), because otherwise it would always return the mocked value, thus not terminating.
Mockito.when(bufferedReader.readLine()).thenReturn("first line").thenReturn(null);
NOTE
Though this is the actual answer to the question, but you should strongly consider choosing the design GhostCat has suggested in another answer (which I eventually did).

Constructor handling exception and using this keyword Java

I have two constructors for my class, one that takes File object and the other takes a String object, and I want to use the this keyword. The function with the implementation is the one with File as parameter, and the one with String will call this. Now I want to check for exception in the constructor that takes String but I get error, that this should be the first line. How can I check for errors then call this.
Here is my code:
public Test (String filename) {
if (filename == null)
throw new NullPointerException("The String you entered is null.");
if (filename.isEmpty())
throw new IllegalArgumentException("The String you entered is empty.");
this(new File(filename)); // error
}
public Test (File f) {
/* implementation here */
}
This is the exact error: Constructor call must be the first statement in a constructor
Unfortunately, this is impossible in Java thanks to their arbitrary restrictions. You have two main possibilities.
The more idiomatic Java technique is to wrap everything in a factory function so you can catch the exception. Factory functions are also useful because they let you create objects polymorphically, and help hide the details of what object is actually created.
public static Test create(String filename){
if (filename == null)
throw new NullPointerException("The String you entered is null.");
if (filename.isEmpty())
throw new IllegalArgumentException("The String you entered is empty.");
return new Test(filename);
}
private Test (String filename) {
this(new File(filename));
}
public Test (File f) {
/* implementation here */
}
The other option is to write the constructor in bytecode, where there are no such restrictions present. Unfortunately, bytecode is less readable and maintainable, so you'll probably want to minimize the amount of bytecode in a primarily Java app. You might also be able do this in a non Java language like AspectJ.
Edit: If you're not actually trying to catch the exceptions, then there's a third possibility. You can insert arbitrary code before the super constructor call by creating a separate function which performs the checks and then passing it as a dummy argument to the super constructor call. Since arguments are evaluated first, your code will run first, but this is a bit of a hack.
public Test (String filename) {
this(doChecks(filename), new File(filename));
}
private static Void doChecks(String filename){
if (filename == null)
throw new NullPointerException("The String you entered is null.");
if (filename.isEmpty())
throw new IllegalArgumentException("The String you entered is empty.");
return null;
}
public Test (Void dummy, File f) {
this(f);
}
public Test (File f) {
/* implementation here */
}
In case we use this or super in constructor, either this or super should be the first statement in the constructor. It is better, if you throw exception from a particular constructor.
public Test (String filename) {
this(new File(filename));
}
Let the second constructor handle any exception, caused by passing null.
public Test (File file) {
// exception handling code
// or new instance creation
}
No, you cannot check for errors before call this. It's forbidden by the specification. In fact, you didn't need it. Let new File(filename) to throw exceptions.
edit: I saw aizen92's comment: Actually that is what my constructor with the implementation has, it catches the exception may be thrown by file, so I just add the null exception and use this directly in my second constructor?
public Test (String filename) {
this((filename == null || filename.isEmpty()) ? null : new File(filename));
}

Categories

Resources