How to find different entities in the same collection with Morphia - java

I have an abstract POJO class which is named Person and two entities which are named Developer and Manager. These entities inherits Person abstract class. There is no problem to save them to the same collection but when I try to find, for instance, only developers in the collection, Morphia's find method gets me all records in the collection and I get java.lang.ClassCastException.
Morphia morphia = new Morphia();
Datastore ds = morphia.createDatastore("test");
for (Developer savedDeveloper : ds.find(Developer.class).asList()) {
System.out.println(savedDeveloper.getFoo());
}
Exception
Sep 27, 2013 11:56:18 AM com.google.code.morphia.logging.MorphiaLoggerFactory chooseLoggerFactory
INFO: LoggerImplFactory set to com.google.code.morphia.logging.jdk.JDKLoggerFactory
Developer1
Developer2
Exception in thread "main" java.lang.ClassCastException: test.model.Manager cannot be cast to test.model.Developer
at test.Test.main(Test.java:39)
Java Result: 1
So my questions is that how can I get only one specific entity list in a collection which has more than one entities?
My POJOs
Person.java
public abstract class Person {
#Id
private ObjectId objectid;
private String username;
public Person() {
}
/* ......Getters and Setters*/ }
People.java
#Entity("people")
public class Developer extends Person {
private String foo;
public Developer() {
}
public String getFoo() {
return foo;
}
public void setFoo(String foo) {
this.foo = foo;
}
}
Manager.java
#Entity("people")
public class Manager extends Person {
private String bar;
public Developer() {
}
public String getBar() {
return bar;
}
public void setBar(String bar) {
this.bar = bar;
}
}

There's actually an open issue on this: https://github.com/mongodb/morphia/issues/22
Polymorphic queries can actually get quite complicated to do correctly generically. They make me a bit nervous to contemplate, actually. That said, I was talking to the C# team and they have an approach that seems to work for them without too much heartburn so there's likely some inspiration there to borrow. For now, though, you'll have to manually include the className field as suggested above.

I resolved this problem with Morphia's BasicDAO. I created a DeveloperDAO class that inherits Morphia's BasicDAO class then I used DAO methods in order to make queries and it works.
public class DeveloperDAO extends BasicDAO<Developer, String> {
public DeveloperDAO(String dbName) throws UnknownHostException {
super(MongoSingleton.getInstance(), MorphiaSingleton.getInstance(), dbName);
} }
Test
public class Test {
public static void main(String[] args) throws UnknownHostException {
DeveloperDAO developerDAO = new DeveloperDAO("test");
for(Developer developer : developerDAO.find().asList())
System.out.println(developer.getFoo());
}}

Related

Best way in Java to hide public setters from client applications

I have a Spring Application which is built on top of DynamoDB. I am trying to write a saveFoo() Repository method that will save an object of type Foo to the database. This method will be called from the application layer.
What I'm struggling with is that the Foo class has fields within it that are Dynamo specific. I don't want clients of the saveFoo() class to think they need to create an object of type Foo with these fields. Nor do I want them to attempt to ever set these values themselves.
These database-specific fields need public getters and setters in order to work with the DynamoDB SDK.
The database model class looks like the following:
#DynamoDBTable(tableName = "foo")
public class Foo {
// Fields the client should be setting
private String bar;
private String baz;
// Fields the client should not access and should not care about. They are internal fields used for DynamoDB purposes.
private Long version;
private String gsiIndexKey;
// Empty constructor needed for deserialization of data from dynamodb
public Foo() {
}
// Getters and setters for all of the above fields.
}
And the repository method to save the object to the DB:
public class FooRepositoryImpl {
public Foo saveFoo(WhatClassShouldThisBe foo) {
// Code that saves a new Foo item to the database and returns it.
}
}
My current idea is to create a FooWrapper interface that the saveFoo() method can take as a parameter. The wrapper will allow the client to set the fields that they should have control over, but does not expose fields related to the database internals. Something like the below:
/**
* Allows us restrict visibility of the Foo fields to the Application by hiding database internal fields.
**/
public interface FooWrapper {
Foo getFoo()
}
public class FooWrapperImpl implements FooWrapper {
private final Foo foo;
public FooWrapperImpl(String bar, String baz) {
foo = new Foo();
foo.setBar(bar);
foo.setBaz(baz);
}
#Override
public Foo getFoo() {
return foo;
}
}
public class FooRepositoryImpl {
public Foo saveFoo(FooWrapper fooWrapper) {
Foo foo = fooWrapper.getFoo(); // Save this item to db
// Code that saves a new Foo item to the database and returns it.
}
}
What are your thoughts on this approach? Does anyone know of some better techniques I could try? I can't help but feel that I am over-engineering things here.
Expose only an interface to clients that has the methods you want. Internally you can call the other public methods of the implementation, but the client code won't know them.
If you are using modern Java, don't export your implementation classes outside of your module. Only export the public interface.
You could also keep an interface for internal use that has more methods than the public API.
public interface Foo {
public void setBar(String bar);
public void setBaz(String baz);
}
#DynamoDBTable(tableName = "foo")
public class FooImpl implements Foo {
// Fields the client should be setting
private String bar;
private String baz;
// Fields the client should not access and should not care about. They are internal fields used for DynamoDB purposes.
private Long version;
private String gsiIndexKey;
// Empty constructor needed for deserialization of data from dynamodb
public FooImpl() {
}
// Getters and setters for all of the above fields.
#Override
public void setBar(String bar) {
this.bar = bar;
}
#Override
public void setBaz(String baz) {
this.baz = bar;
}
// Not part of the Foo interface
public void setVersion(Long version) {
this.version = version;
}
public void setGsiIndexKey(String indexKey) {
this.gsiIndexKey = indexKey;
}
}

