Spring boot using Autowire Cofiguration property class in Entity class - spring

I have to use some set data member class in Spring entity class
Current Entity class
Entity(name="users")
public class Users{
#Id
#GeneratedValue
#Column(name=ID")
private long Id;
#Column(name=NAME")
private String name;
#Column(name=AGE")
private String age;
#Column(name=PIN")
private String pin;
public Users(String name, String age, String pin)
{
this.name = name;
this.age = age;
this.pin = pin;
}
}
Now I need to add a new Member which is unique to that place
areaId, we run sperate application per each area so this will be passed from command line arguments or config properties during application starts.
My properties class looks like below
#Component
#ConfigurationProperties("user.info")
public class UserProperties{
public String areaId;
public String getAreaID(){return this.areaId;}
public void setAreaID(String areaId){ this.areaId = areaId;}
}
users:
info:
areaId:124
I have to store this and initializes also during Users object constructing, here I am trying to make simple
Entity(name="users")
public class Users{
#Id
#GeneratedValue
#Column(name=ID")
private long Id;
#Column(name=NAME")
private String name;
#Column(name=AGE")
private String age;
#Column(name=PIN")
private String pin;
#Column(name=AREAID")
private String areaId;
public Users(String name, String age, String pin)
{
this.name = name;
this.age = age;
this.pin = pin;
this.areaId = ""//?? how to get area id directly ?
}
}
I can not change the constructor of Users because it demands changes in the other application which are using this lib
Want to Autowire a users properties class inside Entity class(but this is not suggestable as read in some articles )
What would be the best way to initialize that default kind of variable?

It seems that your property is something static.
Then get it from a static way at start.
There's several ways to get command line value at start directly or in a static block:
static {
(your code here)
}
You'll can put #Column on a getter on this property after that.

Related

CQEngine Query nested object using parser.retrieve

I have a nested object like
public class SQSMessage implements Serializable {
private String type;
private boolean isEntity;
private String eventType;
private SystemInfo systemInfo;
private DomainAttributes domainAttributes;
#Data
public static class SystemInfo implements Serializable {
private String identifier;
private String ownedBy;
private Payload payload;
private EntityTags entityTags;
private long createdOn;
private String createdBy;
private long version;
private long lastUpdatedOn;
private String lastUpdatedBy;
private String attrEncKeyName;
#Data
public static class Payload implements Serializable {
private String bucketName;
private String objName;
private String encKeyName;
private byte[] payloadBytes;
private byte[] decryptedBytes;
private byte[] sanitizedBytes;
}
#Data
public static class EntityTags implements Serializable {
private List<Tag> tags;
#Data
public static class Tag implements Serializable {
private String tagName;
private String tagValue;
}
}
}
#Data
public static class DomainAttributes implements Serializable {
private String updatedByAuthId;
private String saveType;
private String docName;
private String ceDataType;
private String year;
private String appId;
private String formSetId;
private String appSku;
private String deviceId;
private String deviceName;
}
}
I would like to query the collection of SQSObjects by applying a filter like
ResultSet<SQSMessage> results = parser.retrieve(indexedSQSMessage, "SELECT * FROM indexedSQSMessage WHERE type='income' and DomainAttributes.saveType in ('endSession', 'cancelled')or (DomainAttributes.countryCode is null or DomainAttributes.countryCode='US'");
Is that possible using CQEngine? if yes.. please send me the examples.
The reason why I want o make that as sql... where clause is dynamic for various use cases.
Your example is more complicated than it needs to be for the question, so I am just skimming it. (Read about SSCCE)
However generally this kind of thing should be possible. See this related question/answer for how to construct nested queries: Can CQEngine query an object inside another object
If you set up attributes like that, you should be able to use them in SQL queries as well as programmatically.

Reading property values in constructor using prefix

