4

Suppose I have some code like this:

Vehicle vehicle = vehicleRepostory.findByIdInitialized(vehicleId);

If the Vehicle cannot be found this method will return null. The specification says in this case I must throw a MyObjectNotFoundException so the code becomes something like this:

Vehicle vehicle = vehicleRepostory.findByIdInitialized(vehicleId);
MyObjectNotFoundException.throwIfNull(vehicle, Vehicle.class, vehicleId);

What can I do if I want to get rid of calls to throwIfNull. It is not really DRY and a poor design choice anyway. There must be some design pattern unbeknownst to me. I searched on the web but it did not turn up anything really usable.

A straightforward solution might be putting the code into my Repository but I use SpringData for this so it is just an interface:

public interface VehicleRepository extends Repository<Vehicle, Long>

// ...

@Query("select v from Vehicle v LEFT JOIN FETCH v.technicalData td LEFT JOIN FETCH v.registrationData rd"
    + " where v.vehicleId = ?")
Vehicle findByIdInitialized(Long vehicleId);
Adam Arold
  • 29,285
  • 22
  • 112
  • 207

7 Answers7

3

It sounds like basically you want your repository to support this:

Vehicle vehicle = vehicleRepository.loadExisting(vehicleId);

where the difference between loadExisting and findByIdInitialized would be that the former expects the entity to be present and will throw an a exception if it's not.

That way all repository clients can make a decision as to whether when they perform a lookup, they want the lack of an entity to result in an exception or not. You may even find that all lookups by ID should throw an exception - in which case you can go back to having a single method.

EDIT: If the repository is autogenerated, I'd take one of three approaches:

  • Wrap it
  • Extend it
  • Modify the generator

Which of these choices would be most appropriate would depend on the exact details.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • I edited my question. I forgot to point out that the Repository is generated so I don't have a concrete class to modify. – Adam Arold Feb 22 '13 at 10:04
  • @AdamArold: What's it generated by, and can't you change that generation process or wrap it? – Jon Skeet Feb 22 '13 at 10:07
  • I'm using SpringData for this. I just have to extend Repository and Spring takes care of the rest. Maybe I'm able to modify the factory bean stated in the Spring config: ` ` – Adam Arold Feb 22 '13 at 10:17
  • Ok this will get me going. And by the way this is a red letter day since **you** answered my question. :) – Adam Arold Feb 22 '13 at 10:35
0

You could look into @NotNull annotations in Java. There are several flavours of it, some of them which do their validation compile-time and some of them at runtime. Some editors (like IntelliJ IDEA) can warn you when you're doing an operation which could result in an NPE.

Which @NotNull Java annotation should I use? Avoiding != null statements http://docs.oracle.com/javaee/6/api/javax/validation/constraints/NotNull.html

Community
  • 1
  • 1
Rein
  • 478
  • 3
  • 3
0

It would of course be best if you could redesign the repository itself to throw the exception you need. Without that, you need workarounds that patch the behavior.

One approach would be reflection: wrap calls to repository in a method that receives findByIdInitialized as a string and calls it reflectively. The method can then throw the appropriate exception.

Another way could be to involve some AOP to do the same thing, but perhaps with more type safety.

Marko Topolnik
  • 195,646
  • 29
  • 319
  • 436
0

I suggest that you add a nullable parameter to findByIdInitialized, and it will be like:

Vehicle findByIdInitialized(int vehicleId, boolean throwException) {
   // implementation behavior...

   if (throwException) {
       MyObjectNotFoundException.throwIfNull(vehicle, Vehicle.class, vehicleId);
   }
}
a.karkar
  • 141
  • 1
  • 7
0

Use this:

import static java.util.Objects.requireNonNull;

.
.
.

Object o = requireNonNull(obj);
Mordechai
  • 15,437
  • 2
  • 41
  • 82
0

Sounds like you wanna "after method returning" AOP advice, that intercepts nulls and throws exception.

mishadoff
  • 10,719
  • 2
  • 33
  • 55
-2

You can use NullObject dessign pattern, but thwroing an exception IMHO is the best choice.

To keep in DRY, you should put that throw in findbyIdInitialized.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • No, absolutely not - that would be a way of *avoiding* throwing an exception if the entity isn't found. – Jon Skeet Feb 22 '13 at 09:43
  • @JonSkeet, Yes but he asked about possibilities and he got one. With a opinion and advise. For some reason that pattern exist. In some cases could be expected to use it. This might not be such case but it is only the possibility. – Damian Leszczyński - Vash Feb 22 '13 at 09:49
  • My understanding of the question is that the OP has committed to throwing an exception - but wants to change *how* he goes about doing so. With the edit of the second paragraph, your answer makes more sense - but the first part isn't useful to this question IMO. – Jon Skeet Feb 22 '13 at 09:57
  • I said that the specification explicitly stated that i **have to** throw an exception. – Adam Arold Feb 22 '13 at 10:08
  • @JonSkeet, Your understanding was correct. And your comment probably refer to first version of my answer. NVM thank for commney. Good day. – Damian Leszczyński - Vash Feb 22 '13 at 12:57