Java - Use of Type-specifc Interfaces

Consider the following: say we have an IRestaurant and an IBooking interface.
We then have the following interface function:
interface IBooking {
void reserve(IRestaurant restaurant);
}
However, business requirements dictate a booking service in a country could make reservations to only restaurants in the same country. Then say we have in USA:
class USABooking implements IBooking { ... }
class USARestaurant implements IRestaurant { ... }
In this case, since reserve() in IBooking takes in any instance of IRestaurant, the USABooking implementation would be required to check the instance of the IRestaurant to see if it is an instance of a USARestaurant and then downcast. However, we could also do this as an alternative:
interface IBooking<R extends IRestaurant> {
void reserve(R restaurant);
}
class USABooking implements IBooking<USARestaurant> {
void reserve(USARestaurant restaurant) { ... }
}
Is this a recommended way to go about enforcing the type limitation? In other words, is this better than performing runtime checks on the restaurant instance types? The typing approach sounds good to me, but I just want to make sure it won't "blow up" the architecture and turn out to be a misuse or abuse, since there are other interfaces that also would require such limitations (e.g. ICuisine).
Here's another alternative since I don't understand why there are USABooking and USARestaurant classes:
Consider just having a Booking and Restaurant class, where Restaurant provides a getCountry() method. Separately, to avoid a proliferation of classes, a Booking instance might have something like a List<RestaurantBookingRule> - in this case there would be a single rule that checks the country of the Restaurant. For example:
public class Restaurant {
private final String country; // constructor omitted
public String getCountry() { return country; }
}
public interface RestaurantBookingRule {
public void validateRequest(Restaurant r); // throws exception if the rule is broken
}
public class RequiredCountry implements BookingRule {
private final String country; // constructor omitted
public void validateRequest(Restaurant r) {
if (!r.getCountry().equals(country))
throw ...
}
}
public class Booking {
private final List<RestaurantBookingRule> rules; // constructor omitted
public void reserve(Restaurant r) {
rules.forEach(r -> r.validateRequest(r));
...
}
}
then:
Restaurant r1 = new Restaurant("USA");
Restaurant r2 = new Restaurant("CAN");
Booking usaBooking = new Booking(List.of(new RequriedCountry("USA"));
usaBooking.reserve(r1); // ok
usaBooking.reserve(r2); // throws exception

Schema Generator for ApacheCayenne classes

I'm trying to use SPQR to generate GraphQL schema from a Cayenne generated class.
Cayenne class looks like this
public class MyCayenneClass {
public static final Property<Integer> A_PROPERTY = Property.create("aProperty", Integer.class);
public static final Property<Integer> ANOTHER_PROPERTY = Property.create("anotherProperty", String.class);
public void setAProperty(Integer aProperty) {
writeProperty("aProperty", aProperty);
}
public Integer getAProperty() {
return (Integer)readProperty("aProperty");
}
public void setAnotherProperty(String anotherProperty) {
writeProperty("anotherProperty", anotherProperty);
}
public String getAnotherProperty() {
return (String)readProperty("anotherProperty");
}
}
As the class isn't a simple POJO, SPQR throws an exception and the schema isn't generated.
Error: QUERY_ROOT fields must be an object with field names as keys or a function which returns such an object.
What's the best approach here (without modifying the cayenne class (i.e. annotating a method)?
GraphQLEndPoing.java
#WebServlet(urlPatterns = "/graphql")
public class GraphQLEndpoint extends SimpleGraphQLServlet {
public GraphQLEndpoint() {
super(buildSchema());
}
//This method used SPQR
private static GraphQLSchema buildSchema() {
GraphQLSchema schemaGenerator = new GraphQLSchemaGenerator()
.withOperationsFromSingletons(myRepository) //register the beans
.generate();
return schemaGenerator;
}
private static final MyRepository myRepository;
static {
myRepository= new MyRepository ();
}
}
MyRepository.java
public class MyRepository{
private MyLibService libService;
#GraphQLQuery
public MyCayenneClass find(Integer id) {
List<MyCayenneClass> myList= libService.fetchById(new Integer[] {id});
return myList.get(0);
}
}
*FYI. If I declare the schema. Code will work just fine
schema {
query: Query
}
type Query {
find(id: Int): MyCayenneClass
}
type ConcContract {
id: ID
aProperty: Int
anotherProperty: String
}
From SPQR's perspective, this isn't really different from a POJO, as SPQR cares only about the types.
By default, for all nested classes (MyCayenneClass in your case), everything that looks like a getter will be exposed. For top-level classes (MyRepository in your case), only annotated methods are exposed by default. And at least one top-level method must be exposed, otherwise you have an invalid schema.
The error, as it stands, just means not a single top-level query was discovered. I see the #GraphQLQuery annotation is commented out. Is that intentional? With the default config, this would not expose any query.
You can register a different ResolverBuilder, e.g. PublicResolverBuilder (or your own implementation/extension) if you want to expose un-annotated methods.
E.g.
generator.withOperationsFromSingleton(new MyRepository(), new PublicResolverBuilder())
This would expose all public methods from that class.
Here's a slightly simplified example I tried with v0.9.6 and seems to work as expected (I know you're using a rather old version from the error text).
public class MyRepository {
#GraphQLQuery //not commented out
public MyCayenneClass find(Integer in) {
return new MyCayenneClass();
}
}
// extends CayenneDataObject because I don't know where to get the
// writeProperty and readProperty from
// but shouldn't change anything from SPQR's perspective
public class MyCayenneClass extends CayenneDataObject {
public static final Property<Integer> A_PROPERTY = Property.create("aProperty", Integer.class);
public static final Property<String> ANOTHER_PROPERTY = Property.create("anotherProperty", String.class);
public void setAProperty(Integer aProperty) {
writeProperty("aProperty", aProperty);
}
public Integer getAProperty() {
return (Integer)readProperty("aProperty");
}
public void setAnotherProperty(String anotherProperty) {
writeProperty("anotherProperty", anotherProperty);
}
public String getAnotherProperty() {
return (String)readProperty("anotherProperty");
}
}
There's many more customizations you can apply, depending on what you end up needing, but from the question as it stands, it doesn't seem you need anything extra...
To override the ResolverBuilder used for nested classes, you have 2 options.
1) Register it globally, so all nested types use it:
generator.withNestedResolverBuilders(customBuilder)
2) Or per type:
.withNestedResolverBuildersForType(MyCayenneClass.class, new BeanResolverBuilder())
But this is very rarely needed...

