Swaraj
Swaraj

Reputation: 353

Spring Rest `@Controller` wiered behaviour

I am trying hands on Spring Rest service via @Controller. But i came across situation where one method call is responding with valid data and other filtered method call returning incorrect response. Here is my controller

@Controller 
@RequestMapping("/company")
public class CompanyDetailsController {

@Autowired
private CompanyServices companyServices;

@RequestMapping(method = RequestMethod.GET)
public @ResponseBody List<CompanyDetails> getCompanyDetails() {
    return companyServices.getCompanyDetails();
}

@RequestMapping(value = "/{companyShortCode}", method = RequestMethod.GET)
public @ResponseBody CompanyDetails getCompanyDetails(@PathVariable("companyShortCode") String companyShortCode) {
    System.out.println("companyShortCode = "+companyShortCode);
    CompanyDetails companyDetails = companyServices.getCompanyDetails(companyShortCode);
    /*CompanyDetails companyDetails = new CompanyDetails();
    companyDetails.setCompanyCode("abc");
    companyDetails.setCompanyEmail("[email protected]");
    companyDetails.setCompanyPhone(92349234);
    companyDetails.setWebSite("abc.abc.com");
    System.out.println("companyDetails = "+companyDetails);*/
    return companyDetails;
}
}

CompanyDetails

@Entity
@Table(name = "company_details")
@JsonIgnoreProperties({ "hibernateLazyInitializer", "handler" })
public class CompanyDetails implements Serializable {

private static final long serialVersionUID = 8713608417980657723L;

@Id
@Column(name="COMPANY_CODE", nullable = false, updatable = false)
private String companyCode = null;

@Column(name = "COMPANY_NAME", nullable = false, updatable = true)
private String companyName = null;

@Column(name = "COMPANY_PHONE", nullable = true, updatable = true)
private long companyPhone = 0;

@Column(name = "COMPANY_EMAIL", nullable = true, updatable = true)
private String companyEmail = null;

@Column(name = "COMPANY_WEBSITE", nullable = true, updatable = true)
private String webSite = null;

public String getCompanyCode() {
    return companyCode;
}

public void setCompanyCode(String companyCode) {
    this.companyCode = companyCode;
}

public String getCompanyName() {
    return companyName;
}

public void setCompanyName(String companyName) {
    this.companyName = companyName;
}

public long getCompanyPhone() {
    return companyPhone;
}

public void setCompanyPhone(long companyPhone) {
    this.companyPhone = companyPhone;
}

public String getCompanyEmail() {
    return companyEmail;
}

public void setCompanyEmail(String companyEmail) {
    this.companyEmail = companyEmail;
}

public String getWebSite() {
    return webSite;
}

public void setWebSite(String webSite) {
    this.webSite = webSite;
}

@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result
            + ((companyCode == null) ? 0 : companyCode.hashCode());
    result = prime * result
            + ((companyName == null) ? 0 : companyName.hashCode());
    return result;
}

@Override
public boolean equals(Object obj) {
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    CompanyDetails other = (CompanyDetails) obj;
    if (companyCode == null) {
        if (other.companyCode != null)
            return false;
    } else if (!companyCode.equals(other.companyCode))
        return false;
    if (companyName == null) {
        if (other.companyName != null)
            return false;
    } else if (!companyName.equals(other.companyName))
        return false;
    return true;
}

@Override
public String toString() {
    return "CompanyDetails [companyCode=" + companyCode + ", companyName="
            + companyName + ", companyPhone=" + companyPhone
            + ", companyEmail=" + companyEmail + ", webSite=" + webSite
            + "]";
}
}

Repository

@Repository
public class DetailsDaoImpl implements DetailsDao {

private SessionFactory sessionFactory;

public void setSessionFactory(SessionFactory sessionFactory) {
    this.sessionFactory = sessionFactory;
}
@Override
@Transactional(readOnly = true)
public List<CompanyDetails> getCompanyDetails() {
    List<CompanyDetails> details = (List<CompanyDetails>) sessionFactory.getCurrentSession().createCriteria(CompanyDetails.class).list();
    return details;
}

@Override
@Transactional(readOnly = true)
public CompanyDetails getCompanyDetails(String companyShortCode) {
    System.out.println("companyShortCode = "+companyShortCode);
    CompanyDetails details = (CompanyDetails) sessionFactory.getCurrentSession().load(CompanyDetails.class, companyShortCode);
    System.out.println("details = "+details);
    return details;
}
}

Service

public class CompanyServicesImpl implements CompanyServices {

@Autowired
DetailsDao detailsDao;

@Override
public List<CompanyDetails> getCompanyDetails() {
    return detailsDao.getCompanyDetails();

}

@Override
public CompanyDetails getCompanyDetails(String companyShortCode) {
    System.out.println("companyShortCode = "+companyShortCode);
    return detailsDao.getCompanyDetails(companyShortCode);
}

}

If I call List<CompanyDetails> getCompanyDetails(), It return -

[
  {
  "companyCode": "ABCD",
  "companyName": "Test Company",
  "companyPhone": 11226123456,
  "companyEmail": "[email protected]",
  "webSite": "www.abc.com"
   },
  {
  "companyCode": "XYZA",
  "companyName": "XYZA Company",
  "companyPhone": 1122000000,
  "companyEmail": "[email protected]",
  "webSite": "www.XYZA.com"
   }
]

But when i call - Public @ResponseBody CompanyDetails getCompanyDetails(@PathVariable("companyShortCode") String companyShortCode) {, It return -

{"companyPhone": 0}

I tried with dummy Object and it makes it to Json. Tried Creating normal bean and not @Entity and used BeanUtils to copy properties and responding the correct Json. Anyone Know why this is happening?

Updated

before sending response, it is printing as CompanyDetails [companyCode=ABCD, companyName=Test Company, companyPhone=9823611147, [email protected], webSite=www.abc.com]

Upvotes: 1

Views: 106

Answers (2)

SachinSarawgi
SachinSarawgi

Reputation: 2692

In your public CompanyDetails getCompanyDetails(String companyShortCode) method when you are retrieving CompanyDetails object using its Primary Key companyShortCode you are using load method.

load method return a proxy object in which only Primary Key attribute is set and all other attributes are not set. Your session object will send query for retrieving the actual object only when you call any one of getter method for a attribute like details.getCompanyEmail().

So for avoiding that you can call get method. See below code snippet:

@Override
@Transactional(readOnly = true)
public CompanyDetails getCompanyDetails(String companyShortCode) {
    System.out.println("companyShortCode = "+companyShortCode);
    CompanyDetails details = (CompanyDetails) sessionFactory.getCurrentSession().get(CompanyDetails.class, companyShortCode);
    System.out.println("details = "+details);
    return details;
}
}

If you want to go for load method then use below code snippet:

@Override
@Transactional(readOnly = true)
public CompanyDetails getCompanyDetails(String companyShortCode) {
    System.out.println("companyShortCode = "+companyShortCode);
    CompanyDetails details = (CompanyDetails) sessionFactory.getCurrentSession().load(CompanyDetails.class, companyShortCode);
    details.getCompanyName(); //after this all attribute of CompanyDetails object will be set
    System.out.println("details = "+details);
    return details;
}
}

For more reference see this

Hope it helps.

Upvotes: 3

Kiran Kumar
Kiran Kumar

Reputation: 1051

First of all the code is not completely posted, And I am not clear wi ththe response of the second call. The problem might be in the companyservices where you might be creating new object rather than fetching from JPA or from its underlying platform. Another cause might be the JPA configuration.

Upvotes: -1

Related Questions