Getting 404 Not Found for basic spring rest api tutorial - 'hello world' - spring

I am trying to create a rest api web application that can be eventually deployed into a container environment. I downloaded quite a few tutorials from spring.io to other websites as well but each time I use the exact repos I get a 404 error for the simple request.
To simplify it further I reduced it to 2 classes in one package:
project hierarchy
Main class:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
#SpringBootApplication
public class Main {
public static void main(String[] args) {
SpringApplication.run(Main.class, args);
}
}
Controller Class:
#RestController
#RequestMapping("/")
public class RESTController {
private final AtomicLong counter = new AtomicLong();
private static final String template = "Hello, %s!";
/*
* REST API Test Methods
*/
#RequestMapping( "/greeting" )
public String greeting() {
return "It's working...!";
}
And of course the actual request:
http://localhost:8080/test_rest_api/greeting
HTTP Status 404 – Not Found
Type Status Report
Message /test_rest_api/greeting
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/8.5.43
That is running on server by Run As - ; if I select Run as java application and select springboot the following error occurs:
java.lang.IllegalArgumentException: Sources must not be empty at
org.springframework.util.Assert.notEmpty(Assert.java:467)

I finally figured it out and it was a stupid mistake. I added the name of the project as part of the domain of the request url.
http://localhost:8080/test_rest_api/greeting
vs
http://localhost:8080/greeting

Related

Unable to like a tweet using twitter4j but everything else is working fine

Here is the code which is working fine for other methods of twitter variable but only createfavorite is giving this error :
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import twitter4j.TwitterFactory;
import twitter4j.conf.ConfigurationBuilder;
public class TwitterAutoLikerPart1 {
private static Logger logger = LoggerFactory.getLogger(TwitterAutoLikerPart1.class);
public static void main(String[] args) throws Exception {
ConfigurationBuilder cb = new ConfigurationBuilder();
cb.setDebugEnabled(true)
.setOAuthConsumerKey("E")
.setOAuthConsumerSecret("F")
.setOAuthAccessToken("G")
.setOAuthAccessTokenSecret("H");
TwitterFactory tf = new TwitterFactory(cb.build());
var twitter = tf.getInstance();
long tweetid=tweetid;
logger.info("Tweet id is "+tweetid);
logger.info(twitter.createFavorite(tweetid).getText());
/*
Whereas this is working
for(var x:twitter.getFavorites())
logger.info(x.toString());*/
}
}
Here's the logs for your referrence :
Exception in thread "main" 401:Authentication credentials (https://dev.twitter.com/pages/auth) were missing or incorrect. Ensure that you have set valid consumer key/secret, access token/secret, and the system clock is in sync.
{"request":"\/1.1\/favorites\/create.json","error":"Read-only application cannot POST."}
Relevant discussions can be found on the Internet at:
http://www.google.co.jp/search?q=038fb9e8 or
http://www.google.co.jp/search?q=480cbeca
TwitterException{exceptionCode=[038fb9e8-480cbeca], statusCode=401, message=null, code=-1, retryAfter=-1, rateLimitStatus=null, version=4.0.7}
at twitter4j.HttpClientImpl.handleRequest(HttpClientImpl.java:170)
at twitter4j.HttpClientBase.request(HttpClientBase.java:57)
at twitter4j.HttpClientBase.post(HttpClientBase.java:86)
at twitter4j.TwitterImpl.post(TwitterImpl.java:2102)
at twitter4j.TwitterImpl.createFavorite(TwitterImpl.java:1241)
at com.twiiterapi.mt.twitterapi.TwitterAutoLikerPart1.main(TwitterAutoLikerPart1.java:30)
Process finished with exit code 1
Kindly let me know where am I faultering.
Edit: So, the issue was app permission as pointed by the kind person Mr Andy Piper . I changed the permission and it started working like a charm .

Spring and Azure function

Does Spring work with Azure functions?
For example: Rest API that the code inside uses "Autowired" annotation (After running mvn azure-functions:run I've got NullPointerException on "myScriptService").
import java.util.*;
import com.microsoft.azure.serverless.functions.annotation.*;
import com.microsoft.azure.serverless.functions.*;
import com.company.ScriptService;
import org.springframework.beans.factory.annotation.Autowired;
/**
* Azure Functions with HTTP Trigger.
*/
public class Function {
#Autowired
ScriptService myScriptService;
/**
* This function listens at endpoint "/api/hello". Two ways to invoke it using "curl" command in bash:
* 1. curl -d "HTTP Body" {your host}/api/hello
* 2. curl {your host}/api/hello?name=HTTP%20Query
*/
#FunctionName("myhello")
public HttpResponseMessage<String> hello(
#HttpTrigger(name = "req",
methods = "post",
authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Optional<String>> request,
final ExecutionContext context) {
context.getLogger().info("Java HTTP trigger processed a request.");
// Parse query parameter
String query = request.getQueryParameters().get("name");
String name = request.getBody().orElse(query);
if (name == null) {
return request.createResponse(400, "Please pass a name on the query string or in the request body");
} else {
return request.createResponse(200, "Hello, " + name + ", myScriptService.isEnabled(): " + myScriptService.isEnabled());
}
}
}
As some asked for a solution in the comments above, I'm assuming that this problem might be of relevance for other users, too.
So I think Spring Cloud Function is the magic word here: besides some other points (see the project page for details), it aims to enable Spring Boot features (like dependency injection, what you're looking for) on serverless providers (besides Azure Functions, also AWS Lambda and Apache OpenWhisk are supported).
So you have to make some modifications to your project:
Add the spring-cloud-function-adapter-azure dependency:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-function-adapter-azure</artifactId>
<version>2.0.1.RELEASE</version>
</dependency>
Your handler class needs some additional code:
Add the #SpringBootApplication annotation
Add the main() method known from Spring Boot applications
Make sure that Spring can find your ScriptService class e. g. by using the #ComponentScan annotation
It should look like this:
#SpringBootApplication
#ComponentScan(basePackages = { "package.of.scriptservice" })
public class Function {
#Autowired
ScriptService myScriptService;
#FunctionName("myhello")
public HttpResponseMessage<String> hello(
#HttpTrigger(name = "req", methods = "post", authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Optional<String>> request,
final ExecutionContext context) {
// Your code here
}
public static void main(String[] args) {
SpringApplication.run(DemoFunctionHandler.class, args);
}
}
You can find a full example here and here
It looks like that there are a lot of changes between spring cloud v1 and v2. Have a quick look at this blog post: https://spring.io/blog/2018/09/25/spring-cloud-function-2-0-and-azure-functions
If you build your project like the example, spring will create the spring boot context when the azure function is called (and you call handleRequest). But the spring context is not available before this.
Do you add your package to scan for spring cloud function ?
spring.cloud.function.scan.packages="yourPackage"
It is to add in your application.properties

Downloading huge files from spring boot REST service

I'm currently writing a REST service with spring boot which should provide a file download, i. e. a client application can download files from the service. A file can be several gigabytes big (sometimes bigger than the main memory), i. e. loading the file into the main memory is not an option. So I need some kind of streaming meachanism when sending a file to the client.
One promising solution on the net (taken from here):
#RestController
// ...
#RequestMapping(value = "/files/{file_name}", method = RequestMethod.GET)
#ResponseBody
public FileSystemResource getFile(#PathVariable("file_name") String fileName) {
return new FileSystemResource(myService.getFileFor(fileName));
}
But it does not work. I get:
java.lang.IllegalStateException: Unsupported resource class: class org.springframework.core.io.FileSystemResource
at org.springframework.http.converter.ResourceHttpMessageConverter.readInternal(ResourceHttpMessageConverter.java:100)
I researched but don't know what is causing the issue. I tried other approaches (e. g. Downloading a file from spring controllers) but I get the same error. Does anyone know why the solutions seem to work for others but not for me?
Edit: Here is where I call the REST service (jUnit test case):
#RunWith(SpringRunner.class)
#SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class DownloadTest {
#LocalServerPort
private int port;
private RestTemplate template;
private String requestPath;
#Before
public void setUp() throws Exception {
template = new RestTemplate();
requestPath = "http://localhost:" + port + "/files/download";
}
#Test
public void test() {
Resource FileSystemResource =
template.getForObject(requestPath, FileSystemResource.class);
}
}
The code of the RestController is working as expected with a small memory footprint (the file is never loaded to the main memory completely).
The client code that works for me (also with a small memory footprint) can be found here.
i fixed the java.lang.IllegalStateException: Unsupported resource error changing this
Resource FileSystemResource =
template.getForObject(requestPath, FileSystemResource.class);
for this
Resource FileSystemResource =
template.getForObject(requestPath, Resource .class);

Don't have access to Spring boot controller, but have access to index.html

I have a Spring Boot project, what I deployed on remote server. When I call http://109.206.178.66:8080/proxynator/ - I can see an index.html, but when I call rest controller by url http://109.206.178.66:8080/proxynator/countries - I have an error 404 whith
Description: The origin server did not find a current representation for the target resource or is not willing to disclose that one exists.
It's strangely, because when I start this project on my local machine, all working right. Project structure is:
Line from catalina.out file:
SEVERE [http-nio-8080-exec-19] org.apache.tomcat.util.descriptor.web.WebXmlParser.parseWebXml Parse error in application web.xml file at [file:/opt/tomcat/webapps/proxynator/WEB-INF/web.
My controller:
#RestController
class MainController(val proxyRepo: ProxyRepo, val countryRepo:
CountryRepo) {
#GetMapping("/countries")
fun findCountries(): List<Country> = countryRepo.findAll()
#GetMapping("/proxies")
#ResponseBody
fun findProxies(#RequestParam countryid: Int): List<Proxy> =
proxyRepo.findAllByCountryid(countryid)
}
UPD
I added configuration class on the root package
#Configuration
open class RestConfiguration {
#Bean
open fun mainController():MainController
= MainController()
}
But it does not working. I don't understand, why I can see index.html by irl http://109.206.178.66:8080/proxynator/, but can't get access to my controllers. When I package my project I have some files:
Any advice?
your api access url is wrong access using http://109.206.178.66:8080/countries this is the correct path for your rest mapping, not http://109.206.178.66:8080/proxynator/countries
To solve this problem I was edit my Application class.
#SpringBootApplication
#EnableAutoConfiguration
open class Application: SpringBootServletInitializer(){
#Override
override fun configure(application: SpringApplicationBuilder?):
SpringApplicationBuilder {
return super.configure(application)
}
}
fun main(args: Array<String>) {
SpringApplication.run(Application::class.java, *args)
}
I was override configure method, and all is working!
Hope it will save time for anybody!

Running cucumber-groovy features against a spring boot api

I've been attempting to get cucumber-groovy working with spring-boot, but it's not been going well. I get the error org.springframework.web.client.ResourceAccessException: I/O error on GET request for "http://localhost:8080/applicants": Connection refused; nested exception is java.net.ConnectException: Connection refused which seems to indicate that it's hitting the endpoint, but that the service isn't running.
I've read that I need to have a cucumber.xml file, but my project is not using any xml config, it's all annotations, so instead I've got this:
package support
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
#Configuration
#ComponentScan(basePackages = "com.base.package")
public class CucumberConfiguration {}
I've added it to the World, but this seems to be the wrong way of doing things (i.e. I don't know how to add an annotation on groovy step defs).
package support
import com.thing.app.Application
import org.junit.runner.RunWith
import org.springframework.boot.test.SpringApplicationContextLoader
import org.springframework.boot.test.WebIntegrationTest
import org.springframework.test.context.ContextConfiguration
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner
import org.springframework.test.context.web.WebAppConfiguration
import static cucumber.api.groovy.Hooks.*
//#RunWith(SpringJUnit4ClassRunner)
//#ContextConfiguration(classes = Application, loader = SpringApplicationContextLoader)
//#WebAppConfiguration
//#WebIntegrationTest
#ContextConfiguration(classes = CucumberConfiguration)
public class AbstractTest {
}
World() {
new AbstractTest()
}
Before() {}
After() {}
I left in my other annotations to kind of show what I've done so far. None of it has worked.
I've also tried setting up an AbstractDefs class as seen here https://github.com/jakehschwartz/spring-boot-cucumber-example/tree/master/src/test/java/demo, but that also hasn't worked, mostly because I'm not using the cucumber-java style of things, but instead the cucumber-groovy style, which doesn't use step definition classes.
Edit: Just discovered I was doing things wrong by having an env.groovy, I'm used to the ruby cucumber, so I'm having trouble finding all the little problems. Still am having the same issue though, I don't know how to execute in a Spring context.
You can instantiate Spring test context with io.cucumber.spring.SpringFactory and register adapter in World to allow groovy script has access to Spring beans:
env.groovy:
#ContextConfiguration(classes = TestConfiguration, loader = SpringBootContextLoader)
class CucumberContextConfiguration {
}
//adapter bypassing World properties to Spring context
class SpringFactoryWorldAdapter {
private final SpringFactory factory;
SpringFactoryWorldAdapter(SpringFactory factory) {
this.factory = factory;
}
#Override
Object getProperty(String s) {
return factory.testContextManager.getContext().getBean(s);
}
}
def factory; //Keep state to prevent repeated context initialization
World { args ->
if (factory == null) {
factory = new SpringFactory()
factory.addClass(CucumberContextConfiguration)
factory.start()
}
new SpringFactoryWorldAdapter(factory)
}

Resources