I have some backend which adds new data in the database. Link for add new data looks like this:
...handler.php?type=add&comment=ads&idImage=2&idAuthor=3
And response:
{
"success": true
}
And my inteface:
public interface CommentAddRequest
{
#GET("handler.php")
Observable<SimpleResponse> getResponse(#Query("type") String type,
#Query("comment") String comment,
#Query("idImage") Long idImage,
#Query("idAuthor") Long idAuthor
);
}
public class SimpleResponse
{
public Boolean getSuccess()
{
return success;
}
public void setSuccess(Boolean success)
{
this.success = success;
}
#SerializedName("success")
#Expose
private Boolean success;
}
I formirate requset like this:
public static Observable<SimpleResponse> addComment(String comment, Long idImage, Long idAuthor)
{
String type = "add";
CommentAddRequest service = ServiceGenerator.createService(CommentAddRequest.class);
return service.getResponse(type, comment, idImage, idAuthor);
}
}
I debug my code and everything is normal. Request is sends. But in DB doesn't add new data. Though through the browser it works normal. I don't have idea where i should looking up the error. Can you help me?
Related
I am learning the jersey #POST REST call for a simple method which takes in json and returns a simple text. I am using MOXY with Jersey.
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-moxy</artifactId>
<version>2.28</version>
</dependency>
My method looks as follows:
#Path("/travel")
#POST
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.TEXT_PLAIN)
public String testServletPost(ThingsToSeeInParis thingsToSeeInParis)
{
if (thingsToSeeInParis != null){
System.out.println("thingsToSeeInParis.isSeenEiffeltower() "+thingsToSeeInParis.isSeenEiffeltower());
System.out.println("thingsToSeeInParis.isSeenLouvre() "+thingsToSeeInParis.isSeenLouvre());
System.out.println("thingsToSeeInParis.isSeenMontMaetre() "+thingsToSeeInParis.isSeenMontMaetre());
System.out.println("thingsToSeeInParis.id "+thingsToSeeInParis.getId());
}
if (thingsToSeeInParis.isSeenEiffeltower() && thingsToSeeInParis.isSeenLouvre()){
System.out.println("Please shut up the lady behind me");
return "OK";
}
else{
System.out.println("Its a lost case!");
return "Not OK";
}
}
My ThingsToSeeInParis class is simple POJO class. Looks as follows:
public class ThingsToSeeInParis {
private boolean seenEiffeltower;
private boolean seenMontMaetre;
private boolean seenLouvre;
private int id;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public boolean isSeenEiffeltower() {
return seenEiffeltower;
}
public void setSeenEiffeltower(boolean seenEiffeltower) {
this.seenEiffeltower = seenEiffeltower;
}
public boolean isSeenMontMaetre() {
return seenMontMaetre;
}
public void setSeenMontMaetre(boolean seenMontMaetre) {
this.seenMontMaetre = seenMontMaetre;
}
public boolean isSeenLouvre() {
return seenLouvre;
}
public void setSeenLouvre(boolean seenLouvre) {
this.seenLouvre = seenLouvre;
}
}
When I call this method from POSTMAN I get 200 response code but it always returns "Not OK". My postman calls are as follows:
No matter what or how many inputs I put I always get the same output. MOXY is just initializing all the values to default and that is why evaluation is not working. Can someone spot the issue in this code? Please let me know. Thank you.
My problem lies in the fields of JsonSerialization as implemented in Jackson FasterXML Library. I have a series of endpoints through which I exchange content between my back-end and a MVVM front-end framework. This is working, but now I am a little stuck as I got to the point where I want to handle user creation/registration.
This is the model (entity) that represents a group in my application (I omit irrelevant import declarations and JPA annotations):
#JsonRootName(value="userGroup")
#JsonInclude(JsonInclude.Include.NON_NULL)
public class Groups extends MetaInfo implements Serializable {
private String groupName;
private Set<Credential> credentials = new HashSet<>();
public Groups() {
super();
}
public Groups(String groupName) {
this();
this.groupName = groupName;
}
public Groups(String createdBy, String groupName) {
this();
setCreatedBy(createdBy);
this.groupName = groupName;
}
#JsonGetter("group_Name")
// #JsonValue
public String getGroupName() {
return groupName;
}
public void setGroupName(String groupName) {
this.groupName = groupName;
updateModified();
}
#JsonIgnore
public Set<Credential> getCredentials() {
return credentials;
}
public void setCredentials(Set<Credential> credentials) {
this.credentials = credentials;
}
public void addCredential(Credential c) {
credentials.add(c);
if (c.getGroup() != this) {
c.setGroup(this);
}
}
#Override
public String toString() {
return "Groups{" + "groupName=" + groupName + '}';
}
}
And this is the method in the endpoint that retrieves (if exists) and returns a serialized version of a Groups to a JavaScript client:
#Path("/groups")
#Produces("application/json")
public class GroupsResourceService extends RimmaRestService{
#Inject
#Production
private GroupsRepository groupsRepository;
...
#GET
#Path("{group}")
public Response getGroup(#PathParam("group") String group){
if(InputValidators.stringNotNullNorEmpty.apply(group)){
//proceed with making call to the repo
Optional<Groups> optGroup = ofNullable(groupsRepository.getByGroupName(group));
if(optGroup.isPresent()){//ultimately success scenario
try {
String output = getMapper().writeValueAsString(optGroup.get());
return Response.ok(output).build();
} catch (JsonProcessingException e) {
logger.error("Serialization error: "+e.getMessage()+
"\n"+e.getClass().getCanonicalName());
throw new InternalServerErrorException("Server error "
+ " serializing the requested group \""+group+"\"");
}
} else{
throw new NotFoundException("Group " + group + " could not be found");
}
}else{//empty space after the slash
throw new BadRequestException("You haven't provided a group parameter",
Response.status(Response.Status.BAD_REQUEST).build());
}
}
}
Trying to test this code like this:
#Test
public void successfullResponse(){
Response success = groupsResourceService.getGroup("admin");
assertTrue(success.getStatus()==200);
}
...cruelly fails:
<< ERROR!
javax.ws.rs.InternalServerErrorException: Server error serializing the requested group "admin"
at com.vgorcinschi.rimmanew.rest.services.GroupsResourceService.getGroup(GroupsResourceService.java:54)
at com.vgorcinschi.rimmanew.services.GroupsResourceServiceTest.successfullResponse(GroupsResourceServiceTest.java:48)
In this case stack trace is of 0 help, though - that's why I am pasting the output of the log that catches the underlying Json exception:
15:05:05.857 [main] ERROR com.vgorcinschi.rimmanew.rest.services.GroupsResourceService - Serialization error: Can not write a field name, expecting a value
com.fasterxml.jackson.core.JsonGenerationException
Having visited and analyzed 13 similar complaints links (of which 3 are from stackoverflow) I came up with a solution which is more a workaround - if you look back at the entity, I have commented #JsonValue. If I uncomment that and comment #JsonGetter("group_Name") then the test passes with the following output:
{"userGroup":"admin"}
This being only a workaround, I decided to recur to asking for help which I hope someone will be able and kind enough to provide.
Good evening SO,
I wrote two pretty simple classes for one of my projects. This is the first time I met such a problem, so I would like to ask you if I managed to tackle the problem the right way / with good implementation.
The background is quite simple: You have a Channel that might be either busy or not. If the Channel is busy, it means it was taken by a ServiceRequest. Once the request is processed the Channel should be open again.
I googled a little bit and found ideas to use the PropertyChangedListener. Code down below. Please give me all the comments you can regarding the code quality / problem solving here. Thank you!
Test:
#Unroll
def "when request is processed and finished channel is free again"() {
given:
def channel = new Channel()
def request = new ServiceRequest()
request.addPropertyChangeListener(channel)
when:
channel.setRequest(request)
request.finish();
then:
assert !channel.isBusy() && channel.request == null
}
Channel class:
public class Channel implements PropertyChangeListener{
private boolean busy;
private ServiceRequest request;
public Channel() {
this.busy = false;
}
public boolean isBusy() {
return busy;
}
public ServiceRequest getRequest() {
return request;
}
public void setRequest(final ServiceRequest request) {
this.request = request;
busy = true;
}
#Override
public void propertyChange(PropertyChangeEvent evt) {
request = null;
busy = false;
}
ServiceRequest class:
public class ServiceRequest {
PropertyChangeSupport support = new PropertyChangeSupport(this);
private String id;
public ServiceRequest() {
id = "randomlygeneratedid";
}
void addPropertyChangeListener(final PropertyChangeListener l) {
support.addPropertyChangeListener(l);
}
public void finish() {
id = "";
support.firePropertyChange("id", id, "");
support.firePropertyChange("request", null, null);
support.firePropertyChange("busy", null, false);
}
public String getId() {
return id;
}
Here is my code
public class Validator {
private String message = "ok";
public String mainValidate(String value) {
if(!isAccept1()) {
message = "fail1";
return message;
}
if(!isAccept2()) {
message = "fail2";
return message;
}
if(!isAccept3()) {
message = "fail3";
return message;
}
return message;
}
public boolean isAccept1() {}
public boolean isAccept2() {}
public boolean isAccept3() {}
Requirement is: If the code meet any error, return message immediately.
As you can see, with current code, I repeat myself very much.
How can I structure the code and still keep requirement. If any error occur, the code skip other validate and return error message
Many thanks!
You can put all the checks in one method:
public String mainValidate(String value) {
String message = isAccept();
if(!message.equalsIgnoreCase("ok")) {
return message;
}
}
private String isAccept() {
String returnString = "ok";
//check1 - change returnString to whatever message if check fails
//check2 - change returnString to whatever message if check fails
//check3 - change returnString to whatever message if check fails
//etc...
return returnString;
}
You could store the actions / messages in a map and iterate over it:
private static final Map<Predicate<String>, String> VALIDATIONS = new LinkedHashMap<> ();
static {
VALIDATIONS.put(Validator::isAccept1, "fail1");
VALIDATIONS.put(Validator::isAccept2, "fail2");
//etc.
}
public String mainValidate(String value) {
for (Entry<Predicate<String>, String> v : VALIDATIONS.entrySet()) {
Predicate<String> validator = v.getKey();
String errorMsg = v.getValue();
if (!validator.test(value)) return errorMsg;
}
return "ok";
}
public static boolean isAccept1(String value) { return /* ... */; }
This is known as:
Design by Contract
or Precondition
or Method Argument Validation
See also A good Design-by-Contract library for Java?
I am trying to pull data from class in another class and populate a JPanel with the data, but it is not working for some reason.
Here is the full restConnector class where I pull the JSON data.
As far as I know this works fine.
public class restConnector {
private static final Logger LOGGER = LoggerFactory.getLogger(restConnector.class);
private static final restConnector INSTANCE = new restConnector();
public static restConnector getInstance() {
return restConnector.INSTANCE;
}
private restConnector(){
}
private static String user = "ss";
private static String pwd = "ee
public static String encode(String user, String pwd) {
final String credentials = user+":"+pwd;
BASE64Encoder encoder = new sun.misc.BASE64Encoder();
return encoder.encode(credentials.getBytes());
}
//Open REST connection
public static void init() {
restConnector.LOGGER.info("Starting REST connection...");
try {
Client client = Client.create();
client.addFilter(new LoggingFilter(System.out));
WebResource webResource = client.resource("https://somewebpage.com/
String url = "activepersonal";
ClientResponse response = webResource
.path("api/alerts/")
.queryParam("filter", ""+url)
.header("Authorization", "Basic "+encode(user, pwd))
.header("x-api-version", "1")
.accept("Application/json")
.get(ClientResponse.class);
if (response.getStatus() != 200) {
}else{
restConnector.LOGGER.info("REST connection STARTED.");
}
String output = response.getEntity(String.class);
ObjectMapper mapper = new ObjectMapper();
mapper.setPropertyNamingStrategy(new MyNameStrategy());
try {
List<Alert> alert = mapper.readValue(output, new TypeReference<List<Alert>>(){});
} catch (JsonGenerationException e) {
e.printStackTrace();
} catch (JsonMappingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void close() {
}
}
However, when I try to pull the data in another class it gives me just null values from the system.out.print inside refreshData() method. Here is the code that is supposed to print the data
public class Application{
Alert alerts = new Alert();
public Application() {
refreshData();
}
private void initComponents() {
restConnector.init();
refreshData();
}
private void refreshData() {
System.out.println("appalertList: "+alerts.getComponentAt(0));
}
}
Here is my Alert class
#JsonIgnoreProperties(ignoreUnknown = true)
#JsonInclude(Include.NON_EMPTY)
public class Alert {
private int pasID;
private String status;
private boolean shared;
private String header;
private String desc;
public int getPasID() {
return pasID;
}
public void setPasID(int pasID) {
this.pasID = pasID;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public boolean isShared() {
return shared;
}
public void setShared(boolean shared) {
this.shared = shared;
}
public String getHeader() {
return header;
}
public void setHeader(String header) {
this.header = header;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
#Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("\n***** Alert Details *****\n");
sb.append("PasID="+getPasID()+"\n");
sb.append("Status="+getStatus()+"\n");
sb.append("Shared="+isShared()+"\n");
sb.append("Header="+getHeader()+"\n");
sb.append("Description="+getDesc()+"\n");
sb.append("*****************************");
return sb.toString();
}
public String getComponentAt(int i) {
return toString();
}
}
I'm kind a lost with this and been stuck here for a couple of days already so all help would be really appreciated. Thanks for the help in advance.
Edit: Formatted the code a bit and removed the NullPointerException as it was not happening anymore.
As stated in comments:
Me: In your first bit of code you have this try { List<Alert> alert.., but you do absolutely nothing with the newly declared alert List<Alert>. It this where the data is supposed to be coming from?
OP: I'm under the impression that that bit of code is the one that pushes the JSON Array to the Alert.class. Is there something I'm missing there?
Me: And what makes you think it does that? All it does is read the json, and the Alert.class argument is the class type argument, so the mapper know the results should be mapped to the Alert attributes when it creates the Alert objects. That's how doing List<Alert> is possible, because passing Alert.class decribes T in List<T>. The List<Alert> is what's returned from the reading, but you have to determine what to actually do with the list. And currently, you do absolutely nothing with it
You maybe want to change the class just a bit.
Now this is in no way a good design, just an example of how you can get it to work. I would take some time to sit and think about how you want the restConnector to be fully utilized
That being said, you can have a List<Alert> alerts; class member in the restConnector class. And have a getter for it
public class restConnector {
private List<Alert> alerts;
public List<Alert> getAlerts() {
return alerts;
}
...
}
Then when deserializing with the mapper, assign the value to private List<Alert> alerts. What you are doing is declaring a new locally scoped list. So instead of
try {
List<Alert> alert = mapper.readValue...
do this instead
try {
alerts = mapper.readValue
Now the class member is assigned a value. So in the Application class you can do something like
public class Application {
List<Alert> alerts;
restConnector connect;
public Application() {
initComponents();
}
private void initComponents() {
connector = restConnector.getInstance();
connector.init();
alerts = connector.getAlerts();
refreshData();
}
private void refreshData() {
StringBuilder sb = new StringBuilder();
for (Alert alert : alerts) {
sb.append(alert.toString()).append("\n");
}
System.out.println("appalertList: "+ sb.toString());
}
}
Now you have access to the Alerts in the list.
But let me reiterate: THIS IS A HORRIBLE DESIGN. For one you are limiting the init method to one single call, in which it is only able to obtain one and only one resource. What if the rest service needs to access a different resource? You have made the request set in stone, so you cant.
Take some time to think of some good OOP designs where the class can be used for different scenarios.