How to use the prefix in the below code?
Properties:
height.customer.feet=10
height.customer.eu.timezone=UTC
#Configuration
#EnableConfigurationProperties
#ConfigurationProperties(prefix = "height.customer")
public class Customer {
private final int age;
private final String timezone;
public Customer(int age, String timezone){
this.age = age;
this.timezone = timezone;
}
}
Here i want to set the default value for both age and timezone. Default values are read from application.properties file. Can someone help me please?
I could use like below.
#Value("${height.customer.age}")
private final int age;
#Value("${height.customer.eu.timezone}")
private final String timezone;
But if i use like this, i may not able to use constructor injection
There is no relationship between the #ConfigurationProperties and #Value annotation. Check here. What you should be using is the #PropertySource annotation. If you use #ConfigurationProperties then you should have hierarchical properties
#Configuration
#ConfigurationProperties(prefix = "height.customer")
public class Customer {
private final int age; // This maps to height.customer.age
private final String timezone; // This does NOT map to height.customer.eu.timezone but maps to height.customer.timezone
public Customer(int age, String timezone){
this.age = age;
this.timezone = timezone;
}
}
Use the #PropertySource with this example
#Configuration
#PropertySource("classpath: demo.properties") // your properties file
public class Customer {
#Value("${height.customer.age}")
private final int age;
#Value("${height.customer.eu.timezone}")
private final String timezone;
public Customer(int age, String timezone){
this.age = age;
this.timezone = timezone;
}
public Customer(){}
}
And there won't be a conflict with the existing constructor because, values injecting via #PropertySource will be default values. If you provide values in the constructor, these will get overridden.

extract less number of columns from database table as defined in #Entity class and map to same entity pojo in spring boot

My #Entity class is
#Entity
class Demo{
#Id
private int id;
private int firstName;
private String lastName;
private String address;
}
And the #Repositiory Interface is having method as below
#Query(value="select d.id,d.firstName from demo d",nativeQuery=true)
List<Demo> fetchDetails();
Here exception is thrown as : The field "lastName" is not present in ResultSet
Do i need to create another pojo that contain id,firstName as variable and change fetchDetails() methods to as below:
#Query(value="select d.id,d.firstName from demo d",nativeQuery=true)
List<New Pojo class with only 2 fields that is to be selected> fetchDetails();
i want the partially selected resultset to get mapped to Entity Demo automatically.
I their any way to map these two columns to the Entity Demo
You can use Class-Based Projections that you can have a lot of constructor you need according to all fields you want to fetch
For example, here's a projection class for the Demo entity:
public class DemoDto {
private int id;
private int firstName;
private String lastName;
private String address;
// getters, equals and hashCode
}
public DemoDto(String firstName) {
this.firstName = firstName;
}
public DemoDto(int id, String firstName) {
this.id = id;
this.firstName = firstName;
}
public DemoDto(int id, String firstName, String address) {
this.id = id;
this.firstName = firstName;
this.address = address;
}
You must also define equals and hashCode implementations – they allow Spring Data to process projection objects in a collection.
In your repository you can add some query with JPQL Constructor like:
#Query(value="select new your.class.fullname.package.DemoDto(d.firstName) from Demo d")
List<DemoDto> fetchNameOnly();
#Query(value="select new your.class.fullname.package.DemoDto(d.id, d.firstName) from Demo d")
List<DemoDto> fetchIdAndNameOnly();
#Query(value="select new your.class.fullname.package.DemoDto(d.id, d.firstName, d.address) from Demo d")
List<DemoDto> fetchAllDetails();
Projections are introduced for that exact reason. Have a look at the documentation here
What you need is this, create an interface like this with the getter method for the fields you want in the result.
interface IdAndNameOnly {
String getFirstname();
int getId();
}
Modify the query like this. You do not need #Query for simple queries like the one you have.
List<IdAndNameOnly> findAll();
You can convert object of type IdAndNameOnly to your Entity type. But that doesn't make much sense. You can just get the fields which you need from the IdAndNameOnly object. If not what is the point of fetching fewer fields.
If I'm not mistaken you need to create a custom constructor and use it JPQL Constructor Expressions.
Something like this would do the job:
#Entity
class Demo{
#Id
private int id;
private int firstName;
private String lastName;
private String address;
public Demo() {
// JPA needs the default constructor
}
public Demo(int id, String firstName) {
this.id = id;
this.firstName = firstName;
}
}
And the usage something like this:
#Query(value="select new your.class.fullname.package.Demo(d.id,d.firstName) from Demo d")
List<Demo> fetchDetails();

SpringBoot concatenate search parameters browser url

