I am trying to declare a component with a parametrized constructor but it is throwing me an error. Is there any way to resolve this situation?
I can have a default constructor to avoid the situation. But, my Business requirement says only to have parametrized constructor. Is there any work around?
#Component
public class Employee {
private String firstName;
private String lastName;
private int yearsOfExperience;
private String designation;
#Autowired
public Employee(**String** firstName, **String** lastName, **int** yearsOfExperience, **String** designation) {
this.firstName = firstName;
this.lastName = lastName;
this.yearsOfExperience = yearsOfExperience;
this.designation = designation;
}
Error: Could not Autowire. No Beans of String is found. The bold text is an error out with a shared message.
Related
I am using Spring to develop new REST API, I have BaseResponse class which acts as base responses for all response. this class contains attribute String requestUuid; at some cases this requestUuid must be serialized with attribute name requestUuid , on other cases it must be seriliazed as request_uuid, i know i can use #JsonProperty as a field level annotation, but it will affect all responses. is there is any way to override attribute name specifically for each one of the derived classes.
You can use the #JsonProperty on the method level instead. That way, you can override the field's getter method in the subclass and annotate that.
For example:
class BaseResponse {
private String requestUuid;
public getRequestUuid() {
return requestUuid;
}
}
class OtherResponse extends BaseResponse {
#Override
#JsonProperty("request_uuid")
public getRequestUuid() {
return super.getRequestUuid();
}
}
You can send the field twice with different key names.
#JsonAnyGetter
public Map<String, Object> otherFields() {
Map<String, Object> otherFields = new HashMap<>();
otherFields.put("requestUuid", this.requestUuid);
otherFields.put("request_uuid", this.requestUuid);
return otherFields;
}
Also, ignore your actual field:
#JsonIgnore
private String requestUuid;
Expanding on #JoshA response, another alternative is to define a constructor and annotate it. This leads to a more concise code by avoiding the need to override the getter methods in derived classes.
class BaseResponse {
private String firstName;
private String lastName;
public BaseResponse(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public getFirstName() {
return firstName;
}
public getLastName() {
return lastName;
}
}
class OtherResponse extends BaseResponse {
public OtherResponse(#JsonProperty("given_name") String firstName, #JsonProperty("family_name") String lastName) {
super(firstName, lastName);
}
}
NO, its not possible, what is possible you can make new class for different type of requests.
An external service is providing a JSON array with plain/primitive elements (so without field names, and without nested JSON objects). For example:
["Foo", "Bar", 30]
I would like to convert this to an instance of the following Java class using Jackson:
class Person {
private String firstName;
private String lastName;
private int age;
Person(String firstName, String lastName, int age) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
}
}
(This class can be adapted if needed.)
Question: is it possible to deserialize this JSON to Java using something like this?
Person p = new ObjectMapper().readValue(json, Person.class);
Or is this only possible by writing a custom Jackson deserializer for this Person class?
I did try the following, but that didn't work:
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
public class Person {
private String firstName;
private String lastName;
private int age;
#JsonCreator
public Person(
#JsonProperty(index = 0) String firstName,
#JsonProperty(index = 1) String lastName,
#JsonProperty(index = 2) int age) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
}
public static void main(String[] args) throws IOException {
String json = "[\"Foo\", \"Bar\", 30]";
Person person = new ObjectMapper().readValue(json, Person.class);
System.out.println(person);
}
}
Result: Exception in thread "main" com.fasterxml.jackson.databind.JsonMappingException: Argument #0 of constructor [constructor for Person, annotations: {interface com.fasterxml.jackson.annotation.JsonCreator=#com.fasterxml.jackson.annotation.JsonCreator(mode=DEFAULT)}] has no property name annotation; must have name when multiple-parameter constructor annotated as Creator
at [Source: (String)"["Foo", "Bar", 30]"; line: 1, column: 1]
You don't need #JsonCreator, just use #JsonFormat(shape = JsonFormat.Shape.ARRAY)
#JsonFormat(shape = JsonFormat.Shape.ARRAY)
public static class Person {
#JsonProperty
private String firstName;
#JsonProperty
private String lastName;
#JsonProperty
private int age;
}
And use #JsonPropertyOrder({"firstName", "lastName", "age" } ) if you need to preserve some alternative field declaration order in your bean.
I am new to spring boot. I want to achieve relaxed binding in spring boot. As per this documentation https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html#boot-features-external-config-relaxed-binding.
It says, even though if we have name with dashes(like first-name) in .properties file, it can be mapped to variable without dashes(like firstName). But it didn't seems to be working.
I have application.properties file like below:
person.first-name=orcl
person.address=xyz
And my Properties util java file looks like:
#ConfigurationProperties(prefix="person")
#Component
#PropertySource("file: application.properties")
public class ApplicationPropertiesUtil
{
private String firstName;
private String address;
public String getfirstName()
{
return firstName;
}
public void setfirstName(String firstName)
{
this.firstName = firstName;
}
public String getaddress()
{
return address;
}
public void setaddress(String address)
{
this.address = address;
}
}
address property is getting bind properly, but for firstname it is null.
The problem is your setter methods which don't align with java bean standard.
It should be named "setFirstName" with an upper case F.
I am trying to learn how to implement a CRUD ReST API. I created a simple application using JAX-RS and am testing my HTTP methods using Postman. My question is, how do I define optional fields for a model for POST method?
ex. Person contains firstName, lastName as required fields, and age, gender as optional fields.
#XmlRootElement
public class Person {
private long id;
private String firstName;
private String lastName;
public Person() {}
public Person(long id, String firstName, String lastName) {
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
}
//getter and setters omitted
Above is a sub-resource to another resource, and below addPerson service method is used to POST to a HashMap.
public Person addPerson(long userId, Person person) {
Map<Long, Person> persons = users.get(userId).getPersons();
person.setId(persons.size() + 1);
persons.put(person.getId(), person);
return person;
}
I thought of constructing a model whose constructor has multiple different combination of parameters to instantiate a model class, but that doesn't seem very efficient. Can somebody advise?
FURTHER EDIT: This needs to be done while processing JSON. Given two JSON formatted request:
{
"firstName": "Jay",
"lastName": "Kay",
"age": "13"
}
and
{
"firstName": "Jay",
"lastName": "Kay"
}
both should be processable since age(as well as gender) is an "optional attributes" so it may be either omitted, or have a value. I'm coming across JSON parsers and trying to read through them since that may be an answer to processing such requests.
Add gender and age to your Person class
#XmlRootElement
public class Person {
private long id;
private String firstName;
private String lastName;
private int age;
private String gender;
public Person() {}
public Person(long id, String firstName, String lastName) {
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
}
}
While making request from Postman, include the age and gender as keys in x-www-form-urlencoded.
By default, the value of integer is 0 and value for String is empty string.
In your method to handle the request, check the values for gender and age.
If the values are provided in the request, then use the setters of Person class to set the values accordingly.
Suppose the following is your method to handle the request :
#POST
#Path("/AddPerson")
#Produces(MediaType.TEXT_PLAIN)
public String addPerson(#FormParam("id") long id,
#FormParam("firstName") String firstName,
#FormParam("lastName") String lastName,
#FormParam("age") int age,
#FormParam("gender") String gender) {
Person person = new Person(id,firstName,lastName);
if(age != 0) {
person.setAge(age);
}
if(!gender.equals("")) {
person.setGender(gender)
}
// Assuming that PersonService class has the addPerson method
PersonService.addPerson(1,person)
return "Person with id "+ id + " added";
}
Using Spring data I would like to be able to define a custom get-method inside a domain model class without affecting the model itself. For example, using this model:
#Document
public class Person
{
private String firstName;
private String lastName;
public String getFirstName()
{
return firstName;
}
public void setFirstName(String firstName)
{
this.firstName = firstName;
}
public String getLastName()
{
return lastName;
}
public void setLastName(String lastName)
{
this.lastName = lastName;
}
}
Eveything is working fine so far: the model Person has the fields 'firstName' and 'lastName' and I can successfully save a 'person'. The resulting JSON has the fields 'firstName' and 'lastName'. Now I would like to add some additional data in the JSON without affecting the model and its save-operations, something like this:
#Document
public class Person
{
private String firstName;
private String lastName;
public String getFirstName()
{
return firstName;
}
public void setFirstName(String firstName)
{
this.firstName = firstName;
}
public String getLastName()
{
return lastName;
}
public void setLastName(String lastName)
{
this.lastName = lastName;
}
// custom method
public String getFullName()
{
return firstName+" "+lastName;
}
}
The JSON should contain the same data as before, but this time also an additional 'fullName'-field. However, at the same time the data model assumes an additional field 'fullName' is added and filled with null-values when saving into the database.
I have already tried annotations like #Transient, but this does not work. The documentation states "by default all private fields are mapped to the document, this annotation excludes the field where it is applied from being stored in the database", so it only can be applied to private fields in the class, not to get-methods.
What is the correct way to do this in Spring? Of course I can extend the class Person and include the getFullName-method there, but I was wondering if it is possible to include everything in one class.
Edit:
I use Elasticsearch as DB engine using spring-data-elasticsearch 1.2.0.RELEASE. I have just tested MongoDB as alternative and then it is working fine, even without the #Transient annotation. I think the index-method of the ElasticsearchRepository is serializing the provided class instance when saving it to the database. In that way the JSON-output and the saved data are always identical. Any suggestions?