How to specify specific request mapping url - spring

sorry i am new to spring boot and trying to learn, i have this code that when i run it will open a json request of my catalog item if i enter any url that is localhost/catalog/(any userid). But i want to narrow it to 1 specific userid how can i do that? for example i dont want any url to work except localhost/catalog/friends or any other item from the list i mention.
Code:
package com.poc.moviecatalog.controller;
import com.poc.moviecatalog.models.CatalogItem;
import java.util.Collections;
import java.util.List;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
#RestController
#RequestMapping("/catalog")
public class MovieController {
#RequestMapping("/{userId}")
public List<CatalogItem> getCatalog(#PathVariable("userId") String userId) {
return Collections.singletonList(
new CatalogItem("friends", "test", 9)
);
}
}

I hope I've understood your question correctly, you don't want to provide a mapping for any user id, but want one specific endpoint /catalog/friends.
#RestController
#RequestMapping("/catalog")
public class FriendsController {
#GetMapping("/friends")
public List<Friends> getFriends() {
....
}
}
then the url would be: http:<HOST>:<PORT>/catalog/friends

Related

#GetMapping method not calles

I am a beginner so please don't be mean.
I have got an html page index.html
And I want the method MainController::getListEmployee to be called.
In this method, I put a System.err to see if the method is called. And I see nothing.
Controller code
package com.cgi.listeemployes.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import com.cgi.listeemployes.model.User;
import com.cgi.listeemployes.repository.UserRepository;
#Controller // This means that this class is a Controller
#RequestMapping(path="/") // This means URL's start with /demo (after Application path)
public class MainController {
#Autowired // This means to get the bean called userRepository
// Which is auto-generated by Spring, we will use it to handle the data
private UserRepository userRepository;
#GetMapping(path="/index.html")
public #ResponseBody Iterable<User> getListEmployee() {
// This returns a JSON or XML with the users
System.err.println("getting ");
return userRepository.findAll();
}
#PostMapping(path="/add") // Map ONLY POST Requests
public #ResponseBody String addNewUser (#RequestParam String name
, #RequestParam String email) {
// #ResponseBody means the returned String is the response, not a view name
// #RequestParam means it is a parameter from the GET or POST request
User n = new User();
n.setName(name);
n.setEmail(email);
userRepository.save(n);
return "Saved";
}
#GetMapping(path="/all")
public #ResponseBody Iterable<User> getAllUsers() {
// This returns a JSON or XML with the users
return userRepository.findAll();
}
}
thanks for your help
When you want to return a html, just return a string with the name of the html file, it could be "Index" (without the .html).
In your #GetMapping(path="/index.html"), you are returning an object instead a html.
If you want to load data from database and render it at your html, then add the attribute "Model model" in your parameters, like this:
#GetMapping(path="/index.html")
public String getListEmployee(Model model) {
List<User> users = userRepository.findAll();
model.addAttribute("yourUsers", users); // this gonna inject the list of users in your html
System.err.println("getting ");
return "Index"
}
Then in your html, you can get the users with ${yourUsers} and do whatever you want.
I saw your project, it is missing the template engine. Template engine is what gonna get the data of your backend and show in your front/html. I added the Thymeleaf template engine into your pom.xml, and it worked. Here is the thymeleaf dependency:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
To work with thymeleaf, you have to put all your html into a new folder called "templates" in the "resources", same level of "static". You cannot use html in the static folder, this folder should have only css, javascripts and assets.

unable to render an array of strings using th:each atrribute in thymeleaf