I am starting working with Spring Boot. My aim is to make a limited search retrieving data from a database. I want to add multiple parameters in the query of the url.
So far I was able using the seek: http://localhost:8080/wsr/search/, to get a full search of the data in the database. But what I want is delimit the search under several conditions adding parameters in the url in the browser as for instance:
http://localhost:8080/data/search/person?name=Will&address=Highstreet&country=UK
http://localhost:8080/data/search/person?name=Will&name=Angie
http://localhost:8080/data/search/person?name=Will&name=Angie&country=UK
The problem I found is that I can't find the way to work with more than one condition. The only thing I got to make it work, is:
http://localhost:8080/data/search/person?name=Will
I surfed the web but no results for this exact problem, too much information but impossible to find this.
The code I have is:
#Entity
#Table(name = "person")
public class Person {
#Id
#GeneratedValue
#Column(name = "id")
private int id;
#Column(name = "name")
private String name;
#Column(name = "address")
private String address;
#Column(name = "country")
private String country;
public Value() {
}
public Value(int id, String name, String address, String country) {
this.id = id;
this.name = name;
this.address = address;
this.country = country;
}
//all getters and setters
}
public class Implementation {
#Autowired
private DataBase dataBase;
public List<Value> findById(#PathVariable final int id) {
return dataBase.findById(id);
}
public List<Value> findByName(#PathVariable final String name) {
return dataBase.findByName(name);
}
public List<Value> findByAddress(#PathVariable final String address) {
return dataBase.findByAddress(address);
}
public List<Value> findByCountry(#PathVariable final String country) {
return dataBase.findByCountry(country);
}
}
//#Component
#RepositoryRestResource(collectionResourceRel = "person", path = "data")
public interface DataBase extends JpaRepository<Value, Integer>{
public List<Value> findAll();
#RestResource(path = "ids", rel = "findById")
public List<Value> findById(#Param("id") int id) throws ServiceException;
#RestResource(path = "name", rel = "findByName")
public List<Value> findByName(#Param("name") String name) throws ServiceException;
#RestResource(path = "address", rel = "findByAddress")
public List<Value> findByAddress(#Param("address") String address) throws ServiceException;
#RestResource(path = "country", rel = "findByCountry")
public List<Value> findByCountry(#Param("country") String country) throws ServiceException;
}
Hope you can help me putting me in the correct way of what should do or is wrong. If possible some code will also be highly appreciated.
Best regards
You can use #RequestParam("nameParameter")annotation to map all the parameters you want. Let's say you have url like :
http://localhost:8080/data/search/person?name=Will&country=UK
then you can have an api like:
...
#RequestMapping(value = "/person")
public String api(#RequestParam("name") String name, #RequestParam("country") String country)
...

want to autowire DAO class in my entity class

i have a method which i need to call in my entity class company.java.
but when i run my application it throws null pointer exception didn't fount that DAO object in entity class..
How can i get that object in entity class please help
This is my entity class..
package com.salebuild.model;
/**
* Define a company.
*
* #author mseritan
*/
#Entity
#Table(name = "company", uniqueConstraints = {#UniqueConstraint(columnNames = "name")})
#XmlRootElement
#XmlSeeAlso(value = ArrayList.class)
public class Company implements PublishableIF, Serializable, PersistableIF, HistoryIF, AddressableIF {
private static final Logger log = LoggerFactory.getLogger( Company.class );
#Autowired
private CompanyDAO companyDAO;
// CONSTANTS -----------------------------------------------------------------------------------
private static final long serialVersionUID = 1L;
// ATTRIBUTES ----------------------------------------------------------------------------------
private Long id;
#NotBlank
private String name;
private String formerName;
private CorporateTitle topLevelExec;
private List<CompanySite> sites;
private List<CompanyAlias> aliases;
#NotNull
private Industry industry;
private Company parentCompany;
private String emailTopology;
#NotNull
private Double revenue;
#NotNull
private Long numberEmployees;
private CustomerType.Type customerType;
private Boolean recruiter = false;
private int publishState;
private CompanyStatus status;
private Boolean excludeCompany = false;
private CompanyType companyType;
private String salesifyCompanyId;
private CompanySiteType companySiteType;
private String websiteUrl;
private String sourceVendor;
private String notes;
private List<CompanySpecializedRanking> specializedList = new ArrayList<CompanySpecializedRanking>();
#NotNull
private NAICSCode naicsCode;
#NotNull
private SICCode sicCode;
private Long version;
private List<Technology> technologies = new ArrayList<Technology>();
private List<CompanyContact> contacts;
private String phoneNumber;
private String faxNumber;
private String email;
private User userCreated;
private Date dateCreated;
private User userLastModified;
private Date dateLastModified;
private User userLastResearcher;
private Date dateLastResearcher;
#NotBlank
private String street1;
private String street2;
private String street3;
private String city;
private String zipCode;
private State state;
private Country country;
private String specRankingListName;
private Integer specRankingRank;
private Integer specRankingYear;
private String modifiedCompanyName;
private String formattedRevenue;
private String formattedEmployeeSize;
private List<JobPostingRaw> unconfirmedTechnologies;
// ACESSORS ------------------------------------------------------------------------------------
//getter setter for other fields //
this.specRankingYear = specRankingYear;
}
/**
* #param modifiedCompanyName
*
*/
#Column(name="modifiedCompanyName")
public String getModifiedCompanyName() {
return modifiedCompanyName;
}
public void setModifiedCompanyName(String modifiedCompanyName) {
if(modifiedCompanyName==null)
this.modifiedCompanyName=modifiedCompanyName;
else{
this.modifiedCompanyName =companyDAO.updateCompanyName(modifiedCompanyName);
}
}
#Transient
public List<JobPostingRaw> getUnconfirmedTechnologies() {
return unconfirmedTechnologies;
}
public void setUnconfirmedTechnologies(
List<JobPostingRaw> unconfirmedTechnologies) {
this.unconfirmedTechnologies = unconfirmedTechnologies;
}
}
my DAO class is like that --
package com.salebuild.dao;
import com.salebuild.model.Company;
import com.salebuild.model.search.EntitySearchCriteria;
import com.salebuild.model.search.SortedResultsPage;
import java.util.Collection;
import java.util.List;
import java.util.Set;
public interface CompanyDAO extends CrudDAO<Company> {
Company findByNameOrAlias(String name);
List<Company> findBySearchTerm(String searchTerm, Integer start, Integer count);
// SortedResultsPage<Company> findPaged(EntitySearchCriteria criteria);
List<Long> findIds(EntitySearchCriteria criteria);
List<Company> find(Collection<Long> ids);
/**
* For just finding the company name and not looking for alias names.
*
* #param name
* #return
*/
public Company findByName( String name );
public Company findByModifiedName(String name,Company... c);
public int companyCountSinceLastLogin(Long id);
Set<Long> findDistinctIds(EntitySearchCriteria criteria);
public Integer getCompanyCountByRegion(Long regionId,List techCatIds);
List<Company> findAllCompanies(Company instance);
public List<Company> findAllModifiedCompanies(Company instance);
public String updateCompanyName(String name);
}
The easiest option is to implement factory for building entities. Then you can use AutowireCapableBeanFactory to autowire dependencies:
public abstract class GenericFactory<T> {
#Autowired
private AutowireCapableBeanFactory autowireBeanFactory;
public T createBean() {
// creation logic
autowireBeanFactory.autowireBean(createdBean);
return createdBean;
}
}
Of course you can pass object (created or retrieved) and just autowire it.
Another option is to use #Configurable - it automatically injects dependencies. http://docs.spring.io/spring/docs/3.0.x/spring-framework-reference/html/aop.html#aop-atconfigurable
You can find more details in my post: http://www.kubrynski.com/2013/09/injecting-spring-dependencies-into-non.html
JPA entities are meant to be POJOs i.e. simple Java beans which do not have dependencies and have getters and setters which contain no complex logic.
It would be better to create a service which is responsible for saving and updating your entity which is used throughout your code. This service can then be responsible for executing the logic you wish to put in your setter using dependencies which can be autowired.
The issue you have is that you Spring is not responsible for the creation of your entity. You either instantiate it using new or you obtain it from your JPA implementation. Either way there is no opportunity for Spring to autowire declared dependencies.
As an aside it's not good practice to autowire private variables. See this blog post for a fuller discussion.

Resources