Gili
Sam
Hi James,
I ran this question by the author of Jersey and he said that doing so
would violate the JAX-RS specification:
http://n2.nabble.com/com.sun.jersey.impl.uri.UriBuilderImpl.path()-throws-an-unexpected-exception-td1373393.html#a1381422
I need to somehow tell Guice to not use CGLIB or to annotate the
subclass with the same annotations as the superclass.
Gili
On Oct 24, 8:36 pm, "James Carman" <jwcar...@gmail.com> wrote:
> Can Jersey search the class hierarchy for the @Path annotation?
>
> On Fri, Oct 24, 2008 at 7:45 PM, je...@swank.ca <limpbiz...@gmail.com> wrote:
>
> > On Oct 24, 2:42 pm, Gili <gili.tzab...@gmail.com> wrote:
> >> Is it possible to tell Guice to avoid the use of CGLIB unless it's
> >> absolutely necessary? I know Guice uses it to solve circular
> >> dependencies but I use the Provider<Foo> approach instead. CGLIB
> >> proxies sometimes break compatibility. For example, today I ran into
>
> > Are you using method interceptors? We can't do them without CGLIB.
On the one hand I agree JAX-RS should probably check out the
superclass annotations. On the other hand, a proxy that doesn't mimic
the underlying class is a poor proxy ;) JAX-RS just went 1.0 so I don't
foresee them checking the superclass annotations anytime soon. It could
be easier to just fix this in Guice (if possible).
Gili
Stuart McCulloch wrote:
> 2008/10/27 Gili <gili.t...@gmail.com <mailto:gili.t...@gmail.com>>
>
>
> Hi James,
>
> I ran this question by the author of Jersey and he said that doing so
> would violate the JAX-RS specification:
> http://n2.nabble.com/com.sun.jersey.impl.uri.UriBuilderImpl.path()-throws-an-unexpected-exception-td1373393.html#a1381422
>
> I need to somehow tell Guice to not use CGLIB or to annotate the
> subclass with the same annotations as the superclass.
>
>
> looking at the codebase it appears Guice uses CGLIB's FastClass
> to create instances of public types when doing constructor injection,
> even if there's no circular dependency or interception going on, see:
>
> src/com/google/inject/DefaultConstructionProxyFactory.java
>
> afaik using FastClass here is just for performance, so it's technically
> possible to add some sort of switch to turn this off - but I'll leave
> it to
> the Google devs to decide if this is worthwhile or not...
>
> Gili
>
> On Oct 24, 8:36 pm, "James Carman" <jwcar...@gmail.com
> <mailto:jwcar...@gmail.com>> wrote:
> > Can Jersey search the class hierarchy for the @Path annotation?
> >
> > On Fri, Oct 24, 2008 at 7:45 PM, je...@swank.ca
> <mailto:je...@swank.ca> <limpbiz...@gmail.com
> <mailto:limpbiz...@gmail.com>> wrote:
> >
> > > On Oct 24, 2:42 pm, Gili <gili.tzab...@gmail.com
Funny you mention this, I just wrote a bunch of stuff to search the
class hierarchy for method annotations -- luckily it only needs to be
done once per method, but it is less than pleasant.
I would consider it to be correct for Guice to add the annotations to
its generated proxies, but IIRC cglib doesn't generate things beyond
1.4 -- unless guice is using a super-secret version Chris hasn't told
us about yet!
-Brian
Gili
What about the option of having CGLIB totally disabled? Is this
targeted for 2.0 or was it later?
I've seen this a few times and wondered what people are injecting into
domains? Are you using a non-anemic domain and injecting other
domains or services into?
-bp
return objects.toString(this);
This walks all non-static fields using reflection and prints it out.
That's just one example (using helper functions).
Gili
Anyone else doing something more transactional? Just wondering what
the cases are.
-bp
P.S. I'm a service-based guy, so I tend to favor anemic domains.
This article seems somewhat biased ;) He's making a lot of big
assumptions about SOA that aren't necessarily correct. This is
especially true with large distributed systems.
> "'Anemic Domain Model' where facade classes (usually Stateless Session
> Beans) start accumulating more and more business logic and domain
> objects become mere data carriers with getters and setters."
This is correct. Anemic means no logic with data.
> Hm, With anemic model you dont need injeting into model because it is
> only data holder.
Yeah.
> In non-anemic model there is model, services (ejb3) and many helpers
> with support core model and have to be close it.
Not necessarily. In a non-anemic pattern the domain model _is_ the
service. If you invoke a method on it the logic to fulfill that method
is part of the domain class. You can abstract the logic out into an
EJB (eeck - yes even with EJB3), but that's just an anemic proxy. The
domain object is doing little more than encapsulating a client call:
// Anemic
CatService cs = ...;
Cat cat = ...;
cat = cs.fix(cat);
// DDD
Cat cat = ...;
cat.fix();
public class Cat {
private final CatService cs;
private boolean isFixed = false;
@Inject public Cat(CatService cs) {
this.cs = cs;
}
public void fix() {
isFixed = cs.fix(this);
}
}
These are essentially the same in my book. I think what a lot of true
DDD and non-anemic folks are looking for is this:
// DDD
Cat cat = ...;
cat.fix();
public class Cat {
private final EntityManager em;
private boolean isFixed = false;
@Inject public Cat(EntityManager em) {
this.em = em;
}
public void fix() {
isFixed = true;
em.persist(this);
}
}
The code to change the state and save it to the database (or whatever
else is required) is part of the domain object itself.
Both of these DDD approaches encapsulates the state transition within
the cat, but state can be really nasty sometimes and you have also
lost the state of the cat prior to it being fixed unless you clone it
in the client code. Anemic model can fix this situation easily. Plus,
in a distributed system, if I'm passing around a non-anemic Cat, the
fix method might not be guaranteed to work if the remote CatService
isn't reachable or the EntityManager can't connect to the database
from that server. Therefore, the contract is broken. This means you
need an on-the-wire representation of the Cat (SDO, XML, value-object,
transfer-object) and a DDD representation inside the tiers of the
system. This requires some data translation between the transfer-
object and the DDD once the remote server receives the message.
I generally like to think that data and logic should be put as far
away from each other as possible. It doesn't necessarily bloat the
services code anymore than the domain would be bloated. Additionally,
I can have multiple ways to "fix my cat" without writing multiple
domains and they all work on the same data object. That's pretty nice.
This means you can go discover services for "fixing" cats based on the
types and you get a lot of other benefits.
>
> So when you create model and on next time client require you to invoke
> service (without injecting you cant invoke service from model, unless
> as parameter for method model) and you will have to move implemented
> funtionality from Model/Helpers to Services which ends Anemic model
> (all logic are in services).
There are a number of DDD frameworks that will fix this for you using
constructor AOP and other concepts. But in vanilla Java, yes, this is
an issue unless the DI container always creates instances of your
domain.
> In bussiness system there is many abstraction in core system:
> connection to ldap, db, xml, many factories, authorization,
> optymalization like caches, views, builders, kontrolers, managers
> sessions and many other. I think support for this abstraction like IoC
> close to core system it will be added value to system. Guice configure
> system with defaults and in tests or during intergration with other
> system you can ovverride some system policy (example for ldap).
Not sure I follow this bit.
-bp
I don't understand this part of your reply. What do you mean?
> Anemic model can fix this situation easily. Plus,
> in a distributed system, if I'm passing around a non-anemic Cat, the
> fix method might not be guaranteed to work if the remote CatService
> isn't reachable or the EntityManager can't connect to the database
> from that server. Therefore, the contract is broken.
I don't agree with this statement. This is no different from you trying
to reach the database on the server end and it not being reachable for a
different reason (i.e. you've surpassed the maximum number of
connections or the database went down). In both cases your contract
needs to allow for failure when interacting with the database.
> This means you
> need an on-the-wire representation of the Cat (SDO, XML, value-object,
> transfer-object) and a DDD representation inside the tiers of the
> system. This requires some data translation between the transfer-
> object and the DDD once the remote server receives the message.
I don't agree that Rich Domain Models (non-amnemic in your terminology)
require you to pass rich models to the client. For example, you can use
ROA/REST for client-server communication and in that paradigm you only
pass the state back and forth. While it is true that ROA separates state
from behavior it is worth noting it eliminates the service layer
altogether (you're forced to use the same methods across all resources).
Gili
Brian Pontarelli wrote:and you have alsolost the state of the cat prior to it being fixed unless you clone itin the client code.
I don't understand this part of your reply. What do you mean?
Anemic model can fix this situation easily. Plus,in a distributed system, if I'm passing around a non-anemic Cat, thefix method might not be guaranteed to work if the remote CatServiceisn't reachable or the EntityManager can't connect to the databasefrom that server. Therefore, the contract is broken.
I don't agree with this statement. This is no different from you trying
to reach the database on the server end and it not being reachable for a
different reason (i.e. you've surpassed the maximum number of
connections or the database went down). In both cases your contract
needs to allow for failure when interacting with the database.
This means youneed an on-the-wire representation of the Cat (SDO, XML, value-object,transfer-object) and a DDD representation inside the tiers of thesystem. This requires some data translation between the transfer-object and the DDD once the remote server receives the message.
I don't agree that Rich Domain Models (non-amnemic in your terminology)
require you to pass rich models to the client. For example, you can use
ROA/REST for client-server communication and in that paradigm you only
pass the state back and forth. While it is true that ROA separates state
from behavior it is worth noting it eliminates the service layer
altogether (you're forced to use the same methods across all resources).
Are you talking about wanting to be able to represent a Cat with fix()
on the server and without fix() on the client because of business-logic?
Or are you saying that technical limitations might cause fix() to fail
on the client? If it's the latter I argue that it's no different from
the server because even there the DB might become unreachable. If you're
arguing the former, then I argue you need different client-side and
server-side Cat interfaces because they are not really the same.
> It doesn't require you to pass rich models across the wire and in fact
> you really shouldn't do this. In general Rich Domain doesn't separate
> state from behavior, so you need to do that by hand when you pass the
> state across the wire.
I guess I am saying that you shouldn't be passing Rich Domain Objects
over the wire because (from practical experience) the server-side and
client-side interfaces are almost always "different enough" that you
can't share the interfaces. Clients usually contain a subset of the
server methods and might contain some client-only methods. I believe
Rich Domain Objects still hold a lot of value on the server-end, even if
you can't pass them to clients. Clients and servers can both run their
own show (with RDO) and communicate over the wire by passing a subset of
the state (DTO, REST, whatever you want to call it).
I argue you always need to define the client-server interface by hand.
Serializing your state-only Object to the client is very poor practice.
One reason is that you're essentially exposing an interface to the
client and this needs to be designed and exposed very carefully. The
other reason is that you can't rely on having Java on both ends of the wire.
Gili
What I'm saying is that the fix method must be different on the client
and server. This generally means a different class for the client and
server. If it was the same class on the client and server, all the
logic would need to be pull out into a well known interface and that
interface would need to be different implementations on the client and
server, making the domain just a proxy and not very rich.
>
> I guess I am saying that you shouldn't be passing Rich Domain Objects
> over the wire because (from practical experience) the server-side and
> client-side interfaces are almost always "different enough" that you
> can't share the interfaces. Clients usually contain a subset of the
> server methods and might contain some client-only methods. I believe
> Rich Domain Objects still hold a lot of value on the server-end,
> even if
> you can't pass them to clients. Clients and servers can both run their
> own show (with RDO) and communicate over the wire by passing a
> subset of
> the state (DTO, REST, whatever you want to call it).
Yeah, we agree on this. You shouldn't be passing around rich domain
objects because they don't work that way. This incurs a lot of code
overhead though.
>
> I argue you always need to define the client-server interface by
> hand.
> Serializing your state-only Object to the client is very poor
> practice.
> One reason is that you're essentially exposing an interface to the
> client and this needs to be designed and exposed very carefully. The
> other reason is that you can't rely on having Java on both ends of
> the wire.
Not sure what you mean by this. You definitely have to define how your
client talks to the server and what your server responds with, since
that is the standard remoting paradigm. In terms of serializing a
state only object as poor practice, I think you might be confused,
because that's what you said you should do above with the DTO/REST/
whatever. DTOs are state objects.
Again, here's a concrete example so we are on the same page:
RDO
-------
public class ClientCat {
@Inject RemoteCatService cs;
boolean fixed;
public void fix() {
CatDTO dto = new CatDTO();
dto.fixed = this.fixed;
this.fixed = cs.fixTheCat(dto);
}
}
public class ServerCat {
@Inject EntityManager em;
boolean fixed;
public void fix() {
this.fixed = true;
em.persist(this);
}
}
public class CatDTO {
boolean fixed;
}
public class Client {
public void fixTheCat() {
ClientCat cat = DI.makeCat();
cat.fix();
}
}
// This class runs on a different server
public class RemoteCatService {
public void fixTheCat(CatDTO dto) {
ServerCat cat = DI.makeCat();
cat.fixed = dto.fixed;
cat.fix();
}
}
Anemic
----------
public class Cat {
boolean fixed;
}
public class Client {
@Inject RemoteCatService cs;
public void fixTheCat() {
Cat cat = new Cat();
cat = cs.fixTheCat(cat);
}
}
// This class runs on a different server
public class RemoteCatService {
@Inject EntityManager em;
public Cat fixTheCat(Cat cat) {
cat.fixed = true;
em.persist(cat);
return cat;
}
}
I like the second one personally. Less code and easy to manage. Plus,
I can pass my Cat around anywhere I want without transforming it into
other objects. In n-tiered systems, you could potentially pass the Cat
all the way from the front-end to the last tier and then back up. This
is how we built most stuff at Orbitz.
-bp
// Cat + business logic
class Person
{
private String name;
String getName();
Money calculateIncomeTax();
}
\-> Key point: all methods operate on the current Person. Unlike anemic
models, you store business logic methods at this level so long as they
apply to a single Person (i.e. calculateIncomeTax()).
// CatService + state
class People
{
private List<Person> people;
void marry(Person first, Person second);
List<Person> getMarriedPeople();
}
You would reuse the same Person implementation on both client and
server while varying the implementation of People. For your cats
example, you'd have Cat and Cats instead of Cat and CatService.
Gili
With respect to #1 I would suggest injecting two different
implementations of Persons for the client and server. That is, the code
lives inside the Persons instance, but the concrete implementation would
vary.
Again, I am sort of making this up as I go along but it feels right so far.
Gili
Brian Pontarelli wrote:
> A few questions:
>
> 1. Where is the implementation (actual code) for the /Money
> calculateIncomeTax(); method located?/
>
> 2. Why isn't the /marry()/ method on Person like this: /marry(Person
> other);/?
On the flip-side, if you put the logic into the Person class itself
rather than on the server, you end up with a headache when the tax
laws change and you need to push out a new version of the Person class.
I guess that is my main point. The "rich" domain folks talk about
putting logic and data in the same place. But when the logic gets
complex or changes frequently, you _have_ to pull it out into a
service that conforms to an interface. Then it makes sense to put that
logic on another server so that it can be re-used and can scale. Then
you start looking at ways of swapping in new implementations of that
interface at runtime to make updates easier. And you think about
service discovery and all that jazz and BAM, your client is anemic.
You've pulled the logic as far away from the data as you could. Now,
you can still have a "rich" domain on the server. However, if you run
into similar cases on the server, you'll just do it again.
I also think this only applies in certain places. Those are business
domains with business logic. If it looks like to could ever be
distributed, I say make it anemic and service based.
-bp
Brian Pontarelli wrote:
> In terms of the logic for the calculateIncomeTax method, it sounds
> like that is going to be on the server. This means that the client
> version of the Person class will primarily be a proxy to the server.
> Therefore, it doesn't necessarily need to be "rich" because the logic
> is not inside the class itself, but instead defined somewhere else.
> All that you are gaining using a "rich" approach is that you get to
> interact with just the Person class. Once you get to this point, there
> is very little difference between this methodology and using anemic
> domain and services.
For this case there is indeed little difference between the anemic
model and rich model. But for this specific use-case I would flip the
question on you and ask: what do you benefit from a anemic model? Given
the point of using C-style functions and global variables versus OOP why
wouldn't you go for OOP every time?
> I guess that is my main point. The "rich" domain folks talk about
> putting logic and data in the same place. But when the logic gets
> complex or changes frequently, you _have_ to pull it out into a
> service that conforms to an interface.
You have to pull it into an interface, yes, but not necessarily into a
service. Nothing prevents you from defining an interface for
calculateIncomeTax() and providing different implementations in the form
of rich models.
> Then it makes sense to put that
> logic on another server so that it can be re-used and can scale. Then
> you start looking at ways of swapping in new implementations of that
> interface at runtime to make updates easier.
That's a requirement I never had in practice. My assumption has been
that if you have a fail-safe cluster in the first place then you just
update different servers at a time. I find the idea of swapping
implementations at runtime as a form of upgrading quite questionable. It
sounds like it would be much harder to update all necessary classes
atomically and track/log problems if something goes wrong.
> And you think about
> service discovery and all that jazz and BAM, your client is anemic.
> You've pulled the logic as far away from the data as you could. Now,
> you can still have a "rich" domain on the server. However, if you run
> into similar cases on the server, you'll just do it again.
If you absolutely need service discovery then I agree that pretty much
mandates anemic models, but again I question how frequently this
requirement comes up.
Gili
Man, Martin and I would probably blow each up if we got into it. :)
> For this case there is indeed little difference between the anemic
> model and rich model. But for this specific use-case I would flip the
> question on you and ask: what do you benefit from a anemic model?
> Given
> the point of using C-style functions and global variables versus OOP
> why
> wouldn't you go for OOP every time?
The anemic model will produce a well defined wire format that collects
all the data for a Person together. This allows that data to flow
through as many layers/tiers/servers as necessary and be worked on by
anything that understands that class of data. In the end, a large
distributed system is going to be a collection of functions that work
on classes of data.
I find myself coming back to this pattern more and more, but never
taking that step over to fully functional languages. I think the
reason is both due to the ability to organize and encapsulate in OO.
And, I would definitely not use C as a base line. There are many far
more elegant functional languages than C.
I also still use rich-objects at times. It is just not something I
force myself to use for everything. I find that model too restrictive
and not very pragmatic. But, there are still many benefits that I can
achieve from OO concepts like extension, aggregation, polymorphism and
the like. I just find that they also work well with anemic objects and
highly functional services. I guess in the end I don't find OO and
functions to be opposing ideals. They are tools I mix and match to
suit the task at hand.
One idea I've been tossing around lately is a new approach with a
separation of data and function. Not sure what it would look like or
how it would work, but it seems interesting to me. It would allow you
to define a data class such as Human, but have that Human behave like
a Infant at one point in time and a Teenager later. In the reverse,
the Infant might need Human data, but also other data classes to
function properly. Then later on the Teenager might also need the
Human data, but other data to function.
Need to think about it for another year or so to figure it all out. ;)
>
> You have to pull it into an interface, yes, but not necessarily
> into a
> service. Nothing prevents you from defining an interface for
> calculateIncomeTax() and providing different implementations in the
> form
> of rich models.
There probably isn't much keeping us from doing this, even on the
wire. If you consider any service where the wire protocol has the data
and the operation together, you can imagine a system where on the
server the data is first set into the rich-domain and then the
operation is invoked on that same object. The key is to avoid DGC and
shared state. I personally don't use this model, but you could.
However, it will still tend towards anemia when the object on the
server starts to move logic into other locations and other servers.
> That's a requirement I never had in practice. My assumption has been
> that if you have a fail-safe cluster in the first place then you just
> update different servers at a time. I find the idea of swapping
> implementations at runtime as a form of upgrading quite
> questionable. It
> sounds like it would be much harder to update all necessary classes
> atomically and track/log problems if something goes wrong.
I just bring up service discovery and updates because in larger
distributed environments where you have up-time goals, you have to
have some strategy for this. In terms of swapping implementations at
runtime, it is definitely something that I've done in the past and it
works pretty well, if the system is architected correctly. Once your
users are global, you lose any windows for maintenance and this means
that you need to be able to upgrade the system at runtime.
> If you absolutely need service discovery then I agree that pretty
> much
> mandates anemic models, but again I question how frequently this
> requirement comes up.
I'd say that most larger distributed applications use service
discovery and runtime updating. That would just be my guess. The ones
I've worked on use it. BUT, that doesn't mean it isn't something that
can't be figured into other systems without a lot of overhead. More
languages are beginning to come around to the idea of multi-threading
as a core concept and some languages even see runtime updates in that
category as well. If you consider OSGi, JMS (Java Module System), and
languages like Scala, Haskel, and Erlang, you begin to see this
pattern. I find that systems designed this way are far easier to
maintain over the lifetime of the system.
-bp
One idea I've been tossing around lately is a new approach with a
separation of data and function. Not sure what it would look like or
how it would work, but it seems interesting to me. It would allow you
to define a data class such as Human, but have that Human behave like
a Infant at one point in time and a Teenager later. In the reverse,
the Infant might need Human data, but also other data classes to
function properly. Then later on the Teenager might also need the
Human data, but other data to function.
Need to think about it for another year or so to figure it all out. ;)
FWIW this is exactly the motivation behind Qi4j - context based behaviour...
http://www.qi4j.org/introduction.html
there's a mailing list (see http://www.qi4j.org/26.html for subscription/archives)
where the design is regularly discussed and refined, and if you're familiar with
DDD concepts then you should feel right at home