Can I have a single instance of Interface

In my Android application I have a class which gives me static string values; something like this:
public class VehicleInfo {
public static String getVehicleEnginePower(boolean isNew) {
return isNew ? "1800CC" : "1600CC";
}
}
Now I have another category, so I will have to pass another Boolean, and I will get the value I need. However, these categories will keep on increasing. So I looked into the Open/Closed principle which looks promising for quick enhancement. To ensure this I will make the VehicleInfo class as an Interface and then I will have other classes implement VehicleInfo.
public interface VehicleInfo {
String getVehicleEnginePower();
}
public class NewVehicle implements VehicleInfo {
#Override
public String getVehicleEnginePower() {
return "1800CC";
}
}
and the other category classes will also be something like this. In this way I will have to add another class for all the new categories.
The question I wanted to ask is: is there a way that I can have single instance of this interface? Because in the whole application flow, a user will only be able to see one category until he switches to another category.
I don't want to instantiate these classes at multiple points. To clarify my question, I want to do something like this at the start of my application:
if (isNew) {
VehicleInfo vehicleInfor = new NewVehicle();
}
And in the whole application, whenever I call VehicleInfo.getVehicleEnginePower, it should always return engine power from the NewVehicle class.
Is something like this possible? Or am I just being silly and I will have to instantiate this interface on multiple points?
Maybe you need a singleton here
public class VehicleInfoManager {
private static VehicleInfoManager INSTANCE = new VehicleInfoManager();
private VehicleInfo currentVehicleInfo;
public static VehicleInfoManager getInstance() {
return INSTANCE;
}
public void setCurrentVehicleInfo(VehicleInfo info) {
this.currentVehicleInfo = info;
}
public String getVehicleEnginePower() {
return this.currentVehicleInfo.getVehicleEnginePower();
}
private VehicleInfoManager() {
// Constructor private by default
}
}
Then you can call it from everywhere like this
VehicleInfoManager.getInstance().getVehicleEnginePower()
//Or set current info like this
VehicleInfoManager.getInstance().setCurrentVehicleInfo(new NewVehicle())
Just be careful as currentVehicleInfo is null by default so you need to handle null pointer cases.
If I understand your question correctly.
My solution to this would be Enum
public enum VehicleEnginePower {
NEW ("1800CC"),
OLD ("1600CC"),
private final String name;
private Modes(String s) {
name = s;
}
public String toString() {
return this.name;
}
}
Then you can do
if (isNew) {
String powerOfEngine = VehicleEnginePower.NEW.toString();
}

