So I have a web app with a specific route: http://localhost:28389/MyProjectName/webresources/test/ this returns just a json string:
But when I deploy my app on heroku the web app can't find the same path:
This is my ApplicationConfig:
#javax.ws.rs.ApplicationPath("webresources")
public class ApplicationConfig extends Application {
#Override
public Set<Class<?>> getClasses() {
Set<Class<?>> resources = new java.util.HashSet<>();
addRestResourceClasses(resources);
return resources;
}
private void addRestResourceClasses(Set<Class<?>> resources) {
resources.add(pkgServices.TestService.class);
}
}
And this is my TestService class:
#Path("test")
public class TestService {
public TestService () {
}
#GET
#Produces({MediaType.APPLICATION_JSON})
public Response getTestMsg() throws Exception {
return Response.ok("welcome").build();
}
}
Read Heroku docs. They allocate port number for you and set it to environment variable. You have to use this environment variable in your application to bind http server to this port.
Note, you will still connect to your app at 80th port from browser.
Current problem is Heroku cannot forward request to your server because you do not listen on port which Heroku expects you to listen to.
Related
I have a spring boot application with the main class like this
#SpringBootApplication
#EnableEmailTools
#EnableScheduling
#EnableJpaAuditing
public class SimApplication extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(SimApplication.class);
}
public static void main(String[] args) {
SpringApplication.run(SimApplication.class, args);
}
#Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
#Bean
public JsonViewSupportFactoryBean views() {
return new JsonViewSupportFactoryBean();
}
}
I also have controller for / like this
#Controller
public class WebController {
#GetMapping("/")
public String login(){
return "login";
}
}
Running locally it displays the login page. But when I generate war file and deploy it on Tomcat remote server, it always gives me this error
HTTP Status 404 – Not Found
Type Status Report
Message /
Description The origin server did not find a current representation for the target resource or is not willing to disclose that one exists.
Apache Tomcat/9.0.19
Url for localhost is http://localhost:8080/ this redirects me to Login. Now after deploying to Tomcat on a remote server, whenever I hit http://remoteurl:8080/artifact-id/ it sends me to the error page.
What am I missing? Any help would be appreciated. Thanks
I'm wrote a web application in java using Spring framework. Tested it and deployed to remote tomcat server. After deploying I have message OK - Started application at context path [/proxynator]. But, if I use links like http://109.206.178.66:8080/proxynator/ and http://109.206.178.66:8080/proxynator/proxynator/test I have 404 – Not Found and Description: The origin server did not find a current representation for the target resource or is not willing to disclose that one exists.
In Application I have starter class
#SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
and controller
#RestController
#RequestMapping("/proxynator")
public class MainController {
#Autowired
private ProxyRepo proxyRepo;
#Autowired
private CountryRepo countryRepo;
#RequestMapping("/countries")
#ResponseBody
public List<Country> findCountries() {
return countryRepo.findAll();
}
#RequestMapping("/test")
#ResponseBody
public String testMethod() {
return "HELLO";
}
}
I don't know, why I have this problem, because I setting up my tomcat server right, path to my controller is right and application on server is running.
Any ideas how to solve it?
UPD
I was changed my controller like:
#RestController
public class MainController {
#Autowired
private CountryRepo countryRepo;
#RequestMapping("/countries")
#ResponseBody
public List<Country> findCountries() {
return countryRepo.findAll();
}
#RequestMapping("/")
#ResponseBody
public String testMethod() {
return "HELLO";
}
}
And now my enter point is / that calling testMethod(), but it doesn't working too.
To solve this problem I was extends SpringBootServletInitializer and override configure method`
#Override
override fun configure(application: SpringApplicationBuilder?):
SpringApplicationBuilder {
return super.configure(application)
}
and I changed project structure like in official documentation. And now it works good.
PS
I was rewrite project to Kotlin
In my Spring Boot app that will be running locally the user needs to be able to drag photos into the web page from the operating system and have them displayed. The path on the OS to the files can be set at startup with:
#SpringBootApplication
public class UploaderApplication extends WebMvcConfigurerAdapter {
private String workingDir = "/Users/example/Desktop/";
public static void main(String[] args) {
SpringApplication.run(UploaderApplication.class, args);
}
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/dir/**")
.addResourceLocations("file://" + workingDir)
.setCachePeriod(0);
System.out.println(workingDir);
}
But I need to give the user the ability to update the directory where the files are coming from after the app is running, since the absolute path won't always be known when the application starts. If I send a GET request from the browser with a new working directory path entered by the user, how can I update the registry?
Thank you.
This is how I decided to solve it. A user can fill out a form to update a database with the directories they will be uploading from. When the application loads it gets the list of directories and creates identifiers for them that can then be used in the html.
#SpringBootApplication
public class boxApplication extends WebMvcConfigurerAdapter {
#Autowired private TemplateRepository templateRepository;
public static void main(String[] args) {
SpringApplication.run(boxApplication.class, args);
}
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
Template template = templateRepository.findById(1);
for (UploadDirectory local: template.getLocalDirectories()){
registry.addResourceHandler("/dir" + local.getId() + "/**")
.addResourceLocations("file://" + local.getDirectory())
.setCachePeriod(0);
}
}
}
If I have an interface
public interface TestService {
public String getSomething();
}
and a class
import org.apache.ignite.services.Service;
import org.apache.ignite.services.ServiceContext;
public class TestServiceImpl implements Service, TestService {
#Override
public void init(ServiceContext ctx) throws Exception {
}
#Override
public void execute(ServiceContext ctx) throws Exception {
}
#Override
public void cancel(ServiceContext ctx) {
}
#Override
public String getSomething() {
return "HelloWorld";
}
}
I deploy this service on ignite server nodes with
// Deploy services only on server nodes.
IgniteServices serverSvcs = ignite.services(ignite.cluster().forServers());
// Deploy cluster singleton.
serverSvcs.deployClusterSingleton("TestService", new TestServiceImpl());
And Ignite client node try to get the service
TestService testSvc = mIgnite.services().serviceProxy("TestService", TestService.class, false);
If the client node doesn't contain the "TestServiceImpl" class,
will catch exception with message:
"Failed to find class with given class loader for unmarshalling (make sure same versions of all classes are available on all nodes or enable peer-class-loading)",
Is it necessary that ignite client node must have the class TestServiceImpl ?
This was fixed already and the fix will be released in upcoming Ignite 1.6. In the meantime you can download the nightly build and check if it works for you: http://ignite.apache.org/community/contribute.html#nightly-builds
In a rolling upgrade scenario, I would like to know when there are no active HTTP requests in a given Spring MVC container (starter by Spring Boot, running on Jetty).
That would allow the following flow:
Disable server in reverse proxy
Wait for all requests to finish
Perform upgrade
Is there any way to tell how many requests are currently being handled in Spring MVC or Jetty?
You can get information about the number of active requests using Jetty's StatisticsHandler and JMX.
If you're using Jetty as an embedded container (the recommended approach), you can use an EmbeddedServletContainerCustomizer to set this up:
#Bean
public EmbeddedServletContainerCustomizer containerCustomizer() {
return new EmbeddedServletContainerCustomizer() {
#Override
public void customize(ConfigurableEmbeddedServletContainer container) {
((JettyEmbeddedServletContainerFactory) container)
.addServerCustomizers(new JettyServerCustomizer() {
#Override
public void customize(Server server) {
MBeanContainer mbContainer = new MBeanContainer(
ManagementFactory.getPlatformMBeanServer());
server.addEventListener(mbContainer);
server.addBean(mbContainer);
StatisticsHandler statisticsHandler = new StatisticsHandler();
statisticsHandler.setHandler(server.getHandler());
server.setHandler(statisticsHandler);
}
});
}
};
}
You'll need to add a dependency on org.eclipse.jetty:jetty-jmx to get access to MBeanContainer.
You can try with spring boot actuator. On endpoint /metrics you should have field
"httpsessions.active"
You can think of using AoP. That worked for me. Snippets of code from my project:
public class CommonJoinPointConfig {
#Pointcut("execution(* ru.outofrange.controller.ClaimController.searchClaims(..))")
public void searchClaims() {
}
}
#Aspect
public class CounterAspect {
public CounterAspect() {
}
public CounterAspect(MBeanService mBeanService) {
this.mBeanService = mBeanService;
}
#Before("ru.outofrange.aspect.CommonJoinPointConfig.searchClaims()")
public void beforeMethod() {
counterService.increaseNumberOfRunningRequests();
}
#After("ru.outofrange.aspect.CommonJoinPointConfig.searchClaims()")
public void afterMethod() {
counterService.decreaseNumberOfRunningRequests();
}
}
#Configuration
#ComponentScan(value = {"ru.outofrange.controller", "ru.outofrange.mbean"})
#EnableAspectJAutoProxy(proxyTargetClass=true)
public class RestConfig extends RepositoryRestConfigurerAdapter {
#Autowired
private CounterService counterService;
#Bean
CounterAspect counterAspect(CounterService counterService){
return new CounterAspect(counterService);
}
...
}
Some notes. In the Config you should use #EnableAspectJAutoProxy(proxyTargetClass=true) and this annotation should be added into the Config, which scans package with controller and the service, i.e. the defined aspect, the controller and the service should be in the same Spring context.