I'm trying to do a web application using JAX -WS. My problem seems to be very simple, however I cannot understand how to resolve it. I have class variables which values I need to use in GET and POST requests. For example, I initiate 'response' in GET methode and I need to use it then in POST methode, but when I call POST api/conversation from js I receive an error because 'response' is still null. How can I save value for variables? Here is my code
import javax.ws.rs.*;
#ApplicationPath("api")
#Path("conversation")
public class Conversation {
private final String conversationWorkspace = "myworkspace";
private final static String CONVERSATION_ID = "myid";
private final static String CONVERSATION_PASS = "mypass";
private MessageRequest request;
private MessageResponse response;
private ConversationService service;
#GET
#Produces("application/text")
public String getInitiatePhrase(){
service = new ConversationService("2017-05-26", CONVERSATION_ID, CONVERSATION_PASS);
response = service.message(conversationWorkspace, null).execute(); //here response gets its value
return response.getText().get(0);
}
#POST
#Produces("application/text")
#Consumes("application/text")
public String getBotAnswer(String userText){
System.out.println("response " + response);
request = new MessageRequest.Builder().inputText(userText).context(response.getContext()).build(); //response must not be null
response = service.message(conversationWorkspace, request).execute();
return response.getText().get(0);
}
}
The Java class in question does not seem to be a container managed bean. When you make a rest service call to the GET and subsequently the POST methods, two separate instances of the Conversation class are created. Hence, the class field response will be null in the second POST call.
There are multiple ways to solve this problem. However, the approach to take depends on answering the question: Should the service really be aware of two separate client requests? Or should the client make one GET call and then provide the subsequent POST with the required information.
I would use approach 1 noted below, unless there is a good reason to use either 2, 3 or 4. (2, 3 and 4 are similar just they are different specifications / frameworks)
The client caches the response of the GET and sends the required information back with the POST request
Use an EE stateful session bean (http://docs.oracle.com/javaee/6/tutorial/doc/gipjg.html)
Use a CDI session scoped bean (http://docs.oracle.com/javaee/6/tutorial/doc/gjbbk.html)
Use spring session scoped bean (http://springinpractice.com/2008/05/08/session-scoped-beans-in-spring / https://tuhrig.de/making-a-spring-bean-session-scoped/)
Related
I am quiet new in MVC and Spring and I want to learn best practices and solution so I decided to ask what is the best practice or how you would solve my problem.
I got controller with scope session (To store data in global variable not overrided when another user send request). I got global variable as I mentioned and two endpoints. First endpoint POST - here I send form and call another REST service to fetch data - call depends on data from form. Second endpoint GET - here i send which page to return. This endpoint is used for pagination.
Where is the problem? I have to store data in global variable because when I fetch data in POST endpoint I do not have access to it in GET endpoint. I do not like this solution. Do you have any ideas how to solve it better?
#Controller
#SessionScope
public class someController {
Global variable
#PostMapping(value = "/endpoint")
public String endpoint1(Form form){
//here I fetch data from another REST service depends on form data and save it to global variable
}
#GetMapping(value = "/anotherenpoint")
public String endpoint1(int page){
//here I get data from global variable and return to view as Page object
}
Your #Controller shouldn't be session scoped, instead make your variable session scoped. (you can also annotate it with #Autowired, so your controller automatically has the right variable for the current user)
fellow programmers who lurks here at Stack Overflow.
Today's question: How can I get the absolute baseUrl in Spring MVC Framework, from startup?
I'm working with Spring MVC Framework for an application, and I'm in this situation: Let's say that I need to make objects of class Foo, inserted into a list. Every object contains an unique self-link (I'm using org.springframework.hateoas.Link for the real application, but that's beside the point).
Example code:
class Foo{
private int ID;
private String absoluteUrl;
public Foo(int ID, String baseUrl){
this.ID = ID;
this.absoluteUrl = baseUrl + ID;
}
public void setAbsoluteUrl(String baseUrl){
this.absoluteUrl = baseUrl + this.ID;
}
}
If I run it through a factory, it could look something like this:
public List<Foo> GenerateFooList(String baseUrlFetchedBySpring){
List<Foo> list = new ArrayList();
for (int i = 0; i<100; i++){
list.add(new Foo(i, baseUrlFetchedBySpring);
return list;
}
Resulting baseadresses I would expect during the test phase would be "http://localhost:8000" (or hypothetically, at production, "http://www.fooExample.com").
My issue: I need to get the baseUrl from Spring MVC Framework, at startup.
The Spring MVC application I'm working with is configured by annotations only. I have found out that one can get an absolute url by using HttpServletRequest.getRequestURL().toString(), but to my understanding the application receives these after startup, while I need the baseUrl from the beginning. After all, the Spring API describes HttpServletRequest as: "Defines an object to provide client request information to a servlet", in other words a request sent from a client after startup.
I could of course add a static baseUrl by writing a private final String in the code:
private final String BASE_URL = "http://www.fooExample.com/"
But in case of changes on the application's base-url over time, it would be better if the base url could be set automaticly by Spring MVC. Let's say that I have a Cache-class, that uses dependency injection:
#Repository
class FooCache{
List<Foo> list;
SpringObject springObject; // = ???????????
#Autowired
public FooCache(SpringObject springObject){
this.springObject = springObject; // = ???????????
initCache();
}
public void initCache(){
for (int i = 0; i<100; i++){
list.add(new Foo(i, springObject.getAbsoluteBaseUrl()); // method = ???????????
}
}
This is more of what I am looking for: The cache is only set once, at the beginning, using an object from Spring that contains the information I need. Most likely, it's a config-class that is part of the framework, but after searching for a while on the Internet, what I mostly find is HttpServletRequest-related solutions.
What Spring class/object and method am I truly looking for? Or what other suggestions do you have to fetch the base_url from the beginning?
I need the absolute base url for this one, not something relative.
There is no single "base URL" for your application. Think about it - you can access your production server:
via different domain names
via IP
SSH to it and access via "localhost"
via HTTP and HTTPS
If you don't want to or cannot reflect the "base URL" of the request, my suggestion would be to have one "canonical base URL" configured per environment eg. in the properties. But that's up to you if it makes sense in your case.
If you're using java config and Servlet 3.0+ style (without web.xml), you could have a WebApplicationInitializer implementation such as:
public class MyWebApplicationInitializer implements WebApplicationInitializer {
#Override
public void onStartup(ServletContext container) {
ServletRegistration.Dynamic registration = container.addServlet("dispatcher", new DispatcherServlet());
registration.setLoadOnStartup(1);
registration.addMapping("/example/*");
}
}
with this arrangement, you could use servletContext.getContextPath() to get base url.
You have no way of knowing that without a request. You could use InetAddress and resolve host information, but I am guessing that is not what you are looking for.
Let's say you have two domains www.foo.com and www.bar.com pointing to the host where your application is running. On startup you have no information about any of that, you would have to do a reverse DNS search.
When you get a request, you have the information where it is coming from.
You should fill the links on request so you can get rid of caching request scope information.
I am using Jersey Restful webservices. I have below web method to get the results.
#Path("/persons")
public class PersonWS {
private final static Logger logger = LoggerFactory.getLogger(PersonWS.class);
#Autowired
private PersonService personService;
#GET
#Path("/{id}")
#Produces({MediaType.APPLICATION_XML})
public Person fetchPerson(#PathParam("id") Integer id) {
return personService.fetchPerson(id);
}
#DELETE
#Path("/{id}")
public void deletePerson(#PathParam("id") Integer id) {
return personService.deletePerson(id);
}
}
In above Jersey RESTful webservice, i have two web methods one for get and one more for delete with same number of parameters. In above case will there be any ambiguity? If not what should be the URIs for both of the methods? Thanks!
Thanks!
Jersey decides which method to call based on the HTTP method specified in the request. If you use multiple methods with the same HTTP method like GET, then the choice is made by more Annotations like Consumes or Produces etc.
BTW: If you use the URI /persons/{id} for all endpoints, then you can annotate your class with #Path("/persons/{id}") instead of annotating every method with this sub-URI.
There is no ambiguity as the HTTP Method is different (GET vs DELETE).
The same url would also be used to update the object, using the HTTP method PUT
No ambiguity since the HTTP methods used are different i.e GET and DELETE
And the urls will be same as the param required is "id" for both
IN Jersey client program use GET http method for fetching person info, Use DELETE http method for deleting the person.
I have created a jersey web service as following,
#Path("/myservice")
class MywebService{
private int requestNum = 0;
#GET
#Path("/mymethod")
#Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
public void myMethod(){
System.out.println("Request number : "+(++requestNum));
}
}
But each time when I call that myMethod through the web service , I get the request number as 1. Seems like the requestNum always resets to 0. Can anyone help me to solve this problem?
Try making it static, i.e.
static private int requestNum = 0;
The container (Jersey) is responsible for creating instances of your service. Thus you may have multiple different instances. Using an instance variable will not work well. The value of that variable will represent the number of times that instance has received a request.
If you use a static variable, that will count the number of requests sent to all instances of your web service class.
I have an http endpoint redirecting to a REST Java web service.
I am receiving a application/x-www-form-urlencoded request with some attributes embedded within the body of the request.
Inside the web service I would like to update the mule message status with those attributes.
Since RequestContext.getEventContext() is now deprecated and Doc says to implement Callable instead, however seems not working to me.The onCall method is never invoked.
Any idea ?
Below my code:
enter code here
#Path("/restClass")
public class HelloREST implements Callable{
private String industry;
private String lob;
private String nuixlegalentity;
private org.apache.log4j.Logger log = Logger.getLogger(LoadClass.class);
#POST
#Path("/setPayload")
#Consumes("application/x-www-form-urlencoded")
public void setMessage(#FormParam("industry") String industryParam, #FormParam("lob") String lobParam,#FormParam("nuixlegalentity") String nuixlegalentityParam){
log.debug("**************INSIDE SETMESSAGE******************");
industry=industryParam;
lob=lobParam;
nuixlegalentity=nuixlegalentityParam;
}
#Override
public Object onCall(MuleEventContext eventContext) throws Exception{
log.debug("**************INSIDE ONCALL******************");
eventContext.getSession().setProperty("industry","industry");
eventContext.getSession().setProperty("lob",lob);
eventContext.getSession().setProperty("nuixlegalentity",nuixlegalentity);
return eventContext.getMessage();
}
}
}
I assume you're using this class as a resource with the Jersey transport. In that case, Mule will call the JAX-RS annotated methods, based on the incoming request, and thus will not call onCall. Therefore implementing Callable is of no use.
Using RequestContext.getEventContext() is the only way possible to get the EventContext in a Jersey-handled resource.
To this date, MuleSoft hasn't provided a workable replacement for cases like this one so, even if RequestContext.getEventContext() is deprecated, you unfortunately have no other choice than using it.