I'm fairly new to Guice and Warp and am attempting to put together a
typical sample application using warp persistence & JPA. The reasoning
was to create a simple console sample instead of a webapp (many of us
require persistence in applications which have no GUI).
I really like the concept behind warp persistence and wanted to play
around with Guice in a realistic application.
You can find it here: http://code.google.com/p/warp-persist-sample/
I've setup the basic framework and read through the warp
documentation, however I'm definitely running into issues getting it
all to work. I'm pretty sure I need a module (even though I'm using
annotations for my manager and dao injection) to get the warp
persistence running properly. I ran into problems configuring it based
on the warp-persistence test code.
I would really appreciate some help from anyone here who's familiar
with warp persistence and Guice.
I'm planning to keep this sample well documented and grow it step by
step into multiple examples with varying levels of complexity (getting
started, webapp version, etc.).
Please let me know if you'd like commit rights.
Thanks!
should be:
Injector injector = Guice.createInjector(PersistenceService.usingJpa ()
.across(UnitOfWork.TRANSACTION).buildModule());
Injector injector = Guice.createInjector(PersistenceService.usingJpa()
.across(UnitOfWork.TRANSACTION)
.addAccessor( AssetDao.class)
.addAccessor(ProjectDao.class) //etc.
.buildModule());
@Inject private Provider<EntityManager> em;
@Transactional
public Asset saveAsset(Asset asset) {
em.get().persist(asset);
return asset;
}
That's so clean compared to my old Spring JPA setup. ;)
I'll make these changes today and add a little more into it.
I honestly didn't know if it was appropriate to host a new subversion
module for this or whether or not it would be better off as a sub
project within warp-persist. If you would like to setup a samples
project in your warp module we can re-locate this. Up to you.
I'm wondering if I could do the same with warp+guice.
I'll throw it in today to show you what I mean.
Hello:
i have a problem with persitence (i think is my un-knowledge of JPA)
and i know this is not the best place to ask, but since Dhanji seems
to be a really expert i try here.
my problems is the folowing. I have a container (folder) with this
mapping (i only write the significan part):
@Entity
class Container {
@OneToMany(fetch = FetchType.LAZY, mappedBy = "parent")
private List<Container> childs;
@ManyToOne(fetch = FetchType.LAZY)
private Container parent;
}
and some code to add a container inside another one:
Container parent = find(parentId);
Container child = new Container();
parent.addChild(child);
child.setParent(parent);
merge(parent); // i think is now strictly necessary, but...
persist(child);
and when i close the session and ask again for the parent
Container parent = find(theSameParentIdAsBefore)
the parent dont have any child...
any ideas?
thanks in advance
dani
Hello Dhanji for you quick (amazing!) answer. I realize that if i
remove the mappedBy annotation everythink works as expected (!!??).
The thing is that, removing the annotation makes JPA transform the
list into a persisten bag, but if not it leaves at a normal array
list... well, strange from my point of view... i will let it without
until i understan more deeply.
thanks again for the answer!!!
saludos
dani
i'm very happy with the warp-persistence... but there's something a
little bit frustrating to me about the finders...
i was using the dao finder style (not the model driven) but i stop
using because i have to register when i build the persistent module
(something that is not always possible or desirable...) am i missing
something?
thanks again... both libraries are really nice (but currenlty i'm
mostly using persist, because most of my ui are with gwt)
un abrazo
dani
... now i write you maybe i'm making something wrong. i give you an
example
class Content {
@Finder(query = "select AVG(r.value) from Rate r where r.content
= :content")
public Double calculateRate(@Named("content")
final Content content) {
return null;
}
}
i would like to have something like
content = find(id);
rate = content.calculateRate()
but with the use i'm doing to your finders i have to do that
@Inject Content finder;
....
content = find(id);
rate = content.calculateRate()
do i'am using your finders correctly? if so... what are the
differences between a finder and a dao?
i dont know (even i think is not possible easily) to resolve this
problem... if i came with any idea, for sure you will know!
in concrete, i think that return null its not very nice, but i dont
mind very much.
well, thanks for share your knowledge!!
dani
un abrazo
dani
I agree with you on the DAO point. With the tools available now
(especially JPA) it's pretty seldom that you would ever want to swap
in a different implementation.
However what's really shiny to me about the direction you're headed
with warp is that I almost have no need to *implement* the DAO layer,
and yet it still separates the data logic from the managers /
services. Obviously this isn't always necessary, but often enough we
have multiple managers accessing the same DAO methods, and if I call
between my managers it gets messy and isn't ideal should someone want
to swap in their own manager / service implementation. So I still
think the idea of a DAO layer is valuable.
I feel like warp + guice is *almost* there ;) If the CRUD methods were
always abstracted the only time we would ever need to write an actual
DAO implementation is for exceptions to the rule. I.e. Like if I
wanted to always update a modify date in a save/update/create method
at the DAO layer (not a great example, but I can't come up with
anything better at the moment).
I love the idea of having the finders in the interfaces and not having
to clutter up my projects with a bunch of implementations.
Here is the list of methods I would nominate for an abstraction
(always available for any DAO interface):
- CUD operations (everyone has a different opinion on the naming, I.e.
save and remove v.s. persist, merge, delete v.s. create, update,
delete). I personally prefer save and remove but it's really not an
issue to me what they're called.
- get (get could be called read or findByPk etc.)
- getAll (could be called readAll or findAll).
- findByXXXX. Where the convention of the XXXX wildcard can
automagically be assumed to represent a query (I'm a big fan of
convention over configuration). I.e. Through reflection / AOP
findByFieldName with And also being parsed. So I wouldn't even have to
writer the named queries for 99% of my finders.
someDao.findByFirstName wouldn't even need to have a method defined in
the interface. I love this in terms of scalability through conventions
as I can evolve my manager / service layer without touching the DAO
layer for a project.
If all of these we're abstracted we could create an empty DAO
interface called SomeDao and have a manager make any CRUD or finder
call to it. Then we can choose to override the abstraction with a
named query, which will happen occasionally but is still an edge case.
And then if I really really have to I can write the implementation
layer for a DAO method which I can't express through a named query
(very edge case).
- There are very simple projects, usually prototypes, which don't even
require finders, only CRUD operations.
- There is a significant number of projects which require both CRUD
and trivial finder operations, but would never need to define anything
more advanced.
- There is a much smaller number of projects that would need to define
edge finders.
- There is a very small number of projects which would need to provide
an actual DAO implementation.
You could address all of these project types while decreasing the
complexity amongst all of them!
Whew, that was a long post ;)
There is an open source project named Parancoe that I've played around
with that pretty much does everything I've mentioned.
http://wiki.java.net/bin/view/Projects/ParancoePersistenceTutorial
Rick is doing something very similar with Krank, only it's more than
just persistence. Spring based.
http://code.google.com/p/krank/wiki/UsingDAO
AppFuse 2 uses the GenericDao implementation from that IBM article
with some slight differences.
http://appfuse.org/display/APF/Using+JPA
Main things I really like about your warp-persist project?
1) It's using Guice instead of Spring, which is something I want to
play around with.
2) It uses ant instead of Maven2 (I can't stand Maven2 lol), please
stay true to ant, or if you do switch from ant go to buildr or
something better than Maven2 ;)
On Aug 16, 6:25 pm, "Dhanji R. Prasanna" <dha...@gmail.com> wrote:
> Hi Dave
>
> I am generally not a fan of Daos. The purpose behind them was to abstract
> away all the RDBMS load/store operations into state-saving operations
> (save/find/update/remove). So that if one changed the underlying storage
> system (i.e. switched databases) only the DaoImpl ought to change. Since
I would imagine you're more focused on the webapp layer at the moment.
Clean persistence is the holy grail for me though, as I'm often
writing back-end modules without a GUI (ESB, SOA, etc.), or if I do
need a GUI I outsource it (By the way, Wicket looks pretty cool).
> with that pretty much does everything I've mentioned.http://wiki.java.net/bin/view/Projects/ParancoePersistenceTutorial
>
> Rick is doing something very similar with Krank, only it's more than
> just persistence. Spring based.http://code.google.com/p/krank/wiki/UsingDAO
>
> AppFuse 2 uses the GenericDao implementation from that IBM article
> with some slight differences.http://appfuse.org/display/APF/Using+JPA
By the way I'm still having issues with my example. Once I get it
working I'll take a stab at what I've described though if you like and
you can choose whether or not to roll it into your codebase, change
it, or whatever.
I would imagine you're more focused on the webapp layer at the moment.
Clean persistence is the holy grail for me though, as I'm often
writing back-end modules without a GUI (ESB, SOA, etc.), or if I do
need a GUI I outsource it (By the way, Wicket looks pretty cool).
>
> However what's really shiny to me about the direction you're headed
> with warp is that I almost have no need to *implement* the DAO layer,
> and yet it still separates the data logic from the managers /
> services. Obviously this isn't always necessary, but often enough we
> have multiple managers accessing the same DAO methods, and if I call
> between my managers it gets messy and isn't ideal should someone want
> to swap in their own manager / service implementation. So I still
> think the idea of a DAO layer is valuable.
> Main things I really like about your warp-persist project?
> 1) It's using Guice instead of Spring, which is something I want to
> play around with.
> 2) It uses ant instead of Maven2 (I can't stand Maven2 lol), please
> stay true to ant, or if you do switch from ant go to buildr or
> something better than Maven2 ;)
... now i write you maybe i'm making something wrong. i give you an
example
class Content {
@Finder(query = "select AVG(r.value) from Rate r where r.content
= :content")
public Double calculateRate(@Named("content")
final Content content) {
return null;
}
}
i would like to have something like
content = find(id);
rate = content.calculateRate()
but with the use i'm doing to your finders i have to do that
@Inject Content finder;
....
content = find(id);
rate = content.calculateRate()
do i'am using your finders correctly?
if so... what are the
differences between a finder and a dao?
i dont know (even i think is not possible easily) to resolve this
problem... if i came with any idea, for sure you will know!
in concrete, i think that return null its not very nice, but i dont
mind very much.
hello Dhanji (and every other!):
i'm still in doubt, maybe i didnt explain myself very well (my english
is not very good... ;o) ... by the way, what the hell IMO means!??)
i was talking about what i do with dynamic finders and what i would
like to do, and you said:
> Can you explain your use case a bit more? I dont think I see the difference
> in the two methods...
so difference, 1. what i do:
finder.calculateAverage(container);
^^^^^^^^^ => the parameter here
and 2. what i would like to do:
container.calculateAverage();
^^^^^^ => calling the object directly...
(where calculateAverga is a @Finder -select avr(r) from r...- method)
i feel myself doing SOA (again!) instead of MDD (am i right?!) ... i
think the dyncamic finders rise the level of abstraction compared to
the entity manager, thats why i do prefer object.findByName() over
dao.findByName(...) and thats why i prefer object.persist() instead of
entityManager.persist(object). i also really dont care very much if
its a insert into a sql storage or a attach in the current session
since the result i like is that i can found the same object later .
in other order of things:
i readed you tutorial and i liked a lot. very clear. i really like how
do you resolve the URIMapping in warp. i really curious about reading
you next JPA part ;)... also... there is a little bug in your first
example of the second part (newBlog.subject twice!).
its a pitty i'm working hard in a project with only gwt in the client
side, so i only use actively warp-persitence. but i'm still in touch
and curious about the development and evolution of warp... (also,
dreaming with some future ideas i found useful if i could re-use the
warp-templating system outside warp... do you think is easily
possible?)
also, can i use the @SessionScoped annotation from guice in the same
way you use @Singleton? i've tryied: i added
binder.bindAnnotation(@SessionScoped).to(ServerScopes.SESSION) and the
filter to the wem.xml but it doesnt work (does it to you?)
well, thanks about all your feedback and ideas.
un saludo
dani
by the way, what the hell IMO means!??)
so difference, 1. what i do:
finder.calculateAverage(container);
^^^^^^^^^ => the parameter here
and 2. what i would like to do:
container.calculateAverage();
^^^^^^ => calling the object directly...
i feel myself doing SOA (again!) instead of MDD (am i right?!) ... i
think the dyncamic finders rise the level of abstraction compared to
the entity manager, thats why i do prefer object.findByName() over
dao.findByName (...) and thats why i prefer object.persist() instead of
entityManager.persist(object).
in other order of things:
i readed you tutorial and i liked a lot. very clear. i really like how
do you resolve the URIMapping in warp. i really curious about reading
you next JPA part ;)... also... there is a little bug in your first
example of the second part (newBlog.subject twice!).
its a pitty i'm working hard in a project with only gwt in the client
side, so i only use actively warp-persitence. but i'm still in touch
and curious about the development and evolution of warp... (also,
dreaming with some future ideas i found useful if i could re-use the
warp-templating system outside warp... do you think is easily
possible?)
also, can i use the @SessionScoped annotation from guice in the same
way you use @Singleton? i've tryied: i added
binder.bindAnnotation(@SessionScoped).to(ServerScopes.SESSION) and the
filter to the wem.xml but it doesnt work (does it to you?)
well, thanks about all your feedback and ideas.
Both are working now. Please take a peek and let me know if you have
any suggestions.
http://code.google.com/p/warp-persist-sample/
I get your logic about the entity manager being the DAO. I guess my
biggest complaint using the em directly instead of abstracting to a
DAO layer is the casting for the finders. So at the very least
abstracting the finders is desirable... which is what you've already
done.
Or are you simply saying that if my save methods weren't marked as
transactional I would have unexpected behaviour?
Yes the min and max results are definitely useful, I'll add an example
of using these.
I downloaded your example and it finally worked OK. Two small comments
though:
1. You seem to have compiled warp-persist.jar using Java 6 so I get a
"class version" error message at compile time. After substituting the
jar file with the latest build from the warp-persist repository it
worked fine.
2. It would be practical if you added a "run" target in your
build.xml.
Other than that, both the library and the example look cool!
Chris
I backtracked my initial approach to moving krank ( http://code.google.com/p/krank
) from spring to guice and just took out their crud stuff ( because I
still do love having their criteria api for certain things ).
It would be great to have a mix of finders and implementation methods
( especially when you have to dynamically construct a query based on
given information ).
On Aug 16, 6:25 pm, "Dhanji R. Prasanna" <dha...@gmail.com> wrote:
> Hi Dave
>
> I am generally not a fan of Daos. The purpose behind them was to abstract
> away all the RDBMS load/store operations into state-saving operations
> (save/find/update/remove). So that if one changed the underlying storage
> system (i.e. switched databases) only the DaoImpl ought to change. Since
I tried to modify the JpaFinderInterceptor so that if it didn't find
an annotated method, it would just proceed with the invocation.
However, it keeps going into an infinte loop, because the interceptor
is invoked again ( lather, rinse, repeat ).
What am I missing?
I can attach my 'updated' JpaFinderInterceptor and PersistenceModule
( modified to support classes ).
thanks,
-a
On Aug 22, 5:51 pm, Aadi Deshpande <aadi.deshpa...@gmail.com> wrote:
> I took a tack at doing this ( and am currently coming up short, but
> still plugging away ).
>
> I backtracked my initial approach to moving krank (http://code.google.com/p/krank
I am really bad at AOP, so maybe someone here could help me out
I tried to modify the JpaFinderInterceptor so that if it didn't find
an annotated method, it would just proceed with the invocation.
However, it keeps going into an infinte loop, because the interceptor
is invoked again ( lather, rinse, repeat ).
What am I missing?
I can attach my 'updated' JpaFinderInterceptor and PersistenceModule
( modified to support classes ).
thanks,
-a
On Aug 22, 5:51 pm, Aadi Deshpande < aadi.deshpa...@gmail.com> wrote:
> I took a tack at doing this ( and am currently coming up short, but
> still plugging away ).
>
> I backtracked my initial approach to moving krank ( http://code.google.com/p/krank