Can't map property String to JAXBElement<String> using MapStruct - mapstruct

so I was playing a bit with Mapstruct, reading the reference Documentation for the Version 1.1.0.Final, and arrived at the point:
implicit type conversions
where is defined the following statement:
Between JAXBElement < T> and T
I tried that, but the error what I received was:
Can't map property "java.lang.String xmlElement" "javax.xml.bind.JAXBElement<java.lang.String> xmlElement".
Consider to declare/implement a mapping method:
javax.xml.bind.JAXBElement<java.lang.String> map(java.lang.String value)".
I know thisi is the same thread asCan't map property when using MapStruct but since then Mapstruct released a new version.
Am I doing something wrong or this feature really is missing?
Thank you.

Mapping from JAXBElement<T> to T works out of the box. For the reverse you need to make sure that the ObjectFactory(ies) are in the Mapper#uses, MapStruct uses those methods to create the types.
You can also have a look at this integration test.

In case this happens on Java 9 or higher and you use implementation of type JAXBElement from maven library (in my case'javax.xml.bind:jaxb-api') make sure it is on the classpath of the annotation processor - this resolved the issue for me.

If your JAXBElement was generated by a wsdl client generator (eg. xjc) you need to provide the corresponding ObjectFactory.class generated by the client generator:
#Mapper(uses = ObjectFactory.class)
public interface OrderMapper {
Order orderEntityToExternalOrder(OrderEntity orderEntity);
}
See:
MapStruct 1.0.0.Beta1 is out with JAXB support, custom factories, decorators and more

Related

Autofac RegisterAssemblyTypes tries to resolve all public types

Quick question: I've been using autofac with asp.net core in a project and I've noticed that it tries to resolve all types during configuration after updating it to the latest nuget package (going from Autofac.Extensions.DependencyInjection 5.0.1 to 7.0.2). Btw, here's the code that was being used to register the types:
builder.RegisterAssemblyTypes(typeof(Utilizador).Assembly)
.AsImplementedInterfaces()
.AsSelf();
Until now, I wasn't seeing this behavior. The problem with this new approach is that it will try to resolve types that will never be injected through DI. For instance, it complains about public classes that don't have public constructors event though those classes will never be created through DI.
Can someone point me to when this change happened?
Does this mean that now I must filter the types I need explicitly?
Thanks.
This is nothing new.
You can filter those out with something like below:
builder.RegisterAssemblyTypes(ThisAssembly)
.Where(type => type.GetConstructors(BindingFlags.Public).Any())
.AsImplementedInterfaces();

Turn off "builders" in MapStruct when using Immutables

