views:

121

answers:

3

Hi guys,

The legacy database I'm "springwrapping" has Id's that are Strings and that give away some information. For instance, a UserId looks like "DK-6715-00001", meaning a user in Denmark, postal code 6715. This is so wrapped into the enterprise applications that it needs to be kept and my entities verify this in their setter methods.

But, User also has the fields country and postal code, so when an Id for the bean is set, it might as well also set country and postal code. For this, it needs the CountryService to look up that Dk is the Denmark Country object, and look up 6715 with the newly found Country object in PostalService.

First of all, can I wire this up so that I can access CountryService and PostalService from my Entity object? (Entities are defined long before the service objects in my bean definition) Second of all, this should violate any nice design principles. Is there a better design I could do then to let my entities carry references to service beans?

Cheers

Nik

+1  A: 

If you're looking for design advice, here's my $0.02: Entities should not have references to service beans. Services should operate on entities, not the other way around. So if you find that you need a reference to a service in one of your entity classes, it's probably an indicator that there is too much business logic inside the entity class. As a rule of thumb, business logic is OK inside an entity class as long as the logic only deals with that single object or is quite simple (e.g. an equals method). But if business logic is "cross-entity" (involving more than one entity object), it should be implemented in a service bean.

If you don't care what I think and you just want to make your design work: You can inject Spring bean references inside entities using AspectJ. I believe it requires an extra compile step and/or runtime support from AsjectJ. There is no way to do it with Spring proper because the service objects would need to be injected at the time the entity object is created with the new keyword, which Spring doesn't support.

Rob H
It's a compile step for AspectJ - 'normal' AOP is accomplished at runtime.
Nathan
I'm equally looking for both answers, both how do I do this if this is the route I'll have to go, but also what designs are preferable. So from your design perspective, "make a new danish user" would be a business statement, while "make a new user" would be an entity statement?
niklassaers
@niklassaers - Yes, I could certainly imagine a UserAccountService that creates users, assigns roles, resets passwords, etc. And part of the "create user" use case might involve looking up supplemental data like a country code if that's what you require to be in the user ID.
Rob H
Super, thank you very much :-)
niklassaers
The normal AOP I was referring to was the Spring AOP APIs. That magic happens at runtime. AspectJ is unique in that it uses bytecode weaving to accomplish the same thing, only at compile time.
Nathan
You can do load-time weaving, so AspectJ isn't necessarily an additional compilation step.
hbunny
A: 

It sounds like this is logic that should be placed in a Controller.

That UserCreationController (with the possible addition of a UserService) should have references to those CountryService or PostalService, and (maybe) JdbcService or HibernateService depending on your app.

Entity classes (or POJOs) should err on the side of simplicity.

Edit: It's the business logic that separates the two. The controller receives the form data, maps that to your domain entity, calls your business logic (service/s) and based on the result, decides where the user shall go.

Nathan
What's your separation between controller and service? I've always thought that controller is where my interface meets my service, so the way I read your answer I would think you'd have this in a service?
niklassaers
Nathan: Are there any other 'normal' AOP implementations for Java you'd recommend?
niklassaers
@niklassaers: edited
Nathan
A: 

Hi guys, thanks for your input. I've decided that it is indeed a design flaw, and that I was thinking the wrong way about it. I should totally remove the setter-method for the Id property, and just have a getter for it, and then have setters and getters for the other properties that make up the Id. This way, I don't have to work hard to ensure that the Id formatting becomes correct, and I don't have to access any services.

Cheers

Nik

niklassaers