I have
public class CustomerA {
private String street;
public CustomerA() {
}
//get and set methods
}
public class CustomerB {
private IAddress address;
public CustomerB() {
}
//get and set methods
}
public class Address implements IAddress{
private String street;
public Address () {
}
//get and set methods
}
i want to map CustomerA to CustomerB using dozer
my mapping file
<mapping>
<class-a>CustomerA</class-a>
<class-b bean-factory="CustomerBBeanFactory">CustomerB</class-b>
<field>
<a>street</a>
<b >address.street</b>
</field>
</mapping>
In CustomerBBeanFactory i return a CustomerB object and set the address to new Address(). No use of factory means CustomerB cannot instantiate Address Class from interface.
But i am getting the below when i call the map method
java.lang.NullPointerException
at org.dozer.util.ReflectionUtils.invoke(ReflectionUtils.java:323)
at org.dozer.propertydescriptor.GetterSetterPropertyDescriptor.writeDeepDestinationValue(GetterSetterPropertyDescriptor.java:259)
at org.dozer.propertydescriptor.GetterSetterPropertyDescriptor.setPropertyValue(GetterSetterPropertyDescriptor.java:87)
at org.dozer.fieldmap.FieldMap.writeDestValue(FieldMap.java:94)
at org.dozer.MappingProcessor.writeDestinationValue(MappingProcessor.java:895)
at org.dozer.MappingProcessor.mapFromFieldMap(MappingProcessor.java:349)
Any ideas how this can be fixed ?
looks like the set-method did the trick
<mapping>
<class-a>org.apache.camel.converter.dozer.service.Customer</class-a>
<class-b bean-factory="org.apache.camel.converter.dozer.model.CustomerBeanFactory">org.apache.camel.converter.dozer.model.Customer
</class-b>
<field>
<a>street</a>
<b set-method="setStreet">address.street</b>
</field>
</mapping>
Related
In c# (dotnet core), I can defined an assembly/csproj that
Contains only POCO (aka POJO) classes.
Has zero references to any other library.
Have zero ORM attributes (aka, annotations) on the Poco objects.
Then in another assembly/csproj, I can "fluently" define mappings between the poco and the ORM. (Entity Framework or NHibernate for example).
Example like this: (entity framework core)
public class SchoolDBContext: DbContext
{
public DbSet<Student> Students { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
//Write Fluent API configurations here
//Property Configurations
modelBuilder.Entity<Student>()
.Property(s => s.StudentId)
.HasColumnName("Id")
.HasDefaultValue(0)
.IsRequired();
}
}
(above from https://www.entityframeworktutorial.net/efcore/fluent-api-in-entity-framework-core.aspx)
or NHibernate (below)
public class CarMap : ClassMap<Car>
{
public CarMap()
{
Table( "Vehicles.dbo.Car" );
Id( x => x.CarId );
Map( x => x.Name );
Map( x => x.Year );
HasOne( x => x.SteeringWheel ).PropertyRef( x => x.Car);
}
}
public class SteeringWheelMap : ClassMap<SteeringWheel>
{
public SteeringWheelMap()
{
Table( "Vehicles.dbo.SteeringWheel" );
Id( x => x.SteeringWheelId );
Map( x => x.Diameter );
Map( x => x.Color );
References( x => x.Car, "CarId" ).Unique();
}
}
( above from https://github.com/FluentNHibernate/fluent-nhibernate/wiki/fluent-mapping )
In java, I typically see JPA code like this:
package com.mycompany.pojosandjpaannotationsmixed;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import java.time.OffsetDateTime;
#Entity
#Table(name = "SomeEntityTable")
public class SomeEntity {
#Id
#Column(name = "SomeEntityKey", unique = true)
#GeneratedValue(strategy = GenerationType.AUTO)
private long someEntityKey;
#Column(name = "SomeEntityName", unique = true)
private String someEntityName;
#Column(name = "CreateOffsetDateTime", columnDefinition = "TIMESTAMP WITH TIME ZONE" )
private OffsetDateTime createOffsetDateTime;
public long getSomeEntityKey() {
return someEntityKey;
}
public void setSomeEntityKey(long someEntityKey) {
this.someEntityKey = someEntityKey;
}
public String getSomeEntityName() {
return someEntityName;
}
public void setSomeEntityName(String someEntityName) {
this.someEntityName = someEntityName;
}
public OffsetDateTime getCreateOffsetDateTime() {
return createOffsetDateTime;
}
public void setCreateOffsetDateTime(OffsetDateTime createOffsetDateTime) {
this.createOffsetDateTime = createOffsetDateTime;
}
}
All in the same module (I am using gradle, FYI), aka, all in the same .jar.
Is there anyway in java (8 or 11 or whatever) to separate the POCO from the ORM?
A pojo like this:
public class SomeEntity {
private long someEntityKey;
private String someEntityName;
private OffsetDateTime createOffsetDateTime;
public long getSomeEntityKey() {
return someEntityKey;
}
public void setSomeEntityKey(long someEntityKey) {
this.someEntityKey = someEntityKey;
}
public String getSomeEntityName() {
return someEntityName;
}
public void setSomeEntityName(String someEntityName) {
this.someEntityName = someEntityName;
}
public OffsetDateTime getCreateOffsetDateTime() {
return createOffsetDateTime;
}
public void setCreateOffsetDateTime(OffsetDateTime createOffsetDateTime) {
this.createOffsetDateTime = createOffsetDateTime;
}
}
and the ORM mapping code somewhere else? (in a different module/.jar)?
I found this:
https://vladmihalcea.com/fluent-api-entity-building-with-jpa-and-hibernate/
But again, it looks like the POJO is riddled with annotations.
Yes. The JPA specs states:
The object/relational mapping information can take the form of
annotations on the managed persistence classes included in the
persistence unit, an orm.xml file contained in the META-INF directory
of the root of the persistence unit, one or more XML files on the
classpath and referenced from the persistence. xml file, or a
combination of these.
Annotations is only an option. All mapping information can be defined in xml files, or a combination of both. In the later case, the mapping information on the xml files overrides the annotations.
For example, this could be a META-INF/orm.xml file:
<?xml version="1.0" encoding="UTF-8"?>
<entity-mappings xmlns="http://xmlns.jcp.org/xml/ns/persistence/orm"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence/orm
http://xmlns.jcp.org/xml/ns/persistence/orm_2_2.xsd"
version="2.2">
<entity class="com.mycompany.pojosandjpaannotationsmixed.SomeEntity">
<table name="SomeEntityTable" />
<attributes>
<id name="someEntityKey">
<column name="SomeEntityKey" unique="true" />
<generated-value strategy="AUTO" />
</id>
<basic name="someEntityName">
<column name="SomeEntityName" unique="true" />
</basic>
<!--
....
-->
</attributes>
</entity>
</entity-mappings>
In the REST endpoint I'm building in Spring Boot, I'm trying to pass my vehicleDTO to my controller. But before it reaches my controller, there is an error.
InvalidDefinitionException: Cannot construct instance of
com.vehicle.datatransferobject.VehicleDTO (no Creators, like default
construct, exist): cannot deserialize from Object value (no delegate-
or property-based Creator)
vehicleDTO
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.myvehicle.EngineType;
#JsonInclude(JsonInclude.Include.NON_NULL)
public class VehicleDTO {
#JsonIgnore
private Long id;
#NotNull(message = "vehiclenumber can not be null!")
private String vehiclenumber;
#Min(2)
#NotNull(message = "Seat count can not be less than 2!")
private Integer vehicleseatcount;
#NotNull(message = "Engine Type can not be null!")
private EngineType enginetype;
#Max(5)
private Integer vehiclerating;
private VehicleDTO(Long id, String vehiclenumber, Integer vehicleseatcount, EngineType enginetype,Integer vehiclerating){
this.vehiclenumber=vehiclenumber;
this.vehicleseatcount=vehicleseatcount;
this.enginetype=enginetype;
this.vehiclerating=vehiclerating;
this.id=id;
}
public static VehicleDTOBuilder newBuilder()
{
return new VehicleDTOBuilder();
}
#JsonProperty
public Long getId() {
return id;
}
public String getvehiclenumber() {
return vehiclenumber;
}
public Integer getvehicleseatcount() {
return vehicleseatcount;
}
public EngineType getEnginetype() {
return enginetype;
}
public Integer getvehiclerating() {
return vehiclerating;
}
public static class VehicleDTOBuilder{
private Long id;
private String vehiclenumber;
private Integer vehicleseatcount;
private EngineType enginetype;
private Integer vehiclerating;
public VehicleDTOBuilder setId(Long id) {
this.id = id;
return this;
}
public VehicleDTOBuilder setvehiclenumber(String vehiclenumber) {
this.vehiclenumber = vehiclenumber;
return this;
}
public VehicleDTOBuilder setvehicleseatcount(Integer vehicleseatcount) {
this.vehicleseatcount = vehicleseatcount;
return this;
}
public VehicleDTOBuilder setEnginetype(EngineType enginetype) {
this.enginetype = enginetype;
return this;
}
public VehicleDTOBuilder setvehiclerating(Integer vehiclerating) {
this.vehiclerating = vehiclerating;
return this;
}
public VehicleDTO createVehicleDTO()
{
return new VehicleDTO(id, vehiclenumber, vehicleseatcount, enginetype,vehiclerating);
}
}
}
My DTO has an Enum type called EngineType
public enum EngineType {
ELECTRIC, DIESEL
}
My controller looks like this
#PostMapping
#ResponseStatus(HttpStatus.CREATED)
public VehicleDTO addvehicle(#Valid #RequestBody VehicleDTO vehicleDTO)
{
VehicleDO vehicleDO = Mapper.VehicleDO(vehicleDTO);
return Mapper.makeVehicleDTO(Service.addvehicle(vehicleDO));
}
This exception :
InvalidDefinitionException: Cannot construct instance of
com.vehicle.datatransferobject.VehicleDTO (no Creators, like default
construct, exist): cannot deserialize from Object value (no delegate-
or property-based Creator)
means that Jackson didn't find a way to instantiate VehicleDTO that is the default constructor (no arg constructor) or a JsonCreator.
As you use a builder pattern you will configure the VehicleDTO class to make Jackson to instantiate VehicleDTO with the VehicleDTOBuilder such as :
#JsonDeserialize(builder = VehicleDTO.VehicleDTOBuilder.class)
public class VehicleDTO {
...
}
And annotate your builder with JsonPOJOBuilder as :
#JsonPOJOBuilder(buildMethodName = "createVehicleDTO", withPrefix = "set")
public static class VehicleDTOBuilder{
...
}
According to the javadoc, JsonPOJOBuilder is :
used to configure details of a Builder class: instances of which are
used as Builders for deserialized POJO values, instead of POJOs being
instantiated using constructors or factory methods. Note that this
annotation is NOT used to define what is the Builder class for a POJO:
rather, this is determined by JsonDeserialize.builder() property of
JsonDeserialize.
I faced this error when I used Lombok's #Builder and #Data annotations together on a POJO class that is used for connecting to an API (either for consuming or for providing response)
I removed the #Builder annotation and then it is working fine
In my case:
InvalidDefinitionException: Cannot construct instance of com.vehicle.datatransferobject.VehicleDTO (no Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
for the above exception, I just write Default Constructor which instantiates class and solved the problem.
Default Constructor:
public VehicleDTO() {
super();
// TODO Auto-generated constructor stub
}
If you are using Lombok - the best thing is to add these annotations to your DTO:
#AllArgsConstructor
#RequiredArgsConstructor
#Data
#Builder (optional)
In addition to davidxxx`s answer. I used Lombok. And in my case it looked like this:
#Data
#JsonDeserialize(builder = SomeClass.SomeClassBuilder.class)
#Builder(builderClassName = "SomeClassBuilder")
public class SomeClass {
// ...
#JsonPOJOBuilder(withPrefix = "")
public static class SomeClassBuilder {
}
}
I want to put POJO bean key value pair to Ignite cache using REST API. I can put string key value pair to cache. but here i want to put a class as key value. How can i create REST url for this.
My config file look like this
<property name="cacheConfiguration">
<bean class="org.apache.ignite.configuration.CacheConfiguration">
<!-- Set a cache name. -->
<property name="name" value="cacheName"/>
<!-- Set cache mode. -->
<property name="cacheMode" value="PARTITIONED"/>
<property name="indexedTypes">
<list>
<value>com.test.EntitlementKey</value>
<value>com.test.Entitlement</value>
</list>
</property>
</bean>
</property>
And Entitilement Class look like this
import org.apache.ignite.cache.query.annotations.QuerySqlField;
public class Entitlement {
#QuerySqlField
private String name;
#QuerySqlField
private String desc;
public String getname() {
return name;
}
public void setname(String name) {
this.name = name;
}
public String getdesc() {
return desc;
}
public void setdesc(String desc) {
this.desc = desc;
}
And EntitlementKey class
public class EntitlementKey {
#QuerySqlField(index = true)
private String eid;
#QuerySqlField
private String id;
public String getEid() {
return eid;
}
public void setEid(String eid) {
this.eid = eid;
}
public String getid() {
return id;
}
public void setid(String id) {
this.id = id;
}
Currently, in master, you can find an implementation of ticket, which allows using internal java types as keys and values.
At this moment if you want to use your custom types, you need to use ConnectorMessageInterceptor interface. Once you implement and configure it, you will start receiving a callback for all keys and values passed back and forth. So you can encode your object as a String somehow and then convert it to a real object inside interceptor. And the opposite: before returning object from the cache you can convert it to some String form.
I'm developing a web app using struts 2 framework and i'm facing a problem with select tag in a jsp.
The select tag seems to work fine, but as soon as i press the submit button, my action cannot get the data from the select.
I have looked for problems about select, but all of them seem to be related with the list.
In my case, the list is shown fine. So, I'm quite lost and I dont know what should I do.
Here are my jsp code and my action code. When I press the submit, it suppose that the form will be sent to my action, and I shoud get the data from the form, but when I print the data is always null.
JSP Code:
<s:form action="borrarCita" method="post">
<s:select id="idCita" name="idCita" list="pendings" listKey="idCita" listValue="fecha" label="Elija una cita a anular"></s:select>
<s:submit value="Aceptar"/>
</s:form>
The action code:
public class CitasAction extends ActionSupport implements SessionAware{
private static final long serialVersionUID = 1L;
private Map session = ActionContext.getContext().getSession();
private List pendings= new ArrayList<Cita>();
private String idCita;
private String desplegarCitasPendientes;
private String pedirCita;
private String consultarCitas;
private String citaAnulada;
public String execute(){
return SUCCESS;
}
public String pedirCita(){
setCitaAnulada("");
setDesplegarCitasPendientes("");
setConsultarCitas("");
DbService db = (DbService)session.get("db");
Paciente paciente = (Paciente)session.get("Paciente");
List listaMedicos = db.getListaMedicos();
session.remove("listaCitas");
session.put("listaMedicos", listaMedicos);
setPedirCita("ok");
return SUCCESS;
}
public String desplegarCitasPendientes(){
setCitaAnulada("");
setPedirCita("");
setConsultarCitas("");
Paciente pac = (Paciente)session.get("user");
Iterator<Cita> nombreIterator = pac.getCitas().iterator();
while(nombreIterator.hasNext()){
Cita primera = nombreIterator.next();
if(primera.getStatus().equals("Pending")){
getPendings().add(primera);
}
}
setDesplegarCitasPendientes("ok");
return SUCCESS;
}
public String borrarCita(){
setConsultarCitas("");
setPedirCita("");
setDesplegarCitasPendientes("");
System.out.println(getIdCita());
System.out.println(ActionContext.getContext().getParameters().toString());
Paciente pac = (Paciente)session.get("user");
/*
Iterator<Cita> iterator = pac.getCitas().iterator();
while(iterator.hasNext()){
Cita primera = iterator.next();
if(primera.getFecha().equals(getFecha())){
iterator.remove();
break;
}
}
pac.setCitas(getPendings());
pac.getCitas().remove(getCitaSeleccionada());
session.put("user", pac);
DbService db = (DbService)session.get("db");
db.uploadPaciente(pac);*/
setCitaAnulada("ok");
return SUCCESS;
}
public String consultarCitas(){
setPedirCita("");
setDesplegarCitasPendientes("");
setCitaAnulada("");
setConsultarCitas("ok");
return SUCCESS;
}
public Map getSession() {
return session;
}
public void setSession(Map session) {
this.session = session;
}
public List getPendings() {
return pendings;
}
public void setPendings(List pendings) {
this.pendings = pendings;
}
public static long getSerialversionuid() {
return serialVersionUID;
}
public String getDesplegarCitasPendientes() {
return desplegarCitasPendientes;
}
public void setDesplegarCitasPendientes(String desplegarCitasPendientes) {
this.desplegarCitasPendientes = desplegarCitasPendientes;
}
public String getPedirCita() {
return pedirCita;
}
public void setPedirCita(String pedirCita) {
this.pedirCita = pedirCita;
}
public String getConsultarCitas() {
return consultarCitas;
}
public void setConsultarCitas(String consultarCitas) {
this.consultarCitas = consultarCitas;
}
public String getCitaAnulada() {
return citaAnulada;
}
public void setCitaAnulada(String citaAnulada) {
this.citaAnulada = citaAnulada;
}
public String getIdCita() {
return idCita;
}
public void setIdCita(String idCita) {
this.idCita = idCita;
}
}
So, to sum up, I have that select tag in a jsp and when a press the submit, the action doesn't get any data from the select.
I hope someone can help me with this because it's driving me crazy.
If you need more information, please let me know and I will try to post it as soon as posible.
Thanks in advance.
Edit:
Here is a part of the Cita.class code. Also it has the setters and the getters for every attribute.
public class Cita implements Serializable{
#Id #GeneratedValue
#Column(name="CITA_ID")
private int idCita;
#Column(name="FECHA")
#Temporal(TemporalType.DATE)
private Date fecha;
#Column(name="HORA")
#Temporal(TemporalType.TIME)
private Date hora;
#Column(name="ESTADO")
private String status;
#Column(name="ESPECIALIDAD")
private String especialidad;
#ManyToOne
#JoinColumn(name="MEDICO_ID")
private Medico medico;
#ManyToOne
#JoinColumn(name="PACIENTE_ID")
private Paciente paciente;
And here is the struts.xml:
<interceptors>
<interceptor name="logger" class="interceptor.LoginInterceptor"/>
<interceptor-stack name="myStack">
<interceptor-ref name="logger"/>
</interceptor-stack>
</interceptors>
<action name="desplegarCitasPendientes" class="action.CitasAction" method="desplegarCitasPendientes">
<interceptor-ref name="myStack"/>
<result name="success">/citas.jsp</result>
<result name="login" type="redirect">/index.jsp</result>
<result name="input">/index.jsp</result>
</action>
<action name="borrarCita" class="action.CitasAction" method="borrarCita">
<interceptor-ref name="myStack"/>
<result name="success">/citas.jsp</result>
<result name="login" type="redirect">/index.jsp</result>
<result name="input">/index.jsp</result>
</action>
#Jeroen, sorry for the huge wall of code. It was my first post here.
#Roman, I hope this helps you to help me :-)
Thanks for your replies guys.
Edit 2:
Here is my LoginInterceptor:
public class LoginInterceptor extends AbstractInterceptor {
/**
*
*/
private static final long serialVersionUID = 1L;
#Override
public String intercept(final ActionInvocation invocation) throws Exception {
Map<String, Object> session = invocation.getInvocationContext().getSession();
// sb: if the user is already signed-in, then let the request through.
if (session.get("user") != null) {
return invocation.invoke();
}else{
System.out.println("redirect");
return "login";
}
}
}
If you need something else, let me know :-)
Looks like a Interceptor issue.
What is myStack ?
Here's a sample stack I use in my projects (with Login Interceptor)
<package name="test" extends="struts-default">
<interceptors>
<interceptor name="nlogin" class="interceptors.LoginInterceptor"/>
<interceptor-stack name="loginStack">
<interceptor-ref name="nlogin"/>
<interceptor-ref name="defaultStack"/>
</interceptor-stack>
</interceptors>
<default-interceptor-ref name="loginStack"/>
<action name="test-list" class="actions.InboxAction">
<result>/pages/inbox/list.jsp</result>
</action>
</package>
loginStack is being used as the defaultStack for all actions in that package, because of <default-interceptor-ref name="loginStack"/>
ok guys, It seems that I fixed it. Thanks to the coding_idiot's answer, I was able to figure out what was wrong. It seems that lack of defaultStack in my own stack was the problem. I just added the defaultStack and it looks like working fine now.
So, thank you very much to everyone and specially to coding_idiot.
The code finally looks like:
<interceptors>
<interceptor name="logger" class="interceptor.LoginInterceptor"/>
<interceptor-stack name="myStack">
<interceptor-ref name="logger"/>
<interceptor-ref name="defaultStack"/>
</interceptor-stack>
</interceptors>
I'm working on a RestWebService using Resteasy. The basic implementation works fine. Know I tried to return a Complexer- Object through rest...
Actually its pretty easy..I thought. I'm getting a problem because of my nested object (Address)...
What I try is this:
#XmlRootElement(name = "person")
#XmlAccessorType(XmlAccessType.FIELD)
public class Person implements Serializable {
private static final long serialVersionUID = 1199647317278849602L;
private String uri;
private String vName;
private String nName;
private Address address;
.....
#XmlElementWrapper(name="Former-User-Ids")
#XmlElement(name="Adress")
public Address getAddress() {
return address;
}
....
Address looks like this:
#XmlRootElement(name = "address")
#XmlAccessorType(XmlAccessType.FIELD)
public class Address {
private String uri;
private String street;
private String city;
public String getCity() {
return city;
}
public String getStreet() {
return street;
}
....
The Restservice looks like this. It worked perfect without the address object..
#Path("/getPersonXML/{personNumber}")
#GET
#Produces(MediaType.APPLICATION_XML)
public Patient getPatientXML(#PathParam("personNumber") String personNumber) throws ParseException {
Address a1 = new Address("de.person/address/" + "432432","Teststret12","TestCity", "32433", "TestCountry", "081511833");
Patient p1 = new Person();
p1.setAddress(a1);
p1.setUri("de.spironto/person/"+ "432432");
p1.setnName("Power");
p1.setvName("Max");
return p1;
}
At the moment I'm always getting a
javax.xml.bind.JAXBException:
Any Ideas?
Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group.
PROBLEM
The #XmlElementWrapper annotation must be used with a collection property. This means you can have:
#XmlElementWrapper
public List<PhoneNumber> getPhoneNumbers() {
return phoneNumbers;
}
But not
#XmlElementWrapper
public Address getAddress() {
return address;
}
SOLUTION #1 - Using Any JAXB Proivder
You could use an XmlAdapter to accomplish this (see linked answer below):
Access attribute of internal element in the most simple way
SOLUTION #2 - Using EclipseLink JAXB (MOXy)
You could leverage the #XmlPath extension to map this use case:
#XmlPath("Former-User-Ids/Address")
public Address getAddress() {
return address;
}
For More Information
http://blog.bdoughan.com/2010/07/xpath-based-mapping.html
http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html
After building a small marshaller test. I got the failure that there are several properties with the same name. So I tried to delete all #XML_Eleemets annotations in the Address class.
That worked for me...