I wrote an MVC application and I wanted to create an option of editing the photo. I serve image as div which background is the image and div has click listener that post suitable requests to application.
Then on the application side works another program that edits photo as client asked and saves it and override a old one. The problem is that until I redeploy an application it serves an old file even though it has changed. I think the problem is because I serve photos from resources folder and it’s cold “static resources” so I should not change it. Another think is that IntelliJ is not refreshing the photo. Do you have any idea what I do wrong or know how should I serve that photos in better way?
So as Prashant mentioned in comment all I had to do was setCachePeriod to 0.
EDIT:
Following are two ways of doing it:
Either set in the application.properties file:
spring.resources.cache-period = 0
Or, add in the ResourceHandler:
#Component
public class WebConfigurations extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registy.addResourceHandler("/static/**")
.addResourceLocations("classpath:/static/")
.setCachePeriod(0);
}
}
Related
So I have been trying hard to get a simple app to run with populating an HTML file through a controller without using a template engine.
I thought I would take some time to post about my findings related to the subject above. See answer below
Soo the question here is How to access HTML files through a controller in Spring boot without a template engine?
This is a very simplistic answer to a simple issue, this is not meant to scale and does not take into account the entirety of your project
Please keep in mind this is not the norm in a business environment but it was really bothering me how I cannot get a simple HTML to populate from a controller without using a template engine. I got it to work with thymeleaf dependency but I wanted to just get it to work as bare bones as possible. I read a lot of posts with ViewResolver Config classes or things a like but nothing worked. It would conflict with the internal resolvers of Spring boot.
Simple answer is once spring boot is initialized...all your static files must be in resources/static/
Templates folder is specific to use for Thymeleaf, based on my findings and it wont work if you just put it in the resource folders.
With your files in resources/static/ you can access it by going to localhost:8080/yourfilename.html
But if you want to access it through a controller you create a controller with the following:
#Controller
public class IndexController {
#RequestMapping("/")
public String getIndex(){
return " index.html";
}
}
If you want to remove the .html in your return value then you must add the following to your application.properties file
spring.mvc.view.suffix=.html
Then you can use the following
#Controller
public class IndexController {
#RequestMapping("/")
public String getIndex(){
return " index";
}
}
Once again this is a simple research I did on my own just to get it to work.
My Issue:
This is my first time doing tests for Vaadin UI and I am also fairly new to Unit tests in general. My issue is that I can't do anything with my UI components Views because there is no VaadinSession which handles the UI beans. A VaadinSession is never created when using #SpringBootTest. I was able to create tests for my backend since Spring handles those beans, but I can't seem to figure out a way to get Vaadin to start up a session so I can then access the session and do different integration and unit tests.
What I've Tried
TestBench: The Vaadin testbench seemed like a very good option but the issue that I faced was that it doesn't seem to open a VaadinSession whenever I open a ChromeDriver() that goes to the website on my localhost.
Karibu Library: This library seemed like a very good option, but there was one issue, which was that it opens individual UI components that are instantiated, however a couple of my UI Components Classes, uses dependency injection to inject backend services. I cannot instantiate these classes because of the dependeny injection.
The UI Component that I need to access through the VaadinSession.
#Component
#UIScope
#CssImport("./styles/current-info-styles.css")
public class CurrentDayView extends VerticalLayout implements Updatable {
private static final long serialVersionUID = 1L;
//Some code here
#Autowired
public CurrentDayView(NowcastWeatherService nowcastWeatherService, GeoLocationService geoLocationService) {
this.nowcastWeatherService = nowcastWeatherService;
this.geoLocationService = geoLocationService;
//Some Code here
}
//Some code here
My Testbench approach
#RunWith(SpringRunner.class)
#SpringBootTest
public class CurrentDayViewTest extends TestBenchTestCase {
#Test
public void fakeTest() {
Assert.assertTrue(true);
}
#Before
public void startUp() {
System.setProperty("webdriver.chrome.driver", "src/main/resources/drivers/chromedriver.exe");
setDriver(new ChromeDriver());
getDriver().get("http://localhost:8080/");
populateViewWithInformation();
}
#After
public void tearDown() {
getDriver().quit();
}
private void populateViewWithInformation() {
CurrentDayView currentDayView = (CurrentDayView) VaadinSession.getCurrent().getAttribute("current-day-view");
//This is where I get an error because VaadinSession.getCurrent() is null
}
My Final Question:
Does anyone have any idea on how I could have a VaadinSession created or atleast get spring to keep track for Vaadin UI components? If this wasn't clear then please feel free to ask more clarifications relating to my question.
I suggest you give Karibu another shot, it's great for doing these kinds of tests that don't need the app to be running.
Take a look at the Karibu V14 Spring demo project. Pay attention to what Karibu dependency is used. The ApplicationTest#listOrders test contains navigation to a view with autowired dependencies.
The issue with your TestBench test is that TestBench is used to test against a running application, and the tests run in an entirely different process than the actual application.
So when you open the page with the driver, a Vaadin session is created in the application, but you will not be able to access it in your tests, nor will you be able to access any UI state or views. What it allows you to do, however, is to interact with the application as you would do through the browser (clicking buttons, filling in text fields etc.), and to check that the state in the browser is correct, without knowing anything about the server's internal state.
Generally speaking, when you're writing integration tests with TestBench (which is based on Selenium), what you're doing is directing the browser. You're writing Java code, yes, and the code may even be in the same project as your Vaadin UI code, but it can be executed against any URL and what you're interacting with is the browser's DOM. You're describing what the end-user would do: click a button, write some text in an input field, choose an option from a radio button group. The server-side is a black box. After all, if I submit a post on StackOverflow, I can't check if it gets stored in a database - all I can do is look at what I see after I press the "Post your answer" button. If you really want to nitpick, it doesn't even need to be a Vaadin application you're testing with TestBench, as long as the application behaves like one in the browser.
Secondly, you shouldn't store any Components in the VaadinSession. If you open a Vaadin application in multiple browser tabs, each of those tabs will share the same VaadinSession. A single Component instance should only be used inside one browser tab, where the root component is the current UI.
I have two applications :
one spriig boot config server
the another one a spring boot config client
The client side have to use a file named certificate.json.
I want to store this file in the server side so another microprogram and my client programm who need it can retrieve it from the server side.
I try that :
copy the file certificate.json to classpath:/config
add this line to the application.properties :
certificate.location: classpath:config/certificate.json
call the value from client programm by :
#Value("${certificate.location}")
private String certificateLocation;
But the value of certificateLocation is classpath:config/certificate.json. The value I want is the file location like : /home/user/project/scr/main/resources/config/certificate.json.
Or, are there a way to directly retrieve my file by URI, for example locahost:8889/... (8889 is my config server port).
EDIT 1:
I cannot use absolute path from the server because I'm not the one who run it.
Thank you in advance.
I'd do
#Value("${certificate.location}") private Resource certificateLocation;
that way, your location is already a Resource that you can load, call getURI(), getFile().getAbsolutePath() etc. Since your value is prefixed with classpath:, you would have a ClassPathResource instance, which you can use for lot of things.
The classpath is just a protocol part of the URL. You can use file or any other supported protocol. For example, file://home/user/project/scr/main/resources/config/certificate.json.
Try this url
spring.cloud.config.server.native.searchLocations
=file://${user.home}/CentralRepo/
SPRING_PROFILES_ACTIVE=native
I am also get this way using microservice
OP you need to create a web service and return certificate.json as the response. Then you can send and receive data by sending a GET or POST request to a URI like https://12.12.12.12:8080/getCertificate. Please see:
https://spring.io/guides/gs/rest-service/
As a side note, you should never expose your inner files to the internet because it's very unsecure and opens you up to pirating and hacking.
What I would do in this case is
Add configuration for static folder
#SpringBootApplication public class DemoStaticresourceApplication extends WebMvcConfigurerAdapter {
public static void main(String[] args) {
SpringApplication.run(DemoStaticresourceApplication.class, args);
}
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/files/**").addResourceLocations("file:/fileFolder/")
.setCachePeriod(0);
}
}
Place certificate.json in fileFolder and try http://localhost:8080/files/certificate.json and it will be served directly from file system for you.
And now every file you add in this folder will be served only if called using /files/ path
I have a Spring boot application and I have two completely independent angular projects.
One project for the end user and another project for the admin.
For business reasons, I am forced to have both of them as two different projects. I want both these projects to be packaged into the same WAR and when the user hits the URL for the end user, the end user angular application should be loaded and when the admin URL is accessed, the admin angular project should be loaded.
I know that Spring boot loads the angular project from /public or /static directories. However, since in my case, I have two different projects, I cant put them under the same folder since both of them have many file names in common including index.html.
So far, I have done the following:
Created two different folders under "public" as "enduser" and
"manage".
Created a controller which has two methods :
#Controller
public class SampleController {
#RequestMapping(method = RequestMethod.GET, produces = "text/html", value
= "/enduser")
public String enduser() {
return "/enduser/index.html";
}
#RequestMapping(method = RequestMethod.GET, produces = "text/html", value
= "/admin")
public String admin() {
return "/admin/index.html";
}
}
However, when I do like this only the index.html file is loaded and the other components are not loaded(by which I mean the entire angular project is not loaded). So the dependent views and styles etc are not loaded.
Does anybody have an idea on how to handle the above scenario? Thanks.
Just posting the solution below it might help somebody else.
I am using two different folder where I am placing the contents of dist folder from angular source code.
I have two different angular based applications admin and public.
Locations in spring app where I am placing the compiled angular code is as:
/src/main/resources/admin-app/*
(admin-index.html and other static
files from admin angluar project)
/src/main/resources/static/*
(index.html and other static files from public angluar project)
Spring boot config
#EnableAutoConfiguration
public class AddCustomLocations {
#Bean
WebMvcConfigurer configurer () {
return new WebMvcConfigurerAdapter() {
#Override
public void addResourceHandlers (ResourceHandlerRegistry registry) {
registry.addResourceHandler("/pages/**").
addResourceLocations("classpath:/admin-app/");
}
};
}
That's it now when you will hit http://localhost:8080. It will load the public angular app.
And when you will hit
Now when I am trying to open http://localhost:8080/pages/admin-index.html
It will load the admin angular app.
The magic is all files inside static folder will work by default but if we want to create another folder for placing our static files. We will have to notify the spring boot app.
You can also create a sub folder inside the static folder.
public & admin-app
You will have to hit the url like this
localhost:8080/public/index.html
localhost:8080/public/admin-index.html
You will not need to create the above spring configuration for this.
Resolved it the following way:
Created an MVC controller, added two different methods for each URL pattern.Copied the dist files of each project into a a separate folder under static folder.Added a different tag to each project.This way your angular project wont work on grunt serve.So you will have to set url as empty when you run on grunt serve and set it to a value only when you run for build.
I want to access static files, which are outside my web application in a known directory. I have read many options over the www, but I have still some questions about this.
Basically I want to declare a context for the defaultservlet of my application server. In my case I'm trying with the Tapestry Tutorial, which is a Maven based project and imported to eclipse.
The idea was to create a httpservlet, which gets the file from the location. Do someone of you know where I can grab an example of such a servlet and how I can call him? I know that the servlet must be probably declared as a service, because all pages of the application need to access the files, but I could also be mistaken and it is enough to import it, let say, in the layout page (All pages use the layout.tml file). I basically don't have any clue how to do it with a servlet. Can someone show me the light?
Tank you very much.
Another simpler solution is to create a page which returns a stream response
public class StaticFile {
StreamResponse onActivate(String fileName) {
return new StaticFileStreamResponse(fileName);
}
}
Then in another component / page
#Inject ComponentResources resources;
public Link getStaticFileLink() {
return resources.createPageRenderLinkWithContext("StaticFile", "path/to/myFile.jpg");
}
TML
<img src="${StaticFileLink}" />
But then you won't take advantage of tapestry's 304 NOT_MODIFIED response as in my other solution.
The tapestry way of doing this is by contributing an AssetRequestHandler and an AssetFactory.
AppModule.java
public static void contributeAssetDispatcher(
MappedConfiguration<String, AssetRequestHandler> config,
ResourceStreamer streamer)
{
config.add("staticfile", new StaticFileAssetRequestHandler(streamer));
}
public void contributeAssetSource(
MappedConfiguration<String, AssetFactory> config)
{
config.add("staticfile", new StaticFileAssetFactory());
}
Then in your tml you can use
<img src="${asset:staticfile:path/to/myFile.jpg}" />
Take a look at the ContextAssetRequestHandler, ClasspathAssetRequestHandler, ContextAssetFactory and ClasspathAssetFactory for inspiration.
Be careful not to open up a security hole where a hacker can access any file on your server by passing file paths prefixed with ../../