In proyect with Jhipste 4.4.1, Spring Boot, Grandle, MongoDb
#Mapper(componentModel = "spring", uses = {})
public interface OportunidadMapper extends EntityMapper <OportunidadDTO, Oportunidad> {
Is OportunidadDTO ad:
private Long clienteId;
In Oportunidad
#Field("clienteId")
private Long clienteId;
I added a field to the DTO and to the entity but the Mapper does not parse it to me. Do I have to do something else, so that I can recognize it? (They have getter and setter in both classes)
You must recompile your project with gradle so that MapStruct annotation processor re-generates OportunidadMapperImpl class.
Related
I process messages from a queue. I use data from the incoming message to determine which class to use to process the message; for example origin and type. I would use the combination of origin and type to look up a FQCN and use reflection to instantiate an object to process the message. At the moment these processing objects are all simple POJOs that implement a common interface. Hence I am using a strategy pattern.
The problem I am having is that all my external resources (mostly databases accessed via JPA) are injected (#Inject) and when I create the processing object as described above all these injected objects are null. The only way I know to populate these injected resources is to make each implementation of the interface a managed bean by adding #stateless. This alone does not solve the problem because the injected members are only populated if the class implementing the interface is itself injected (i.e. container managed) as opposed to being created by me.
Here is a made up example (sensitive details changed)
public interface MessageProcessor
{
public void processMessage(String xml);
}
#Stateless
public VisaCreateClient implements MessageProcessor
{
#Inject private DAL db;
…
}
public MasterCardCreateClient implements MessageProcessor…
In the database there is an entry "visa.createclient" = "fqcn.VisaCreateClient", so if the message origin is "Visa" and the type is "Create Client" I can look up the appropriate processing class. If I use reflection to create VisaCreateClient the db variable is always null. Even if I add the #Stateless and use reflection the db variable remains null. It's only when I inject VisaCreateClient will the db variable get populated. Like so:
#Stateless
public QueueReader
{
#Inject VisaCreateClient visaCreateClient;
#Inject MasterCardCreateClient masterCardCreateClient;
#Inject … many more times
private Map<String, MessageProcessor> processors...
private void init()
{
processors.put("visa.createclient", visaCreateClient);
processors.put("mastercard.createclient", masterCardCreateClient);
… many more times
}
}
Now I have dozens of message processors and if I have to inject each implementation then register it in the map I'll end up with dozens of injections. Also, should I add more processors I have to modify the QueueReader class to add the new injections and restart the server; with my old code I merely had to add an entry into the database and deploy the new processor on the class path - didn't even have to restart the server!
I have thought of two ways to resolve this:
Add an init(DAL db, OtherResource or, ...) method to the interface that gets called right after the message processor is created with reflection and pass the required resource. The resource itself was injected into the QueueReader.
Add an argument to the processMessage(String xml, Context context) where Context is just a map of resources that were injected into the QueueReader.
But does this approach mean that I will be using the same instance of the DAL object for every message processor? I believe it would and as long as there is no state involved I believe it is OK - any and all transactions will be started outside of the DAL class.
So my question is will my approach work? What are the risks of doing it that way? Is there a better way to use a strategy pattern to dynamically select an implementation where the implementation needs access to container managed resources?
Thanks for your time.
In a similar problem statement I used an extension to the processor interface to decide which type of data object it can handle. Then you can inject all variants of the handler via instance and simply use a loop:
public interface MessageProcessor
{
public boolean canHandle(String xml);
public void processMessage(String xml);
}
And in your queueReader:
#Inject
private Instance<MessageProcessor> allProcessors;
public void handleMessage(String xml) {
MessageProcessor processor = StreamSupport.stream(allProcessors.spliterator(), false)
.filter(proc -> proc.canHandle(xml))
.findFirst()
.orElseThrow(...);
processor.processMessage(xml);
}
This does not work on a running server, but to add a new processor simply implement and deploy.
I upgraded Abp to 4.8.1. After this update my AutoMapper throws this error:
- Missing type map configuration or unsupported mapping.
The issue arises when i try to map a DTO to an Entity
Im how im configuring AbpAutomapper
var thisAssembly = typeof(dsimApplicationModule).GetAssembly();
IocManager.RegisterAssemblyByConvention(thisAssembly);
Configuration.Modules.AbpAutoMapper().Configurators.Add(
// Scan the assembly for classes which inherit from AutoMapper.Profile
cfg => cfg.AddMaps(thisAssembly)
);
My DTO:
[AutoMapTo(typeof(ServiceTemplate))]
public class UpdateServiceTemplateDto : EntityDto, IShouldNormalize, ICustomValidate
{
//properties
}
In AppService, Update Method:
var serviceTemplate = ObjectMapper.Map<ServiceTemplate>(input);
Worked fine before update. I Read that dynamic mapping is depricated in Automapper 8.1.1. Not sure this is considered dynamic though since i use reflection.
I tried creating a JHipster app with one of the options: --skip-client.
Also I disabled Liquibase afterwards.
Then I created a test entry, similar to:
entity Test {
id String,
hireDate ZonedDateTime
}
I put this into a test.jh file, executed on a terminal:
jhipster import-jdl test.jh
When I looked into the Java source of the app, I discovered a Test.java class, id was automatically recognized as a primary key I believe:
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
#SequenceGenerator(name = "sequenceGenerator")
private Long id;
But hireDate was annotated with:
#Column(name = "hire_date")
private ZonedDateTime hireDate;
Why is that?
I created a view "Test" for this entity in my database, also the columns are "Id" and "HireDate".
But with the automaticaly added #Column annotation, the column name for example "hire_date" doesn't exist in my view.
Can I solve this somehow? I this something related to JHipster generator or to do with Spring Boot?
And there is another issue:
#Size(max = 100)
#Column(name = "jhi_type", length = 100)
private String type;
To name a Java field "type" seems ok, but JHipster makes "jhi_type" for #Column
Cheers
These are the JHipster naming conventions: snake-case for columns and camel-case for java entity fields. If you had used Liquibase, this would have worked fine.
You can't configure this behavior in the generator.
Disabling liquibase does not change the fact that you created a view in your database that does not respect JHipster naming conventions. JHipster generates code that expects columns to be named this way. Either you respect these conventions or you modify the generated code manually.
Alternatively, you could try jhispter-db-helper module but it seems this project has been abandoned.
No need to define the id field in the jdl, you get it for free by default.
I've a Groovy project where I use RESTEasy with Weld and deploy to embedded Jetty. What I can't seem to get working is bean validation. RESTEasy documentation says that adding resteasy-validator-provider-11 along with hibernate validator dependencies (hibernate-validator, hibernate-validator-cdi, javax.el-api, javax.el) is enough. But the bean validation is simply ignored by RESTEasy. I curiously also get the following message in the logs:
plugins.validation.ValidatorContextResolver - Unable to find CDI supporting ValidatorFactory. Using default ValidatorFactory
Based on the suggestions on [this][1] post, I tried registering Hibernate InjectingConstraintValidatorFactory in META-INF/validation.xml but it depends on a BeanManager being injected and blows up at runtime.
The code can be found here https://github.com/abhijitsarkar/groovy/tree/master/movie-manager/movie-manager-web
A log gist is here: https://gist.github.com/anonymous/8947319
I've tried everything under the sun without any success. Pls help.
To do this without EE, I believe you'll need to fork the existing InjectingConstraintValidatorFactory but instead of using injection of the bean manager, use the CDI 1.1 class CDI to get a reference to the bean manager, e.g. CDI.current().getBeanManager(). http://docs.jboss.org/cdi/api/1.1/javax/enterprise/inject/spi/CDI.html
You do need to be on CDI 1.1 to do this (so Weld 2+, 2.1.1 is current I believe). Here's an example impl, based on: https://github.com/hibernate/hibernate-validator/blob/master/cdi/src/main/java/org/hibernate/validator/internal/cdi/InjectingConstraintValidatorFactory.java
public class InjectingConstraintValidatorFactory implements ConstraintValidatorFactory {
// TODO look for something with better performance (HF)
private final Map<Object, DestructibleBeanInstance<?>> constraintValidatorMap =
Collections.synchronizedMap( new IdentityHashMap<Object, DestructibleBeanInstance<?>>() );
private final BeanManager beanManager;
public InjectingConstraintValidatorFactory() {
this.beanManager = CDI.current().getBeanManager();
Contracts.assertNotNull( this.beanManager, "The BeanManager cannot be null" );
}
#Override
public <T extends ConstraintValidator<?, ?>> T getInstance(Class<T> key) {
DestructibleBeanInstance<T> destructibleBeanInstance = new DestructibleBeanInstance<T>( beanManager, key );
constraintValidatorMap.put( destructibleBeanInstance.getInstance(), destructibleBeanInstance );
return destructibleBeanInstance.getInstance();
}
#Override
public void releaseInstance(ConstraintValidator<?, ?> instance) {
DestructibleBeanInstance<?> destructibleBeanInstance = constraintValidatorMap.remove( instance );
destructibleBeanInstance.destroy();
}
}
I finally fixed this. Turns out, a validation.xml is not really required, resteasy-cdi module does a fine job of registering the BeanManager. What I was missing and not clearly documented anywhere, is that if an annotation is placed on a method, the validation engine just "decides" what should be validated. I placed a #NotNull on a method and it was validating the return type, not the parameters. One can use validationAppliesTo element in some cases but #NotNull doesn't have it. When I moved it from the method to the parameter, it started working.
Now I ran across what I believe is a Weld bug but I'll post that question separately.
I'm studying how Rhino.Mocks works and trying to understand how can I set manually a value in a class Property.
I have seen a sample in internet where you have only desired Property as argument of Expect.Call(), instead of using a method.
MockRepository mocks = new MockRepository();
Person p = mocks.StrictMock<Person>();
Expect.Call(p.FirstName).Return("John");
Person is a class such as:
public class Person
{
public string FirstName {get;set;}
}
I always receive the error:
Invalid call, the last call has been
used or no call has been made (make
sure that you are calling a virtual
(C#) / Overridable (VB) method).
Am I missing something? Is it possible to set manually class Properties and evaluate them to see if getters and setters are working fine?
As with any mocking framework, Rhino Mocks can only mock interfaces or classes that defines virtual methods and properties.
That's because when implementing a class, Rhino creates a derived class from the one you specify, replacing every virtual (or Overridable in VB) method with a stub implementation that uses an interceptor to handle the call.
When you specify a non virtual method, Rhino can't create a wrapper.
That is also true tor sealed (NonInheritable in VB) classes.
So for your class to work, you should implement the property as such:
public class Person
{
public virtual string FirstName { get; set; }
}
This way Rhino can override the poperty accordingly.