I'm using EF 4.1 Code First. I have an entity defined with a property like this:
public class Publication
{
// other stuff
public virtual MailoutTemplate Template { get; set; }
}
I've configured this foreign key using fluent style like so:
modelBuilder.Entity<Publication>()
.HasOptional(p => p.Template)
.WithMany()
.Map(p => p.MapKey("MailoutTemplateID"));
I have an MVC form handler with some code in it that looks like this:
public void Handle(PublicationEditViewModel publicationEditViewModel)
{
Publication publication = Mapper.Map<PublicationEditViewModel, Publication>(publicationEditViewModel);
publication.Template = _mailoutTemplateRepository.Get(publicationEditViewModel.Template.Id);
if (publication.Id == 0)
{
_publicationRepository.Add(publication);
}
else
{
_publicationRepository.Update(publication);
}
_unitOfWork.Commit();
}
In this case, we're updating an existing Publication entity, so we're going through the else path. When the _unitOfWork.Commit() fires, an UPDATE is sent to the database that I can see in SQL Profiler and Intellitrace, but it does NOT include the MailoutTemplateID in the update.
What's the trick to get it to actually update the Template?
Repository Code:
public virtual void Update(TEntity entity)
{
_dataContext.Entry(entity).State = EntityState.Modified;
}
public virtual TEntity Get(int id)
{
return _dbSet.Find(id);
}
UnitOfWork Code:
public void Commit()
{
_dbContext.SaveChanges();
}
depends on your repository code. :) If you were setting publication.Template while Publication was being tracked by the context, I would expect it to work. When you are disconnected and then attach (with the scenario that you have a navigation property but no explicit FK property) I'm guessing the context just doesn't have enough info to work out the details when SaveChanges is called. I'd do some experiments. 1) do an integration test where you query the pub and keep it attached to the context, then add the template, then save. 2) stick a MailOutTemplateId property on the Publicaction class and see if it works. Not suggesting #2 as a solution, just as a way of groking the behavior. I"m tempted to do this experiment, but got some other work I need to do. ;)
I found a way to make it work. The reason why I didn't initially want to have to do a Get() (aside from the extra DB hit) was that then I couldn't do this bit of AutoMapper magic to get the values:
Publication publication = Mapper.Map<PublicationEditViewModel, Publication>(publicationEditViewModel);
However, I found another way to do the same thing that doesn't use a return value, so I updated my method like so and this works:
public void Handle(PublicationEditViewModel publicationEditViewModel)
{
Publication publication = _publicationRepository.Get(publicationEditViewModel.Id);
_mappingEngine.Map(publicationEditViewModel, publication);
// publication = Mapper.Map<PublicationEditViewModel, Publication>(publicationEditViewModel);
publication.Template = _mailoutTemplateRepository.Get(publicationEditViewModel.Template.Id);
if (publication.Id == 0)
{
_publicationRepository.Add(publication);
}
else
{
_publicationRepository.Update(publication);
}
_unitOfWork.Commit();
}
I'm injecting an IMappingEngine now into the class, and have wired it up via StructureMap like so:
For<IMappingEngine>().Use(() => Mapper.Engine);
For more on this, check out Jimmy's AutoMapper and IOC post.
Related
Hi I want to test duplication by adding same fixture more than twice. It could be the code below:
#Test(expected=DuplicationException.class)
public void saveFailedWithDuplicatedAccount(){
memberServiceImpl.save(member);
memberServiceImpl.save(member);
}
but I don't know how to deal with Mockito coding - like using when(), verify(). Since I am new to mockito, and I have got nothing found in the Google, so is there any example code to check duplicating addition?
You need to save state somewhere.
It may be some kind of internal storage or real database.
And you can extract logic for searching duplicates and mock that.
For example:
Test(expected = DuplicationException.class)
public void saveFailedWithDuplicatedAccount() {
DuplicateService duplicateServiceMock = Mockito.mock(DuplicateService.class);
memberServiceImpl.setDuplicateService(duplicateServiceMock);
memberServiceImpl.save(member);
Mockito.when(duplicateServiceMock.isDuplicate(member)).thenReturn(true);
memberServiceImpl.save(member);
}
public class DuplicateAccountService {
public boolean isDuplicateAccount(String login) {
return false; // Some logic for find duplicates
}
}
Suppose I have two sets of controllers in Spring:
/jsonapi1/*
/jsonapi2/*
both of which return objects that are to be interpretted as JSON text.
I'd like some kind of filter to wrap the responses from one set of these controllers so that:
the original response is contained within another object.
For example, if /jsonapi1/count returns:
{"num_humans":123, "num_androids":456}
then the response should be wrapped and returned as follows:
{ "status":0,
"content":{"num_humans":123, "num_androids":456}
}
if an exception happens in the controller, then filter should catch the exception and report it as follows
{ "status":5,
"content":"Something terrible happened"
}
The responses from the other controllers are returned unchanged.
We're currently customizing a MappingJackson2HttpMessageConverter passed to WebMvcConfigurerAdapter.configureMessageConverters in order to perform the above tasks. Works great except that it doesn't seem possible for this approach to be selective about the URLs (or controller classes) it applies to.
Is it possible to apply these kinds of wrappers to individual controller classes or URLs?
Update: Servlet filters look like a solution. Is it possible chose which filter gets applied to which controller methods, or which URLs?
I was struggling on this for multiple days. The solution by #Misha didn't work for me. I was able to finally get this working using ControllerAdvice and ResponseBodyAdvice.
ResponseBodyAdvice allows to inject custom transformation logic on the response returned by a controller but before it is converted to HttpResponse and committed.
This is how my controller method looks:
#RequestMapping("/global/hallOfFame")
public List<HallOfFame> getAllHallOfFame() {
return hallOfFameService.getAllHallOfFame();
}
Now i wanted to add some standard fields around the response like devmessage and usermessage. That logic goes into the ResponseAdvice:
#ControllerAdvice
public class TLResponseAdvice implements ResponseBodyAdvice<Object> {
#Override
public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
return true;
}
#Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType,
Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request,
ServerHttpResponse response) {
// TODO Auto-generated method stub
final RestResponse<Object> output = new RestResponse<>();
output.setData(body);
output.setDevMessage("ResponseAdviceDevMessage");
output.setHttpcode(200);
output.setStatus("Success");
output.setUserMessage("ResponseAdviceUserMessage");
return output;
}
}
The entity classes look like this:
#Setter // All lombok annotations
#Getter
#ToString
public class RestResponse<T> {
private String status;
private int httpcode;
private String devMessage;
private String userMessage;
private T data;
}
#Entity
#Data // Lombok
public class HallOfFame {
#Id
private String id;
private String name;
}
To handle exceptions, simply create another ControllerAdvice with ExceptionHandler. Use the example in this link.
Advantages of this solution:
It keeps your controllers clean. You can support any return type from your controller methods.
Your controller return type class does not need to extend some base class as required by the AOP approach.
You do not need to hack your way through Spring filters by using HttpServletResponseWrappers. They come up with a performance penalty.
EDIT - 17th September 2019
To handle exceptions use #ExceptionHandler. Refer code below.
#ExceptionHandler(Exception.class)
#ResponseBody
public MyResponseEntity<Object> handleControllerException(HttpServletRequest request, Throwable ex) {
// default value
int httpCode = HttpStatus.INTERNAL_SERVER_ERROR.value();
if(ex instanceof ResourceNotFoundException) {
httpCode = HttpStatus.NOT_FOUND.value();
}
...
}
The way I understand your question, you have exactly three choices.
Option #1
Manually wrap your objects in simple SuccessResponse, ErrorResponse, SomethingSortOfWrongResponse, etc. objects that have the fields you require. At this point, you have per-request flexibility, changing the fields on one of the response wrappers is trivial, and the only true drawback is code repetition if many of the controller's request methods can and should be grouped together.
Option #2
As you mentioned, and filter could be designed to do the dirty work, but be wary that Spring filters will NOT give you access to request or response data. Here's an example of what it might look like:
#Component
public class ResponseWrappingFilter extends GenericFilterBean {
#Override
public void doFilter(
ServletRequest request,
ServletResponse response,
FilterChain chain) {
// Perform the rest of the chain, populating the response.
chain.doFilter(request, response);
// No way to read the body from the response here. getBody() doesn't exist.
response.setBody(new ResponseWrapper(response.getStatus(), response.getBody());
}
}
If you find a way to set the body in that filter, then yes, you could easily wrap it up. Otherwise, this option is a dead end.
Option #3
A-ha. So you got this far. Code duplication is not an option, but you insist on wrapping responses from your controller methods. I'd like to introduce the true solution - aspect-oriented programming (AOP), which Spring supports fondly.
If you're not familiar with AOP, the premise is as follows: you define an expression that matches (like a regular expression matches) points in the code. These points are called join points, while the expressions that match them are called pointcuts. You can then opt to execute additional, arbitrary code, called advice, when any pointcut or combination of pointcuts are matched. An object that defines pointcuts and advice is called an aspect.
It's great for expressing yourself more fluently in Java. The only drawback is weaker static type checking. Without further ado, here's your response-wrapping in aspect-oriented programming:
#Aspect
#Component
public class ResponseWrappingAspect {
#Pointcut("within(#org.springframework.stereotype.Controller *)")
public void anyControllerPointcut() {}
#Pointcut("execution(* *(..))")
public void anyMethodPointcut() {}
#AfterReturning(
value = "anyControllerPointcut() && anyMethodPointcut()",
returning = "response")
public Object wrapResponse(Object response) {
// Do whatever logic needs to be done to wrap it correctly.
return new ResponseWrapper(response);
}
#AfterThrowing(
value = "anyControllerPointcut() && anyMethodPointcut()",
throwing = "cause")
public Object wrapException(Exception cause) {
// Do whatever logic needs to be done to wrap it correctly.
return new ErrorResponseWrapper(cause);
}
}
The final result will be the non-repeating response wrapping that you seek. If you only want some or one controller receive this effect, then update the pointcut to match methods only within instances of that controller (rather than any class holding the #Controller annotation).
You'll need to include some AOP dependencies, add the AOP-enabling annotation in a configuration class, and make sure something component-scans the package this class is in.
Simplest way i manage custom responses from controllers is by utilising the Map variable.
so your code ends up looking like:
public #ResponseBody Map controllerName(...) {
Map mapA = new HashMap();
mapA.put("status", "5");
mapA.put("content", "something went south");
return mapA;
}
beauty of is is that you can configure it any thousand ways.
Currently i use for object transmition, custom exception handling and data reporting, too easy.
Hope this helps
I am also using AOP with #Around. Developed a custom annotation and using that for point cut. I am using a global Response. It has the status, Message and data which is of type List of type
List <? extends parent> dataList
( which can solve your class cast exception). All the entities extends this Parent class. This way I can set all the data into my List.
Also I am using the message key as param with the custom annotation and setting it in action.
Hope this helps.
I'm experimenting with interception in Castle Windsor and notice that interceptors seem to be created as decorators of my service interface.
In other words, if I have an interface "ISomethingDoer" and a concrete "ConcreteSomethingDoer", the proxy implements ISomethingDoer but does not inherit from ConcreteSomethingDoer.
This is fine, and no doubt by design, but what I'm wondering is whether I can intercept protected virtual methods in my concrete classes that wouldn't be known by the public interface. I am doing this in order to add logging support, but I might want to log some of the specific internal details of a class.
In my slightly unimaginative test case I have this:
public interface ISomethingDoer
{
void DoSomething(int Count);
}
[Loggable]
public class ConcreteSomethingDoer : ISomethingDoer
{
public void DoSomething(int Count)
{
for (var A = 0; A < Count; A++)
{
DoThisThing(A);
}
}
[Loggable]
protected virtual void DoThisThing(int A)
{
("Doing a thing with " + A.ToString()).Dump();
}
}
So what I want to do is log calls to "DoThisThing" even though it's not part of the interface.
I've managed to get this working in Autofac. (I've created a Linqpad script here: http://share.linqpad.net/frn5a2.linq) but am struggling with Castle Windsor (see http://share.linqpad.net/wn7877.linq)
In both cases my interceptor is the same and looks like this:
public class Logger : IInterceptor
{
public void Intercept(IInvocation Invocation)
{
String.Format("Calling method {0} on type {1} with parameters {2}",
Invocation.Method.Name,
Invocation.InvocationTarget.GetType().Name,
String.Join(", ", Invocation.Arguments.Select(a => (a ?? "*null*").ToString()).ToArray())).Dump();
Invocation.Proceed();
"Done".Dump();
}
}
What I really want to do is say "any classes with a [Loggable] attribute, should use the logging interceptor". In the Autofac example I've specifically attached a logger to the registration, whereas with Castle I'm using an IModelInterceptorsSelector which looks like this:
public class LoggerInterceptorSelector : IModelInterceptorsSelector
{
public bool HasInterceptors(ComponentModel Model)
{
return Model.Implementation.IsDefined(typeof(LoggableAttribute), true);
}
public InterceptorReference[] SelectInterceptors(ComponentModel Model, InterceptorReference[] Interceptors)
{
return new[]
{
InterceptorReference.ForType<Logger>()
};
}
}
Finally, the code to execute all this is:
var Container = new WindsorContainer();
Container.Register(
Component.For<Logger>().LifeStyle.Transient
);
Container.Kernel.ProxyFactory.AddInterceptorSelector(new LoggerInterceptorSelector());
Container.Register(
Component.For<ISomethingDoer>()
.ImplementedBy<ConcreteSomethingDoer>()
.LifeStyle.Transient
);
var Doer = Container.Resolve<ISomethingDoer>();
Doer.DoSomething(5);
When run I would expect to see "Calling method DoThisThing with parameters x" for each time the method is called. Instead I only get the call to DoSomething logged.
I can see why Castle Windsor is doing this, but I'm wondering if there is a way to tweak the behaviour?
(As a side-note I don't want to use Windsor's own interceptor attributes as I don't want to introduce dependencies to Castle outside of my composition root.)
I have tried resolving the ConcreteSomethingDoer specifically and this works, but not if I'm resolving the ISomethingDoer.
Apologies for the long post, and also apologies because I am pretty new to Castle Windsor!
I you could register like:
Container.Register(
Component.For<ISomethingDoer, ConcreteSomethingDoer>()
.ImplementedBy<ConcreteSomethingDoer>()
.LifeStyle.Transient
);
This should create a class proxy by deriving from ConcreteSomethingDoer. However this won't work with dynamic interceptors. However you probably can work around that by creating a facility which registers the interceptor when needed.
I have a model roughly like this:
public interface IUnitOfWork { }
public class UnitOfWork : IUnitOfWork { }
public interface IService { }
public class Service : IService
{
public IUnitOfWork UnitOfWork { get; set; }
}
public class ViewModel
{
public IService Service { get; set; }
}
And a configuration that could be like this:
container.Register(Component.For<IService>().ImplementedBy<Service>()
.LifeStyle.Transient
Component.For<IUnitOfWork>().ImplementedBy<UnitOfWork>()
.LifeStyle.Transient,
Component.For<ViewModel>().LifeStyle.Transient);
I need to resolve, at different points, two instances of ViewModel (I'm using a typed factory for this, but let's leave that aside for simplicity and assume I'm using the raw container)
The catch is that I need to resolve two instances of ViewModel at different points (from another ViewModel that knows about both), and they need to share the same IUnitOfWork.
So, something like this:
var vm1 = container.Resolve<ViewModel>();
//...later
var vm2 = container.Resolve<ViewModel>();
Now, it's very easy to share the Service. I'd just have to do something like:
var vm2 = container.Resolve<ViewModel>(new { vm1.Service });
But of course the actual model is more complicated (different ViewModels, with more Services each), so that's not an option.
I can pass the UnitOfWork to Resolve, but it doesn't get used by default (which makes sense). Is there any way to use that parameter (probably by registering a delegate somewhere) when resolving the second ViewModel?
I'd like to be able to do the following:
var vm2 = container.Resolve<ViewModel>(new { UnitOfWork });
And get a ViewModel whose Service has that specific UnitOfWork.
If you need to share a component and you cannot set as singleton(rich client) or perwebrequest, you need to use Contextual lifestyle.
check this thread see my last comment to downoload contrib w/ Contextual Lifestyle
For you case I assume those 2 ViewModel will be used by 1 View... so View + UoW require Contextual Lifestyle
check also this one too see comments at the end
The solution was to use ContextualLifestyle coupled with a custom factory that kept a reference to the ContainerContext, in order to use the same one when resolving another ViewModel.
Summary:
I want to save two classes of the same name and different namespaces with the Fluent NHibernate Automapper
Context
I'm writing having to import a lot of different objects to database for testing. I'll eventually write mappers to a proper model.
I've been using code gen and Fluent NHibernate to take these DTOs and dump them straight to db.
the exception does say to (try using auto-import="false")
Code
public class ClassConvention : IClassConvention
{
public void Apply(IClassInstance instance)
{
instance.Table(instance.EntityType.Namespace.Replace(".", "_"));
}
}
namespace Sample.Models.Test1
{
public class Test
{
public virtual int Id { get; set; }
public virtual string Something { get; set; }
}
}
namespace Sample.Models.Test2
{
public class Test
{
public virtual int Id { get; set; }
public virtual string SomethingElse { get; set; }
}
}
And here's the actual app code
var model = AutoMap.AssemblyOf<Service1>()
.Where(t => t.Namespace.StartsWith("Sample.Models"))
.Conventions.AddFromAssemblyOf<Service1>();
var cfg = Fluently.Configure()
.Database(
MySQLConfiguration.Standard.ConnectionString(
c => c.Is("database=test;server=localhost;user id=root;Password=;")))
.Mappings(m => m.AutoMappings.Add(model))
.BuildConfiguration();
new SchemaExport(cfg).Execute(false, true, false);
Thanks I really appreciate any help
Update using Fluent Nhibernate RC1
solution from fluent-nhibernate forums by James Gregory
Got around to having a proper look at
this tonight. Basically, it is down to
the AutoImport stuff the exception
mentioned; when NHibernate is given
the first mapping it sees that the
entity is named with the full assembly
qualified name and creates an import
for the short name (being helpful!),
and then when you add the second one
it then complains that this import is
now going to conflict. So the solution
is to turn off the auto importing;
unfortunately, we don't have a way to
do that in the RC... I've just
commited a fix that adds in the
ability to change this in a
convention. So if you get the latest
binaries or source, you should be able
to change your Conventions line in
your attached project to do this:
.Conventions.Setup(x => {
x.AddFromAssemblyOf<Program>();
x.Add(AutoImport.Never()); });
Which adds all the conventions you've
defined in your assembly, then uses
one of the helper conventions to turn
off auto importing.
I was not able to get this to work using Conventions for FluentMappings (in contrast to AutoMappings). However, the following works for me, though it must be added to each ClassMap where needed.
public class AMap : ClassMap<A>
{
public AMap()
{
HibernateMapping.Not.AutoImport();
Map(x => x.Item, "item");
...
}
}
I am having real problem with this, and the example above or any of its variants do not help.
var cfg = new NotifyFluentNhibernateConfiguration();
return Fluently.Configure()
.Database(
FluentNHibernate.Cfg.Db.MsSqlConfiguration.MsSql2005
.ConnectionString("Server=10.2.65.227\\SOSDBSERVER;Database=NotifyTest;User ID=NHibernateTester;Password=test;Trusted_Connection=False;")
)
.Mappings(m => {
m.AutoMappings
.Add(AutoMap.AssemblyOf<SubscriptionManagerRP>(cfg));
m.FluentMappings.Conventions.Setup(x =>
{
x.AddFromAssemblyOf<Program>();
x.Add(AutoImport.Never());
});
} )
.BuildSessionFactory();
I can't find Program's reference..
I've also tried to put down a seperate xml file to in desperation config fluent nhibernate's mapping to auto-import = false with no success.
Can I please have some more extensive example on how to do this?
Edit, I got the latest trunk just weeks ago.
Edit, Solved this by removing all duplicates.
I have had the same problem. I solved it like this:
Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2008
.ConnectionString(...)
.AdoNetBatchSize(500))
.Mappings(m => m.FluentMappings
.Conventions.Setup(x => x.Add(AutoImport.Never()))
.AddFromAssembly(...)
.AddFromAssembly(...)
.AddFromAssembly(...)
.AddFromAssembly(...))
;
The imported part is: .Conventions.Setup(x => x.Add(AutoImport.Never())). Everything seems to be working fine with this configuration.
Use the BeforeBindMapping event to gain access to the object representation of the .HBM XML files.
This event allows you to modify any properties at runtime before the NHibernate Session Factory is created. This also makes the FluentNHibernate-equivalent convention unnecessary. Unfortunately there is currently no official documentation around this really great feature.
Here's a global solution to duplicate mapping problems ( Just remember that all HQL queries will now need to use Fully Qualified Type names instead of just the class names ).
var configuration = new NHibernate.Cfg.Configuration();
configuration.BeforeBindMapping += (sender, args) => args.Mapping.autoimport = false;
I had to play around with where to add the convention AutoImport.Never() to. I have my persistence mapping separated into different projects - models for each application can also be found in different projects. Using it with Fluent NHibernate and auto mapping.
There are occasions when domains, well mappings really have to be combined. This would be when I need access to all domains. POCO classes used will sometimes have the same name and different namespaces, just as examples above.
Here is how my combine all mapping looks like:
internal static class NHIbernateUtility
{
public static ISessionFactory CreateSessionFactory(string connectionString)
{
return Fluently.Configure()
.Database(
MsSqlConfiguration
.MsSql2008
.ConnectionString(connectionString))
.Mappings(m => m.AutoMappings
.Add(ProjectA.NHibernate.PersistenceMapper.CreatePersistenceModel()))
.Mappings(m => m.AutoMappings
.Add(ProjectB.NHibernate.PersistenceMapper.CreatePersistenceModel()))
.Mappings(m => m.AutoMappings
.Add(ProjectC.NHibernate.PersistenceMapper.CreatePersistenceModel())).BuildSessionFactory();
}
}
And one of the persistence mappers:
public static class PersistenceMapper
{
public static AutoPersistenceModel CreatePersistenceModel()
{
return
AutoMap.AssemblyOf<Credential>(new AutoMapConfiguration())
.IgnoreBase<BaseEntity>()
.Conventions.Add(AutoImport.Never())
.Conventions.Add<TableNameConvention>()
.Conventions.Add<StandardForeignKeyConvention>()
.Conventions.Add<CascadeAllConvention>()
.Conventions.Add<StandardManyToManyTableNameConvention>()
.Conventions.Add<PropertyConvention>();
}
}
Persistence mappers are very similar for each POCO namespace - some have overrides. I had to add .Conventions.Add(AutoImport.Never()) to each persistence mapper and it works like a charm.
Just wanted to share this if anyone else is doing it this way.