How can I avoid this if statement

I have an enum
public enum Vehicle {
CAR("CAR", "Car"), PUSHBIKE("PUSHBIKE", "PuschBike");
public boolean isCar()
{
...
}
public boolean isPushBike()
{
....
}
}
I have a 2 DAO CarDAO and PushBikeDAO which is are implementing a BaseDao
I have a JSF managed bean somthing like this
public class JsfManagedBean {
private Vehicle vehicle;
private BaseDAO baseDao;
public void Search()
{
//I need to get rid of this if statement
if (vehicle.isCar())
{
baseDao = new CarDao;
baseDao.search();
}
else if(vehicle.isPushBike())
{
baseDao = new PushBike;
baseDao.search();
}
//Please Note each type of search is very different call to an other party's Jar
}
}
I am trying to get rid of this if statement possibly by using generics or any proper OO technique
may be something like
baseDao = new baseDaoImpl<getClass(vehicle.getcode())>
where if vehicle.getcode() returns String value Car I do have a model class Car.
Just loud thinking (clinching the straws really :)).
This is an offshot of this question of mine
Add a method to the enum that calls new and returns the right dao.
Let each of the enum constants define their respective DAO classes:
public enum Vehicle {
CAR("CAR", "Car"){
public BaseDAO getNewDAO(){
return new CarDAO();
}
},
PUSHBIKE("PUSHBIKE", "PuschBike"){
public BaseDAO getNewDAO() {
return new PushBikeDAO();
}
};
Vehicle(String a, String b){/* ... */}
//this forces every enum constant to implement a getNewDAO() method:
abstract BaseDAO getNewDAO();
}
This way, you can use:
public void Search() {
baseDao = vehicle.getNewDAO();
baseDao.search();
}
Take a look at the Factory method pattern and the Strategy pattern if you'd like to know more. Enums are my preferred way to use the latter.
I would use a factory method, like so:
public class JsfManagedBean {
private static final Map<Vehicle,BaseDAO> daos;
static {
Map<Vehicle,BaseDAO> tmp = new HashMap<Vehicle,BaseDAO>();
tmp.put(Vehicle.CAR,new CarDAO());
tmp.put(Vehicle.BIKE,new BikeDAO());
daos = Collections.unmodifiableMap(tmp);
}
public static getDao(Vehicle v) {
return daos.get(v);
}
private Vehicle vehicle;
private BaseDAO baseDao;
public void Search()
{
baseDao = getDao(vehicle);
baseDao.search();
}
}
Unless you have more uses for DAO objects, you could make this code shorter:
if (vehicle.isCar()) new CarDao().search();
else if(vehicle.isPushBike()) new PushbikeDao().search();
With two alternatives, I'd stay with the if statement. If you had really many variants of vehicles, you could use a hash table keyed by the enum values and storing the DAO classes:
Map<Vehicle, Class> DAOClass = new HashMap<...>();
...
DAOClass.get(vehicle).getConstructor().newInstance().search();
Reflection is not that slow not to use here.

Categories

Resources