How do I completely disable using "builders" in MapStruct? I don't want to use them at all as they are causing all kinds of issues for me.
I created the service file under META-INF (I would prefer a way to assign it to the mapping builder= but I did not see any examples how to do it right in code).
It is still trying to use Immutables "builder" instance instance of the "ModifiableXXX" instance I want to map to. I'd even take a way of forcing it to the modifiable type if that is available.
In another mapping, using an update the ModifiableXXX (with #AfterMapping and #MappingTarget) approach works.
My mapper looks like this right now:
#Mapper
public interface MongoProjectMapper
{
ModifiableProject mapModel(MongoProject project);
#AfterMapping
ModifiableProject updateProject(MongoEntity e, #MappingTarget ModifiableProject p);
}
From Mapstruct version 1.3.1.Final we can use annotation org.mapstruct.Builder#disableBuilder within: #BeanMapping, #Mapper or #MapperConfig
#Mapper(builder = #Builder(disableBuilder = true))
public interface ProjectMapper
Have a look at #mapping-with-builders and documentation
Completely disabling builders is possible via the NoOpBuilderProvider. You need to create a org.mapstruct.ap.spi.BuilderProvider file in the META-INF/services directory with org.mapstruct.ap.spi.NoOpBuilderProvider as it’s content. This will completely disable the builders.
There is a feature request to make this more granular and disable it via #BeanMapping or on the mapper level. Have a look at mapstruct/mapstruct#1661

Is there any way to create a fake from a System.Type object in FakeItEasy?

Is there any way to create a fake from a System.Type object in FakeItEasy? Similar to:
var instance = A.Fake(type);
I try to write a fake container for AutoFac that automatically return fakes for all resolved types. I have looked in the code for FakeItEasy and all methods that support this is behind internal classes but I have found the interface IFakeObjectContainer that looks pretty interesting, but the implementations still need registration of objects that is the thing that I want to come around.
As of FakeItEasy 2.1.0 (but do consider upgrading to the latest release for more features and better bugfixes), you can create a fake from a Type like so:
using FakeItEasy.Sdk;
…
object fake = Create.Fake(type);
If you must use an earlier release, you could use some reflection based approach to create a method info for the A.Fake() method. (since it's about auto mocking this shouldn't be a problem really).
This is best done using a registration handler. You should look into how AutofacContrib.Moq implements its MoqRegistrationHandler. You'll see that it is actually using the generic method MockRepository.Create to make fake instances. Creating a similar handler for FakeItEasy should be quite simple.

AspectJ problem

Hi I am new to AspectJ and I would like to find out if creating variants of a class using Aspects - I will create another instance of the class as well?
I am guessing that the question is, if I am adding aspects would a new class be created.
The answer is no, as the weaving, either when compiling or at run-time, using AspectJ, will add the changes to the classes that are affected by the aspects, so there is no new class created, it is just that the byte code for the original class and the final class are different.
What do you mean by variants?
If you are asking if AspectJ instantiates copies of your class, the answer is no.
AspectJ uses a design pattern called proxy to intercept calls to your class.

Windsor Container: How to specify a public property should not be filled by the container?

When Instantiating a class, Windsor by default treats all public properties of the class as optional dependencies and tries to satisfy them. In my case, this creates a rather complicated circular dependency which causes my application to hang.
How can I explicitly tell Castle Windsor that it should not be trying to satisfy a public property? I assume there must be an attribute to that extent. I can't find it however so please let me know the appropriate namespace/assembly.
If there is any way to do this without attributes (such as Xml Configuration or configuration via code) that would be preferable since the specific library where this is happening has to date not needed a dependency on castle.
You can use the Castle.Core.DoNotWireAttribute attribute to stop a property from being wired up by the IoC container (this is in the Castle.Core assembly, which means your library only needs to take a dependency on the lightweight Castle.Core assembly - if for example you want to use the code without an inversion of control container altogether, or in a different IoC container).
I don't believe there's any way to prevent wiring from occurring in the Xml configuration, but it would be reasonably easy to add support for this - if I had to do this I would probably:
Introduce some kind of attribute on the property declaration in the xml: <myprop wire="false" />
Inherit from PropertiesDependenciesModelInspector, overriding the InspectProperties method to apply some additional logic to identifying which properties should be added as dependencies to the components model (inspecting the model.Configuration for the wire="false" attribute/value pair).
Inherit from DefaultComponentModelBuilder and override the InitializeContributors to include your replacement PropertiesDependenciesModelInspector - or just remove the existing properties contributor and add your own at run time via the AddContributor/RemoveContributor methods.
Replace the ComponentModelBuilder service instance assigned to the kernel of your container.
Another approach which could work for you is to just manually remove the dependencies from the model before any instances of the service are requested ie.
kernel.GetHandler(typeof(MyComponent)).ComponentModel.Dependencies.RemoveAll(d => d.DependencyKey == "PropertyThatShouldNotBeWired");
YMMV with that approach though - especially if you have startable services or other facilities which may be eagerly instantiating your component after it's registered.
I created a facility to help with this:
Castle.Facilities.OptionalPropertyInjection
I do not know which version of Castle you guys were using at that time, but none of the solution mentioned were working. Plus, there is a lot of dead links.
With castle 3.1, here the solution I came up with (thanks to some castle source code digging):
container.Register(Component.For(type)
.LifestyleTransient()
.Properties( propertyInfo => propertyInfo.PropertyType != typeof(MyOtherType)));
The 'Properties' function adds a property filter used by castle when constructing the ComponentModel. In my case, all properties dependency will be satisfied except the property type 'MyOtherType'.
Maybe it will be helpful for someone. In Windsor 4.1 there is PropertiesIgnore method during registration.
Component.For<Role>().LifestyleTransient().PropertiesIgnore((model, propertyInfo) => true)
DoNotWireAttribute
Class: http://svn.castleproject.org:8080/svn/castle/trunk/Core/Castle.Core/Attributes/DoNotWireAttribute.cs
Test: http://svn.castleproject.org:8080/svn/castle/trunk/InversionOfControl/Castle.Windsor.Tests/IgnoreWireTestCase.cs
This can be achieved by the following code:
var container = new WindsorContainer();
// We don't want to inject properties, only ctors
var propInjector = container.Kernel.ComponentModelBuilder
.Contributors
.OfType<PropertiesDependenciesModelInspector>()
.Single();
container.Kernel.ComponentModelBuilder.RemoveContributor(propInjector);
Source Castle Windsor Documentation
Posted this on the google groups forum too here: http://groups.google.com/group/castle-project-devel/browse_thread/thread/43aa513817bd057a