#Indexed annotation is ignored - spring-data-solr

I have a simple Product class as it follows
#SolrDocument(collection = "product")
public class Product {
#Id
#Indexed(name = "id", type = "string")
private String id;
#Field
#Indexed(name = "namex", type = "text_general", stored = false, searchable=true)
private String name;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
my problem is that the annotation #Indexed is completely ignored. The name of the field is simply name (instead of namex) and the field is stored. Any guess?
UPDATE 1 if I remove the type annotation name works, but stored has no effect still

I managed by modifying the bean that creates the SolrTemplate object like follows:
#Bean
public SolrTemplate solrTemplate(SolrClient client) throws Exception {
SolrTemplate st = new SolrTemplate(client);
st.setSchemaCreationFeatures(Collections.singletonList(Feature.CREATE_MISSING_FIELDS));
st.afterPropertiesSet();
return st;
}

Related

Resteasy - Multiple resource methods match request "POST /.../..."

I am doing a REST API with Java Resteasy framework (using Jackson as well).
I was trying to define 2 api endpoints almost equal:
#POST
#Path("/addbook")
#Produces(MediaType.APPLICATION_XML)
#Consumes(MediaType.APPLICATION_XML)
public BookAdvanced addBook (BookAdvanced book){...}
#POST
#Path("/addbook")
#Produces(MediaType.APPLICATION_XML)
#Consumes(MediaType.APPLICATION_XML)
public Book addBook (Book book){...}
Is this possible? What I want is, depending on the xml arriving execute one or the other method
Here book class:
package package1;
import javax.xml.bind.annotation.*;
import java.util.Date;
#XmlRootElement(name = "book")
public class Book {
private Long id;
private String name;
private String author;
#XmlAttribute
public void setId(Long id) {
this.id = id;
}
#XmlElement(name = "title")
public void setName(String name) {
this.name = name;
}
#XmlElement(name = "author")
public void setAuthor(String author) {
this.author = author;
}
public Long getId() {
return id;
}
public String getName() {
return name;
}
public String getAuthor() {
return author;
}
// constructor, getters and setters
}
Here BookAdvanced class:
package package1;
import javax.xml.bind.annotation.*;
import java.util.Date;
#XmlRootElement(name = "book")
public class BookAdvanced {
private Long id;
private String name;
private String author;
private int year;
#XmlAttribute
public void setId(Long id) {
this.id = id;
}
#XmlElement(name = "title")
public void setName(String name) {
this.name = name;
}
#XmlElement(name = "author")
public void setAuthor(String author) {
this.author = author;
}
#XmlElement(name = "year")
public void setYear(int year) {
this.year = year;
}
public Long getId() {
return id;
}
public String getName() {
return name;
}
public String getAuthor() {
return author;
}
public int getYear() {
return year;
}
// constructor, getters and setters
}
27-Jan-2023 12:33:18.238 WARN [http-nio-8080-exec-39] org.jboss.resteasy.core.registry.SegmentNode.match RESTEASY002142: Multiple resource methods match request "POST /hello/addbook". Selecting one. Matching methods: [public package1.BookAdvanced prova_gradle_war.HelloWorldResource.addBook(package1.BookAdvanced), public package1.Book prova_gradle_war.HelloWorldResource.addBook(package1.Book)]
Matching is based on the request URI and not the request body. There is no real way to match the path and decide the method to use based on the body.
You could do something manually where you inspect the data and determine which type to create.

AutoMapper assign property from parent type property

is there i way in autoMapper to assign child class property from parent class property. I have looked at other example out there but didn't quite get what I need so posting my issue here.
here's code
class ParentDB {
public int id;
public DateTime CreatedDate;
public string Name;
}
class ChildDB {
public int id;
publi string Name;
public int Number;
}
class ParentViewModel : IMapFrom <ParentDB> {
pulic int id;
pulic string Name;
public ChildViewModel child;
}
class ChildViewModel : IMapFrom <ChildDB> {
public int Id;
pulic string Name;
pulic DateTime ParentCreated;
}
public interface IMapFrom<T>
{
void Mapping(Profile profile) => profile.CreateMap(typeof(T), GetType());
}
Problem is that "ParentCreated" time in ChildViewMode needs to come from ParentDB. I have tried following with no success
class ParentViewModel : IMapFrom <ParentDB> {
pulic int id;
pulic string Name;
public ChildViewModel child;
public DateTime CreatedDate;
public void Mapping(Profile profile)
{
profile.CreateMap<ParentDB, ParentViewModel>()
.AfterMap( (s,d) => d.ChildViewModel.ParentCreated = d.CreatedDate);
}
}
var children = await Context.ParentDB
.ProjectTo<ParentViewModel>(mapper.ConfigurationProvider)
.ToListAsync()
with above although ParentViewModel.CreatedDate has date, ChildViewModel.ParentCreated is null. can some please explain why its not assigning date in AfterMap and hwo can this be fix.
Thanks
I am not how to do the map in the way you shared, since I can't see the IMapFrom <T> interface.
Maybe you can try below:
var parent = new ParentDB { id = 1, Name = "AA", CreatedDate = DateTime.Now.AddDays(1) };
var configuration = new MapperConfiguration(cfg => {
cfg.CreateMap<ParentDB, ParentViewModel>()
.AfterMap((s, d) => d.ChildViewModel.ParentCreated = s.CreatedDate);
});
var mapper = configuration.CreateMapper();
ParentViewModel parentViewModel = mapper.Map<ParentViewModel>(parent);
Also you should initlize the ChildVewModel in the ParentViewModel, otherwise it will occur a NullReference exception
public class ParentViewModel
{
public ParentViewModel()
{
ChildViewModel = new ChildViewModel();
}
public int id;
public string Name;
public ChildViewModel ChildViewModel;
}
Result:

Jackson annotation #JsonUnwrapped ignores #JsonProperty value

Here's very simple scenario in which I got value object that I want to un-wrap for serialization. Using custom Serializer is not an option.
public class UnwrappedWithPropertyName {
public static void main(String[] args) throws JsonProcessingException {
final Address address = new Address(new Postcode("45678"));
final ObjectMapper mapper = new ObjectMapper();
System.out.println(mapper.writeValueAsString(address));
}
static class Address {
#JsonUnwrapped
#JsonProperty("postcode")
private final Postcode postcode;
Address(Postcode postcode) {
this.postcode = postcode;
}
public Postcode getPostcode() {
return postcode;
}
}
static class Postcode {
private final String value;
Postcode(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
}
That will result in {"value":"45678"} and what I would expect is {"postcode":"45678"}
By annotating field with #JsonValue one can control the name of such field from enclosing class.
static class Address {
#JsonProperty("postcode")
private final Postcode postcode;
Address(Postcode postcode) {
this.postcode = postcode;
}
public Postcode getPostcode() {
return postcode;
}
}
static class Postcode {
#JsonValue
private final String value;
Postcode(String value) {
this.value = value;
}
}
Move #JsonProperty("postcode") to private final String value;

Room Android : Entities and Pojos must have a usable public constructor

Entities and Pojos must have a usable public constructor. You can have an empty constructor or a constructor whose parameters match the fields (by name and type)
Am integrating room into my existing project. While annotating a POJO, which implements Parcelable, with #Entity tag and making necessary changes, am getting this error. I already have an empty constructor in it. Any help would be appreciated.
#Entity(tableName = "Departments")
public class Department implements Parcelable {
#PrimaryKey(autoGenerate = true)
private Integer primaryId;
private Integer id;
private String departmentName;
private String logoUrl;
#Embedded
private ArrayList<Template> templateList;
public Department() {
}
protected Department(Parcel in) {
this.primaryId = (Integer) in.readSerializable();
this.departmentName = in.readString();
this.logoUrl = in.readString();
this.id = (Integer) in.readSerializable();
this.templateList = in.createTypedArrayList(Template.CREATOR);
}
public static final Creator<Department> CREATOR = new Creator<Department>() {
#Override
public Department createFromParcel(Parcel in) {
return new Department(in);
}
#Override
public Department[] newArray(int size) {
return new Department[size];
}
};
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeSerializable(primaryId);
dest.writeString(departmentName);
dest.writeString(logoUrl);
dest.writeSerializable(id);
dest.writeTypedList(templateList);
}
public Integer getPrimaryId() {
return primaryId;
}
public void setPrimaryId(Integer primaryId) {
this.primaryId = primaryId;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getLogoUrl() {
return logoUrl;
}
public void setLogoUrl(String logoUrl) {
this.logoUrl = logoUrl;
}
public String getDepartmentName() {
return departmentName;
}
public void setDepartmentName(String departmentName) {
this.departmentName = departmentName;
}
public ArrayList<Template> getTemplateList() {
return templateList;
}
public void setTemplateList(ArrayList<Template> templateList) {
this.templateList = templateList;
}
}
#Entity(tableName = "Templates")
public class Template implements Parcelable {
#PrimaryKey(autoGenerate = true)
private Integer primaryId;
private Integer id;
private String code;
private String description;
private Integer departmentId;
#Embedded
private ArrayList<Issue> issueList;
public Template() {
}
private Template(Parcel in) {
this.primaryId = (Integer) in.readSerializable();
this.code = in.readString();
this.description = in.readString();
this.id = (Integer) in.readSerializable();
this.departmentId = (Integer) in.readSerializable();
this.issueList = in.createTypedArrayList(Issue.CREATOR);
}
public static final Creator<Template> CREATOR = new Creator<Template>() {
#Override
public Template createFromParcel(Parcel in) {
return new Template(in);
}
#Override
public Template[] newArray(int size) {
return new Template[size];
}
};
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeSerializable(primaryId);
dest.writeString(code);
dest.writeString(description);
dest.writeSerializable(id);
dest.writeSerializable(departmentId);
dest.writeTypedList(issueList);
}
public Integer getPrimaryId() {
return primaryId;
}
public void setPrimaryId(Integer primaryId) {
this.primaryId = primaryId;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public ArrayList<Issue> getIssueList() {
return issueList;
}
public void setIssueList(ArrayList<Issue> issueList) {
this.issueList = issueList;
}
public Integer getDepartmentId() {
return departmentId;
}
public void setDepartmentId(Integer departmentId) {
this.departmentId = departmentId;
}
}
#Entity(tableName = "Issues")
public class Issue implements Parcelable {
#PrimaryKey(autoGenerate = true)
private Integer primaryId;
private Integer id;
private String code;
private String description;
private Integer parentIssue;
public Issue() {
}
protected Issue(Parcel in) {
this.primaryId = (Integer) in.readSerializable();
this.code = in.readString();
this.description = in.readString();
this.id = (Integer) in.readSerializable();
this.parentIssue = (Integer) in.readSerializable();
}
public static final Creator<Issue> CREATOR = new Creator<Issue>() {
#Override
public Issue createFromParcel(Parcel in) {
return new Issue(in);
}
#Override
public Issue[] newArray(int size) {
return new Issue[size];
}
};
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeSerializable(primaryId);
dest.writeString(code);
dest.writeString(description);
dest.writeSerializable(id);
dest.writeSerializable(parentIssue);
}
public Integer getPrimaryId() {
return primaryId;
}
public void setPrimaryId(Integer primaryId) {
this.primaryId = primaryId;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Integer getParentIssue() {
return parentIssue;
}
public void setParentIssue(Integer parentIssue) {
this.parentIssue = parentIssue;
}
}
Room assumes your entity class will be having only one constructor. But there is no such limitations, If you have multiple constructor then annotate one of them with
#Ignore
Room will ignore this constructor and compile without any error.
Example
#Entity(tableName = "Departments")
public class Department implements Parcelable {
#PrimaryKey(autoGenerate = true)
private Integer primaryId;
private Integer id;
private String departmentName;
private String logoUrl;
#Embedded
private ArrayList<Template> templateList;
/**Room will ignore this constructor
**/
#Ignore
public Department() {
}
protected Department(Parcel in) {
this.primaryId = (Integer) in.readSerializable();
this.departmentName = in.readString();
this.logoUrl = in.readString();
this.id = (Integer) in.readSerializable();
this.templateList = in.createTypedArrayList(Template.CREATOR);
}
}
I'm not sure why you are getting your specific constructor error. That said your code will error from embedding the ArrayList. #Embedded is not meant to be used this way. #Embedded allows you to flatten your POJO structure when storing it. Nested POJO properties will appear as if they had been properties on the parent POJO. Using Embedded on a List is the same as asking it to flatten the properties of the ArrayList object and store them, not flatten the list items and store them.
The appropriate measure is to transition into a foreign key, primary key relationship. An alternative solution is to create a new POJO that contains your list of items (ie Templates, with an 's'). This would contain an ArrayList of Template objects. You would then define a converter that converts the POJO to a json/comma seperated list, and stores it in a single column that by default would be called "templates". Here is a link to this approach :
Android room persistent library - TypeConverter error of error: Cannot figure out how to save field to database"
Hope this helps.

Hibernate : #OneToMany : Always deleting and reinserting the child records

Please help me resolve this issue. I tried googling for a solution and couldn't find one for this.
Table structure
Table: Catalog
catalog_id (primary key)
name
Table: Catalog_Locale
catalog_id
locale_id
sequence
composite key(catalog_id,locale_id)
Class
public Class Catalog{
#Id
#Column(name = "CATALOG_ID", nullable = false)
private String catalogId;
#Column(name = "NAME")
private String name;
#OneToMany(targetEntity = CatalogLocale.class,fetch=FetchType.LAZY)
#JoinColumn(name = "CHILD_CATALOG_ID", nullable = false)
#Cascade(value = {})
protected List<CatalogLocale> locales = new ArrayList<CatalogLocale>(10);
public void setCatalogId( String catalogId ){
this.catalogId = catalogId;
}
public void setName( String name ){
this.name = name;
}
public void setLocales( List<CatalogLocale> locales ){
this.locales = locales;
}
public void getCatalogId(){
return catalogId;
}
public void getName(){
return name;
}
public void getLocales(){
return locales;
}
}
public class CatalogLocale{
#EmbeddedId
CatalogLocalePk catalogLocalePk;
#Column(name = "SEQUENCE")
private int sequence;
public void setCatalogLocalePk( CatalogLocalePk catalogLocalePk ){
this.catalogLocalePk = catalogLocalePk;
}
public void setSequence( int sequence ){
this.sequence = sequence;
}
public CatalogLocalePk getCatalogLocalePk(){
return catalogLocalePk;
}
public int getSequence(){
return sequence;
}
#Embeddable
public static class CatalogLocalePk{
#Column(name = "CATALOG_ID", nullable = false)
private String catalogId;
#Column(name = "LOCALE_ID", nullable = false)
private String localeId;
public CatalogLocalePk(){
}
public CatalogLocalePk( String catalogId, String localeId ){
this.catalogId = catalogId;
this.localeId = localeId;
}
public void setCatalogId( String catalogId ){
this.catalogId = catalogId;
}
public void setLocaleId( String localeId ){
this.localeId = localeId;
}
public String getCatalogId(){
return catalogId;
}
public String getLocaleId(){
return localeId;
}
}
}
The code works for fine for the insert operation, but for any update to the Catalog will trigger for delete and reinsert all entries of the child table.
Is there any solution for this?