I have a class DistributionRule class which contains private Set distributions;
#Getter
#Setter
public class DistributionRule extends BaseModel {
private String ruleName;
private String skuId;
private String catalogueId;
private String categoryId;
private Boolean active;
private RuleLevel level;
private Set<Distribution> distributions;
private Double thresholdValue;
private RuleType ruleType = RuleType.GENERAL;
#Getter
#Setter
public static class Distribution {
private String consumerId;
private Double distribution;
}
}
In RuleServiceImpl, there is a method to get DistributionRule list:
#Override
public List<DistributionRule> getDistributionRules() {
return ruleRepository.findAll();
}
In DivRuleApplicationTests class:
#RunWith(SpringRunner.class)
#SpringBootTest
class DivRuleApplicationTests {
#Autowired
private RuleServiceImpl ruleServiceImpl;
#MockBean
RuleRepository ruleRepository;
#Test
void test() {
assertTrue(true);
}
#Test
public void getDistributionRulesTest(){
Set<Distribution> distributions = new HashSet();
when(ruleRepository.findAll()).thenReturn(Stream
.of(new DistributionRule("rule0010", "0010", " ", " ", true, "SKU", ""),
new DistributionRule("rule0020", "0020", "", "", true, "SKU", ""))
.collect(Collectors.toList()));
assertEquals(2, ruleServiceImpl.getDistributionRules().size());
}
}
How do I pass the "Distribution" values in Stream.of()?
Firstly, the method you are trying to mock on when, returns a List<DistributionRule>. In this case, you don't need to create a Stream.of(new DistributionRule(...)) and then collect it as a List. Simply use List.of(new DistributionRule(...)), as it will return the List you want it.
Secondly, you should annotate both DistributionRule and inner class Distribution with #AllArgsConstructor to generate a constructor with all arguments. This will let you create an DistributionRule object passing the Distribution Set as a parameter:
#Test
public void getDistributionRulesTest(){
Set<Distribution> distributions1 = Set.of(
new Distribution(...), new Distribution(...)
);
Set<Distribution> distributions2 = Set.of(
new Distribution(...), new Distribution(...)
);
when(ruleRepository.findAll()).thenReturn(List.of(
new DistributionRule("rule0010", "0010", ..., distributions1, ..),
new DistributionRule("rule0020", "0020", ..., distributions2, ...)
));
assertEquals(2, ruleServiceImpl.getDistributionRules().size());
}
PS: I usually use the #Data annotation instead of #Getter and #Setter, as it's a shortcut for that and other annotations. You can take a look here if you want to know more: https://projectlombok.org/features/Data
Related
#JsonInclude(JsonInclude.Include.NON_NULL)
public class Flight implements Serializable {
private TrackInformation trackInformation;
private MiscData miscData;
private CargoItems cargoItems;
}
Controller class
#RequestMapping(value = "/getFlightByKey", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
public Flight getFlightByKey(#RequestBody #Valid final FlightInfoRequestDTO request)throws NoDataFoundException {
return flightInfoAppService.getFlightByKey(request.getKey());
}
public class TrackInformation extends AbstractRecord {
private static final long serialVersionUID = -5226745652646434627L;
private String sourceFacility;
private ComputerID computerID;
private String sourceTimeStamp;
private Double latitude;
private Double longitude;
private ReportedAltitude reportedAltitude;
private Integer speed;
}
public abstract class AbstractRecord implements Serializable {
}
Now the returned flight object has null fields for nested objects. How can I ignore null fields from nested objects.
did hashCode and equals override in TrackInformation.
You should add #JsonInclude(JsonInclude.Include.NON_NULL) on every nested class as well to ignore nested class null value properties
#JsonInclude(JsonInclude.Include.NON_NULL)
public class TrackInformation extends AbstractRecord {
// properties
}
I'm new to Spring Boot. I have a mysql database, I use a query to count row in my table. But it's not work, it still return my original table data. Can you help me check my code.
Here is my Entity:
#Entity
#Table(name = "act_id_membership", schema = "activiti", catalog = "")
#IdClass(ActIdMembershipEntityPK.class)
public class ActIdMembershipEntity {
private String userId;
private String groupId;
#Id
#Column(name = "USER_ID_")
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
#Id
#Column(name = "GROUP_ID_")
public String getGroupId() {
return groupId;
}
public void setGroupId(String groupId) {
this.groupId = groupId;
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ActIdMembershipEntity that = (ActIdMembershipEntity) o;
return Objects.equals(userId, that.userId) &&
Objects.equals(groupId, that.groupId);
}
#Override
public int hashCode() {
return Objects.hash(userId, groupId);
}
}
Here is my query:
#Repository
public interface MemershipRepository extends JpaRepository<ActIdMembershipEntity, String> {
#Query ("select new com.example.activiti_restful.dtos.UserMembership(i.userId, count(i)) from ActIdMembershipEntity i where i.userId ='kermit'")
UserMembership countMemberships(String userId);
}
Updated code:
My service class:
#Service
public class MembershipService {
#Autowired
private MemershipRepository repository;
public long count() {
return repository.count();
}
My resource class:
#RestController
public class MembershipResource {
#Autowired
private MembershipService membershipService;
#GetMapping("/membership")
public long list() {return membershipService.count();}
}
My custom JSON Object class:
public class UserMembership {
private String userId;
private long numberOfusers;
public UserMembership(String userId, long numberOfusers) {
this.userId = userId;
this.numberOfusers = numberOfusers;
}
}
MySQL Table:
act_id_membership
According repositories documentation using CrudRepository provides a method called count() that is one of the Superinterfaces which JpaRepository is implemented.
Based CrudRepository documentation says:
long count(); Returns the number of entities.
Then you should use CrudRepository method. In addition Remove Uppercase MembershipREPOSITORY, by java code convention, you have to use by following way MembershipRepository.
#Repository
public interface MembershipRepository extends JpaRepository <ActIdMembershipEntity, String> {
}
And use it in your Service:
#Service
public class MembershipService {
#Autowired
private MembershipRepository repo;
public long count() {
return repo.count();
}
}
UPDATED
Based on your requirement:
In Controller:
#RestController
public class MembershipResource {
#Autowired
private MembershipService membershipService;
#GetMapping("/membership")
public List<Object> list() { return membershipService.countMemberships();
}
}
In Service:
#Service
public class MembershipService {
#Autowired
private MemershipRepository repository;
public List<Object> countMemberships() {
return repository.countMemberships();
}
}
In Repository:
#Repository
public interface MemershipRepository extends JpaRepository<ActIdMembershipEntity, String> {
#Query ("select i.userId, count(i) from ActIdMembershipEntity i where i.userId ='kermit'")
List<Object> countMemberships();
}
*> Actually I want it return a json format like [{ name: kermit, value:6}]. Now it just return a number 6 only. How I can do that? Thank you!
First, create a class to wrap your data:
public class UserMembership {
private String userId;
private long numberOfUsers;
public UserMembership(String userId, long numberOfUsers) {
this.userId = userId;
this.numerOfUsers = numberOfUsers;
}
}
Then
#Repository
public interface MembershipRepository extends JpaRepository <ActIdMembershipEntity, String> {
#Query ("select new *****.UserMembership(i.userId, count(i)) from ActIdMembershipEntity i where i.userId = :userId")
UserMembership countMemberships(String userId);
}
*****: your full package name
Hope it help!
I am trying to save nested JSON in a database using Spring Boot and RestController. Those JSONs look something like this:
{
"name": "Car 1",
"plate_number": "PLATE NUMBER",
"owner": {
"first_name": "First name",
"last_name": "Last name"
}
}
It was easy to map the normal fields (name and plate number) using the auto mapping provided by spring in the RestController:
public Car createProduct(Car car) {
}
But now, how can i map the object owner to it's own class, CarOwner?( I need to mention that i have multiple classes that uses this approach so a generalised way would be very useful )
EDIT:
My entities look like this:
#Entity
#Table(name = "cars")
public class Car extends BaseEntityWithName {
private String name;
private String plateNumber;
#ManyToOne(fetch = FetchType.EAGER)
#JoinColumn(name = "owner_id")
private Owner owner;
}
#Entity
#Table(name = "car_owners")
public class CarOwner extends BaseEntityWithName {
private String firstName;
private String lastName;
// Constructor, setters, getters
}
And I'm trying to do something like this in the controller:
#RestController
#RequestMapping("/cars")
public class CarController {
#Autowired
private CarService carService;
#RequestMapping(value = "/create", method = RequestMethod.POST)
#ResponseBody
public ProductModel createItem(Car car) {
// How do I create the owner using the JSON parameters
// provided in the nested JSON?
car.setOwner(owner); // Owner created above
return carService.save(car);
}
}
EDIT 2
My two services look like this. The structure is the same on both of them.
#Service
public class CarServiceImpl implements CarService {
#Autowired
private ProductManufacturerRepository productManufacturerRepository;
#Autowired
private CarRepository carRepository;
#Override
public List<Car> findAll() {
return carRepository.findAll();
}
#Override
public Car findOne(Long id) {
return carRepository.findOne(id);
}
#Override
#Transactional
public Car save(Car car) {
return carRepository.save(car);
}
#Override
public void removeOne(Long id) {
carRepository.delete(id);
}
}
From your service layer I can see that you just need to save the owner class. Preferrably this would be in a separate Owner service but this is good enough for a start.
#Service
public class CarServiceImpl implements CarService {
#Autowired
private ProductManufacturerRepository productManufacturerRepository;
#Autowired
private CarRepository carRepository;
#Override
public List<Car> findAll() {
return carRepository.findAll();
}
#Override
public Car findOne(Long id) {
return carRepository.findOne(id);
}
#Override
#Transactional
public Car save(Car car) {
Owner person = car.getOwner();
ownerRepository.save(person);
return carRepository.save(car);
}
#Override
public void removeOne(Long id) {
carRepository.delete(id);
}
}
I am trying to make a simple round-trip with a REST API that leads to storing an entity into the db and then returns the stored entity.
Going down works fine and the entity is stored and correctly returned to the REST Controller. However, when I return it, Jackson seems to serialize it incorrectly, as the "name" attribute is not included.
This is the entity:
#Entity
#Configurable
public class MyEntity extends IdentifiableEntity {
private String name;
protected MyEntity() {
};
public MyEntity(String name) {
this.name = name;
}
}
and the extended entity:
#Configurable
#Inheritance(strategy = InheritanceType.JOINED)
#Entity
public abstract class IdentifiableEntity {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
#Column(name = "id")
private Long id;
#Version
#Column(name = "version")
private Integer version = 1;
public String toString() {
return ReflectionToStringBuilder.toString(this,
ToStringStyle.SHORT_PREFIX_STYLE);
}
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
public Integer getVersion() {
return this.version;
}
public void setVersion(Integer version) {
this.version = version;
}
}
The REST controller is:
#RestController
#RequestMapping("/service")
public class Service {
#RequestMapping(value = "/public/{name}", method = RequestMethod.GET)
public MyEntity storeEntityPublic(#PathVariable String name) {
System.out.println("Hello " + name
+ ", I am saving on the db. (PUBLIC)");
MyEntity saved = controller.saveEntity(name);
return saved;
}
}
Then my business logic:
#Service
public class LogicController {
#Autowired
private MyEntityRepository myEntityRepository;
public MyEntity saveEntity(String name) {
MyEntity cg = new MyEntity(name);
return myEntityRepository.save(cg);
}
}
I am using Spring repositories:
#Repository
public interface MyEntityRepository extends JpaSpecificationExecutor<MyEntity>,
JpaRepository<MyEntity, Long> {
}
The returned JSON is:
{"id":12,"version":1}
Where is my "name" attribute? Is is set in the variable being returned by the REST controller.
I found the trick: MyEntity needs to have a public get for the property that has to be shown. A good reason to use a DTO pattern.
In response to your "I don't want to have my Entity "dirty"" comment: Jackson allows the use of so-called Mixins. They allow you to define annotations for your class outside the class itself. In your case it could look like this:
public abstract class MyEntityMixin {
#JsonProperty
private String name;
}
You may keep it as a field and annotate the field with #JsonProperty if you like.
I have a project (homework) about JAX-RS. I'm working with NetBeans, Jersey and Tomcat.
This is my "User" class for main object in the system.
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement(name="user")
public class User {
//#XmlElement
//public int id ;
#XmlElement
public String username;
#XmlElement
public String fullname;
#XmlElement
public String gender;
#XmlElement
public String birthDate;
public User(){
}
public User(String username,String fullname, String gender,String birthDate){
//this.id = id;
this.username = username;
this.fullname = fullname;
this.gender = gender;
this.birthDate = birthDate;
}
}
This is my "JAXBContextResolver" Class
import com.sun.jersey.api.json.JSONConfiguration;
import com.sun.jersey.api.json.JSONJAXBContext;
import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.Provider;
import javax.xml.bind.JAXBContext;
#Provider
public class JAXBContextResolver implements ContextResolver<JAXBContext>{
private JAXBContext context;
private Class[] types = {User.class};
public JAXBContextResolver() throws Exception {
this.context =
new JSONJAXBContext( JSONConfiguration.mapped().build(), types);
}
#Override
public JAXBContext getContext(Class<?> objectType) {
for (Class type : types) {
if (type == objectType) {
return context;
}
}
return null;
}
}
And this is my post method in the "UserService" class
#POST
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public List<User> createNewUser(User tUser) {
List<User> list = new ArrayList<User>();
list.add(tUser);
return list;
}
When I am trying a post new user in the localhost with RESTClient (Firefox add-ons) my request body is a json input like that:
{"user":{"username":"blabla","fullname":"blabla","gender":"M","birthDate":"05.01.1978"}}
In the post method (in the UserService class) must the variable "tUser" automatically filled with the coming input ? "tUser" variable shows null elements in it in the debugging mode like that:
If I know wrong could somebody correct me please? Why this values shows null? Must not them shows "blabla" - "blabla" - "M" - "05.01.1878" ? Could you help me please?
I solved this problem; In the JAXBContextResolver class I change the method like that :
public JAXBContextResolver() throws Exception {
this.context =
new JSONJAXBContext( JSONConfiguration.mapped().rootUnwrapping(false).build(), types);
}
The difference with the first one is adding "rootUnwrapping(false)" expression.
#XmlRootElement is not working in your example. Send
{"username":"blabla","fullname":"blabla","gender":"M","birthDate":"05.01.1978"}
instead
EDIT
1)
public List<User> createNewUser(Request tUser)
and class
class Request
{
public User user;
}
2)
public List<User> createNewUser(String tUser)
and convert String to object using google-gson or jackson json processor