pls I tried rendering an array of strings with thymeleaf and its showing blank. does any one know the reason for this? The code is shown below:
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
#Controller
public class HomeController {
//public String[] greetings= new String[] {"Hi","Hello","Watsup"};
#RequestMapping("/home")
public String getHomePage(Model model) {
model.addAttribute("msg",new String[]{"Hi","Hello","Watsup"});
//model.addAttribute("msg",new String[]{"Hi","Hello","Watsup"});
return "home";
}
//<h1 th:text=${welcomeMessage}>*Hello Peeps!*</h1>
}```
the html(thymeleaf) is shown below:
<h1 th:each="msg : ${greetings}" th:text=${msg}>Hello,homepage</h1>
You are setting the attribute on the model by the "msg" key. You need to access that instead of greetings.
<h1 th:each="message : ${msg}" th:text=${message}>Hello,homepage</h1>

Where does the filter for Ehcache 3 simple web page caching call the cache?

I am trying to cache a simple web page in Ehcache. Thanks to some help from another SO post I discovered that I need to implement my own filter based on Ehcache 2 code. When I look at the filter I don't understand it. Where does it ever call the cache to return a value? Here is my implementation (quite possibly wrong):
package com.sentiment360.pulse.cache;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.bind.Element;
import org.ehcache.Cache;
import org.ehcache.CacheManager;
import org.ehcache.config.Configuration;
import static org.ehcache.config.builders.CacheManagerBuilder.newCacheManager;
import org.ehcache.core.Ehcache;
import org.ehcache.event.CacheEvent;
import org.ehcache.event.CacheEventListener;
import org.ehcache.xml.XmlConfiguration;
import javax.servlet.http.HttpServletRequest;
public class SimplePageCachingFilter implements CachingFilter {
public static final String DEFAULT_CACHE_NAME = "SimplePageCachingFilter";
private Logger LOG = Logger.getLogger(this.getClass().getName());
private String cacheName="basicCache";
protected String getCacheName() {
if (cacheName != null && cacheName.length() > 0) {
LOG.log(Level.INFO,"Using configured cacheName of {}.", cacheName);
return cacheName;
} else {
LOG.log(Level.INFO,"No cacheName configured. Using default of {}.", DEFAULT_CACHE_NAME);
return DEFAULT_CACHE_NAME;
}
}
protected CacheManager getCacheManager() {
return CacheManager.getInstance();
}
protected String calculateKey(HttpServletRequest httpRequest) {
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append(httpRequest.getMethod()).append(httpRequest.getRequestURI()).append(httpRequest.getQueryString());
String key = stringBuffer.toString();
return key;
}
}
See in the super class.
But you do implements CachingFilter ?! Where is that interface? It does look like you were trying to "copy" the previous Ehcache's SimplePageCachingFilter, right? You would also need to port that abstract super class (and maybe read a little about javax.servlet.Filter, in case these aren't entirely clear...)
Now, you may also want to ping the dev team on the Ehcache Dev Google group about this. They should be able to provide pointers and then help with the implementation. Looks like a good idea for a future pull request! :)

Creating a unique Id and saving it in DB

I am new to Spring REST. I have to achieve the below mentioned requirement using Spring REST. I have to use JPA Repository for DB interaction
I have 2 tables, Application and App_Config. Application table has the following rows:
id(Primary Key), ApplicationId, Status, Source_System. App_config table has the following rows: ApplicationId (foreign key), HeaderText, FooterText. I need to use java UUID to generate a unique id for the application every time a new application sends an HTTP POST request. Based on the ApplicationId generated I need to save the data in App_Config table. There is a possibility that the same application appears twice. In that case I have to retrieve the already generated ApplicationId and load the Header and Footer from App_Config table.
Please advise how to achieve this via POST method. I need to send back only the generated ApplicationId to the user
Partial solution of your problem (the other part is not understood) regarding sending a rest with UUID and the rest api will be server+/generator/uuid
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.util.UUID;
#RestController
#RequestMapping("/generator")
public class UuidGeneratorRestController {
#RequestMapping(value = "/uuid", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<UUID> getUUID() {
UUID generated = UUID.randomUUID();
return new ResponseEntity(generated, HttpStatus.OK);
}
}

How to make localhost app publish to CloudFoundry as is: getting Resource not Available on CF

I have a basic Spring web app (Spring MVC Project) that I want to run on CloudFoundry. I took the default HelloWorld project and added to it. I've installed the CloudFoundry STS extensions, got a server created, publisd my app to the CF site. The 'home' page displays both on my localhost server, and the CF servers. All good. But, when I click on the only link to take me back into the HomeController to a different method/view, I get a 'Resource not available' error on the CF server, though it works perfectly on my localhost (local PC) server.
On my local PC:
The url is: http://localhost:8080/myapp (correct)
The initial page (home.jsp) displays with one link: Property (correct)
Mousing over the link shows this in the status bar: http://localhost:8080/myapp/property (correct)
Clicking takes me to the method mapped to /property and shows the property page (property.jsp). (correct)
On CloudFoundry:
The url is : http://myapp.cloudfoundry.com/ (correct)
The initial page (home.jsp) displays same as on my localhost PC. (correct)
Mousing over link shows this in status bar: http://myapp.cloudfoundry.com/myapp/property (correct, I think).
Clicking gets 'esource not available.
When I go up into the location window and remove myapp from the url, it works.
Below is all the code, but I think it's just some of my own misunderstanding of the two environments, my local PC, and CloudFoundry. Hopefully, someone can educate me on what I'm not knowing here to get the apps to work in both environements--locally, and on CloudFoundry.
Here is the HTML for home.jsp, the initial page
<html>
<head></head>
<body>
Property
</body>
</html>
The HomeController is:
package com.myapp.app;
import java.util.Locale;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
import com.myapp.services.PropertyServicesImpl;
/**
* Handles requests for the application home page.
*/
#Controller
public class HomeController {
private static final String VIEW_HOME = "home";
private static final String VIEW_PROPERTY = "property";
private static final String ACQUISITIONS = "acquisitions";
#Autowired private PropertyServicesImpl propertyServices;
/**
* Shows home view
*/
#RequestMapping(value = "/", method = RequestMethod.GET)
public ModelAndView home(Locale locale, Model model) {
return new ModelAndView(VIEW_HOME);
}
/**
* Shows Property.jsp with jQuery tabs.
*/
#RequestMapping(value = "/property", method = RequestMethod.GET)
public ModelAndView property(Locale locale, Model model) {
return new ModelAndView(VIEW_PROPERTY);
}
}
rather than putting a fixed value in your view it would be best to get the context path for the request and then adding that to the path in your view.
Add the following imports in to your Home controller;
import javax.servlet.http.HttpServletRequest;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
Then in the RequestMapping method get the current request object and create a UrlPathHelper instance and get the base path for the requests context;
HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
UrlPathHelper helper = new UrlPathHelper();
String baseURL = helper.getContextPath(request);
So, when run from vFabric locally, baseURL will be "/myapp" and when run from a Cloud Foundry instance it will be ""
All that is left is to add this to the model and use it in the view;
model.addAttribute("relPath", baseURL);
I tested this with the Spring MVC template project in STS and it worked just fine, my HomeController looked like this;
package com.vmware.mvctest;
import java.text.DateFormat;
import java.util.Date;
import java.util.Locale;
import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.util.UrlPathHelper;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import com.sun.tools.internal.ws.processor.model.Request;
/**
* Handles requests for the application home page.
*/
#Controller
public class HomeController {
private static final Logger logger = LoggerFactory.getLogger(HomeController.class);
/**
* Simply selects the home view to render by returning its name.
*/
#RequestMapping(value = "/home", method = RequestMethod.GET)
public String home(Locale locale, Model model) {
logger.info("Welcome home! the client locale is "+ locale.toString());
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
UrlPathHelper helper = new UrlPathHelper();
Date date = new Date();
DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);
String formattedDate = dateFormat.format(date);
String baseURL = helper.getContextPath(request);
model.addAttribute("serverTime", formattedDate );
model.addAttribute("relPath", baseURL);
return "home";
}
}
and my view looked like this;
<%# page session="false" %>
<html>
<head>
<title>Home</title>
</head>
<body>
<h1>
Hello world! (${relPath})
</h1>
home
<P> The time on the server is ${serverTime}. </P>
</body>
</html>
the context path in CF is {app.name}.cloudfoundry.com and not {app.name}.cloudfoundry.com/{app.name}
Replace in your jsp the Property with Property.

Resources