Rest Service URL giving Not working and giving Error - glassfish

So I have been trying to make this rest service work and I have been on it for a few days but just can't get the URL to work no matter what I try. I first tried every suggestion the internet gave regarding to the web.xml file. Once I realised it's a last cause I tried the JAXRSConfiguration class with an '#ApplicationPath("/")' annotation.
So here is the JAXRS Class:
#ApplicationPath("api")
public class JAXRSConfiguration extends Application {
public JAXRSConfiguration() {
BeanConfig beanConfig = new BeanConfig();
beanConfig.setVersion("2.0.0");
beanConfig.setSchemes(new String[]{"http"});
beanConfig.setHost("localhost:8080");
beanConfig.setBasePath("/MyApp/api");
beanConfig.setResourcePackage("rest");
beanConfig.setPrettyPrint(true);
beanConfig.setScan();
getClasses();
}
#Override
public Set<Class<?>> getClasses() {
final Set<Class<?>> classes = new HashSet<>();
classes.add(UserResource.class);
classes.add(MessageService.class);
return classes;
}
}
And here is one of my resource files:
#Path("/users")
public class UserResource {
private UserService service = new UserService();
#DELETE
#Path("/{userId}")
public void deleteMessage(#PathParam("userId") int id) {
service.deleteUser(id);
}
#POST
#Path("/{userId}/follow/{userToFollowId}")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public void followUser(#PathParam("userToFollowId") int userId, int userToFollowId) {
service.followUser(userId, userToFollowId);
}
#POST
#Path("/register")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public User registerUser(User user) {
return service.registerUser(user);
}
#PUT
#Path("/{userId}")
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.TEXT_PLAIN)
public User updateUser(User user) {
return service.updateUser(user);
}
#GET
#Path("/{userId}")
#Consumes(MediaType.TEXT_PLAIN)
#Produces(MediaType.APPLICATION_XML)
public User getUser(#PathParam("userId") int id) {
return service.getUser(id);
}
#GET
#Produces(MediaType.APPLICATION_XML)
public List<User> getAllUsers() {
return service.getAllUsers();
}
#GET
#Path("/{userId}/followers")
#Consumes(MediaType.TEXT_PLAIN)
#Produces(MediaType.APPLICATION_XML)
public List<User> getFollowers(#PathParam("userId") int id) {
return service.getFollowers(id);
}
#GET
#Path("/{userId}/followings")
#Consumes(MediaType.TEXT_PLAIN)
#Produces(MediaType.APPLICATION_XML)
public List<User> getFollowings(#PathParam("userId") int id) {
return service.getFollowings(id);
}
#GET
#Path("/{userId}/kweets")
#Consumes(MediaType.TEXT_PLAIN)
#Produces(MediaType.APPLICATION_XML)
public List<Kweet> getKweets(#PathParam("userId") String username) {
return service.getKweets(username);
}
#GET
#Path("/{userId}/timeline")
#Consumes(MediaType.TEXT_PLAIN)
#Produces(MediaType.APPLICATION_XML)
public List<Kweet> loadTimeline(#PathParam("userId") int id) {
return service.loadTimeline(id);
}
}
The Error I'm getting is:
HTTP Status 404 - Not Found
type Status report
messageNot Found
descriptionThe requested resource is not available.
GlassFish Server Open Source Edition 5.0

Open your IDEA module settings, and look under Artifacts. You'll find something like this
The highlighted name of the war/exploded artifact is going to be your server context path.
In my case it would become
http://localhost:8080/kwetter-0.0.1
You should replace it with yours.
Now, you need to add the #ApplicationPath path, which is /api. So it becomes
http://localhost:8080/kwetter-0.0.1/api
Now, you need to add the REST service #Path, which is /users. So it becomes
http://localhost:8080/kwetter-0.0.1/api/users
An example:
GET http://localhost:8080/kwetter-0.0.1/api/users/{userId}/followers
Be sure you don't have this checked, under Run/Debug configuration.

Related

Adding path to base url in Spring Rest Docs?

I have following configuration to use with Rest Docs:
webTestClient = buildWebClient().mutate()
.filter(documentationConfiguration(restDocumentation))
.baseUrl("https://api.my-domain.com/")
.build()
In my case I use path prefix to my service - service/foo since I use k8s ingress and my service is served on path offset.
Is there a way to insert such prefix without modifying production code?
Related documentation fragment:
https://docs.spring.io/spring-restdocs/docs/current/reference/html5/#configuration-uris-webtestclient
To document another URI than the one called to generate documentation, you have to write your own OperationPreprocessor. There are some predefined like Preprocessors.modifyUris but it does not allow to modify the request path.
Check below the webTestClient configuration and the URIUpdaterOperationRequest class. Code is available on GitHub: https://github.com/Query-Interface/SO-Answers/blob/master/java/spring/rest-docs-modify-uripath/src/test/java/com/example/demo/DemoApplicationTests.java
public void init() throws Exception {
final URIUpdaterPreprocessor preprocessor = new URIUpdaterPreprocessor();
webTestClient = webTestClient.mutate()
.filter((documentationConfiguration(this.restDocumentation)
.operationPreprocessors()
.withRequestDefaults(preprocessor)
.withResponseDefaults(prettyPrint()))
)
.build();
}
private static final class URIUpdaterPreprocessor
implements OperationPreprocessor {
#Override
public OperationRequest preprocess(OperationRequest request) {
return new URIUpdaterOperationRequest(request);
}
#Override
public OperationResponse preprocess(OperationResponse response) {
return response;
}
}
private static final class URIUpdaterOperationRequest
implements OperationRequest {
private OperationRequest delegate;
public URIUpdaterOperationRequest(OperationRequest request) {
delegate = request;
}
public byte[] getContent() {
return delegate.getContent();
}
public String getContentAsString() {
return delegate.getContentAsString();
}
public HttpHeaders getHeaders() {
return delegate.getHeaders();
}
public HttpMethod getMethod() {
return delegate.getMethod();
}
public Parameters getParameters() {
return delegate.getParameters();
}
public Collection<OperationRequestPart> getParts() {
return delegate.getParts();
}
public URI getUri() {
URI sourceUri = delegate.getUri();
UriComponentsBuilder builder = UriComponentsBuilder.fromUri(sourceUri);
return builder
.host(sourceUri.getHost())
.replacePath("/service/foo"+sourceUri.getPath())
.build().toUri();
}
public Collection<RequestCookie> getCookies() {
return delegate.getCookies();
}
}
I think another possibilty is to update the mustache templates so as to add a prefix before all request path references. The default templates are located here on github.

.NET CORE 2.0 Unable to resolve service for type while attempting to activate

I have a IDataRepository.cs file that contains an interface and its implementation like so:
public interface IDataRepository<TEntity, U> where TEntity : class
{
IEnumerable<TEntity> GetAll();
TEntity Get(U id);
TEntity GetByString(string stringValue);
long Add(TEntity b);
long Update(U id, TEntity b);
long Delete(U id);
}
I have another class TokenManager.cs that implements IDataRepository Interface:
public class TokenManager : IDataRepository<Token, long>
{
ApplicationContext ctx;
public TokenManager(ApplicationContext c)
{
ctx = c;
}
//Get the Token Information by ID
public Token Get(long id)
{
var token = ctx.Token.FirstOrDefault(b => b.TokenId == id);
return token;
}
public IEnumerable<Token> GetAll()
{
var token = ctx.Token.ToList();
return token;
}
//Get the Token Information by ID
public Token GetByString(string clientType)
{
var token = ctx.Token.FirstOrDefault(b => b.TokenClientType == clientType);
return token;
}
public long Add(Token token)
{
ctx.Token.Add(token);
long tokenID = ctx.SaveChanges();
return tokenID;
}
}
and finally, I have a controller to put all things together, my controller files looks like this:
[Route("api/[controller]")]
public class TokenController : Controller
{
private IDataRepository<Token, long> _iRepo;
public TokenController(IDataRepository<Token, long> repo)
{
_iRepo = repo;
}
// GET: api/values
[HttpGet]
public IEnumerable<Token> Get()
{
return _iRepo.GetAll();
}
// GET api/values/produccion
[HttpGet("{stringValue}")]
public Token Get(string stringValue)
{
return _iRepo.GetByString(stringValue);
}
}
But the problem is that every time I try to access some method from my API, for example using postman I get the error:
InvalidOperationException: Unable to resolve service for type FECR_API.Models.Repository.IDataRepository`2[FECR_API.Models.Token,System.Int64] while attempting to activate;FECR_API.Controllers.TokenController
I tried using something like this inside ConfigureServices, but get a conversion error
services.AddScoped<IDataRepository, TokenManager>();
Any idea what I'm doing wrong?
Please ensure you register dependencies in DI container inside Startup.cs
public class Startup
{
...
public void ConfigureServices(IServiceCollection services)
{
...
services.AddScoped<IDataRepository<Token, long>, TokenManager>();
...
}
}

Spring TestRestTemplate authentication

I am trying to build Spring Boot test to test rest API, so that I can get Principal from the request and use that to identify the user.
Server returns
{"timestamp":1502014507361,"status":403,"error":"Forbidden","message":"Access
Denied","path":"/hello"}
What am I missing here?
#RunWith(SpringRunner.class)
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class RestTemplateTest {
#Autowired
TestRestTemplate testRestTemplate;
#Test
public void testit() {
testRestTemplate.withBasicAuth("user", "password");
String responsePayload = testRestTemplate.getForObject("/hello", String.class);
}
#RestController
public class GreetingController {
#RequestMapping("/hello")
public String heipat(Principal principal) {
String string = "hello there";
return string;
}
#Configuration
#EnableWebSecurity
static class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
public void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.authorizeRequests().anyRequest().hasRole("USER");
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
authenticationManagerBuilder.inMemoryAuthentication()
.withUser("user").password("password").roles("USER");
}
}
You need to be authenticated first. like requesting a /login API.
Also you need to make the login API accessible by everyone by doing this:
http.csrf().disable().authorizeRequests()
.antMatchers("/login").permitAll()
When you includes WebSecurityConfig you will have basic usernamerAndPassowrd authentication.

Is it possible to use one generic/abstract service in ServiceStack?

I am developing a (hopefully) RESTful API using ServiceStack.
I noticed that most of my services look the same, for example, a GET method will look something like this:
try
{
Validate();
GetData();
return Response();
}
catch (Exception)
{
//TODO: Log the exception
throw; //rethrow
}
lets say I got 20 resources, 20 request DTOs, so I got about 20 services of the same template more or less...
I tried to make a generic or abstract Service so I can create inheriting services which just implement the relevant behavior but I got stuck because the request DTOs weren't as needed for serialization.
Is there any way to do it?
EDIT:
an Example for what I'm trying to do:
public abstract class MyService<TResponse,TRequest> : Service
{
protected abstract TResponse InnerGet();
protected abstract void InnerDelete();
public TResponse Get(TRequest request)
{
//General Code Here.
TResponse response = InnerGet();
//General Code Here.
return response;
}
public void Delete(TRequest request)
{
//General Code Here.
InnerDelete();
//General Code Here.
}
}
public class AccountService : MyService<Accounts, Account>
{
protected override Accounts InnerGet()
{
throw new NotImplementedException();//Get the data from BL
}
protected override void InnerDelete()
{
throw new NotImplementedException();
}
}
To do this in the New API we've introduced the concept of a IServiceRunner that decouples the execution of your service from the implementation of it.
To add your own Service Hooks you just need to override the default Service Runner in your AppHost from its default implementation:
public virtual IServiceRunner<TRequest> CreateServiceRunner<TRequest>(ActionContext actionContext)
{
return new ServiceRunner<TRequest>(this, actionContext); //Cached per Service Action
}
With your own:
public override IServiceRunner<TRequest> CreateServiceRunner<TRequest>(ActionContext actionContext)
{
return new MyServiceRunner<TRequest>(this, actionContext); //Cached per Service Action
}
Where MyServiceRunner is just a custom class implementing the custom hooks you're interested in, e.g:
public class MyServiceRunner<T> : ServiceRunner<T> {
public override void OnBeforeExecute(IRequestContext requestContext, TRequest request) {
// Called just before any Action is executed
}
public override object OnAfterExecute(IRequestContext requestContext, object response) {
// Called just after any Action is executed, you can modify the response returned here as well
}
public override object HandleException(IRequestContext requestContext, TRequest request, Exception ex) {
// Called whenever an exception is thrown in your Services Action
}
}
Also for more fine-grained Error Handling options check out the Error Handling wiki page.
My solution was to add an additional layer where I can handle Logic per entity:
Base Logic Sample:
public interface IEntity
{
long Id { get; set; }
}
public interface IReadOnlyLogic<Entity> where Entity : class, IEntity
{
List<Entity> GetAll();
Entity GetById(long Id);
}
public abstract class ReadOnlyLogic<Entity> : IReadOnlyLogic<Entity> where Entity : class, IEntity, new()
{
public IDbConnection Db { get; set; }
#region HOOKS
protected SqlExpression<Entity> OnGetList(SqlExpression<Entity> query) { return query; }
protected SqlExpression<Entity> OnGetSingle(SqlExpression<Entity> query) { return OnGetList(query); }
#endregion
public List<Entity> GetAll()
{
var query = OnGetList(Db.From<Entity>());
return Db.Select(query);
}
public Entity GetById(long id)
{
var query = OnGetSingle(Db.From<Entity>())
.Where(e => e.Id == id);
var entity = Db.Single(query);
return entity;
}
}
Then we can use hooks like:
public interface IHello : IReadOnlyLogic<Hello> { }
public class HelloLogic : ReadOnlyLogic<Hello>, IHello
{
protected override SqlExpression<Hello> OnGetList(SqlExpression<Hello> query)
{
return query.Where(h => h.Name == "Something");
}
}
Finally our service only calls our logic:
public class MyServices : Service
{
IHello helloLogic;
public object Get()
{
return helloLogic.GetAll();
}
}

Use session state for an ApiController

I want to have my own AppContext in my ApiController (MVC4).
Should be something like
public class TestController : BaseApiController
{
[HttpGet]
public IEnumerable<TestVM> GetAll()
{
// the test service is injected with SimpleInjector
return _testService.GetAll(**base.AppContext**);
}
}
but the ApiController haven't access to the Session.
Are there any solutions to "activate" the Session for specific keys (because I don't want the whole Session)?
Or do you have any other idea (cache or cookie)?
This is the BaseApiController
public abstract class BaseApiController: ApiController
{
public IAppContext AppContext
{
get { return SessionState.AppContext; }
}
}
and this is my IAppContext (it will have more properties in the future)
public interface IAppContext
{
IIdentity User { get; }
/// <summary> Gets the user id. </summary>
/// <value>The user id.</value>
int IdUser { get; }
}
here the application module which is registered in the web.config
public class ApplicationModule : IHttpModule
{
// ...
SessionState.AppContext = _appContext.InitializeNew(
HttpRuntime.AppDomainAppPath, languages);
// ...
}
SessionState class to get the AppContext
public class SessionState : BaseSessionVariables
{
public static IAppContext AppContext
{
get { return SessionState.Get<IAppContext>("AppContext"); }
set { SessionState.Set("AppContext", value); }
}
}
here the BaseSessionVariables class
public static HttpSessionState GetSession()
{
return HttpContext.Current.Session;
}
protected static T Get<T>(string key) where T : class
{
var session = BaseSessionVariables.GetSession();
if (session == null)
{
throw new Exception("No session");
}
return (session[key] as T);
}
Thanks for your help!
Take a look at the implementation below. It should get you headed in the right direction.
Updated IAppContext - Added Setters
public interface IAppContext
{
IIdentity User { get; set; }
/// <summary> Gets the user id. </summary>
/// <value>The user id.</value>
int IdUser { get; set; }
}
Updated Base Controller - Instantiates a new AppContextImplemenation in the OnActionExecuting method
public abstract class BaseApiController: ApiController
{
public IAppContext AppContext {get; set;}
protected override void OnActionExecuting(
ActionExecutingContext filterContext)
{
AppContext = new AppContextImplementation();
}
}
New Class - implements IAppContext and wraps the HttpContext Session. For testing you can then create an TestAppContextImplementation that doesn't rely on Session but some other in memory storage mechanism.
public class AppContextImplementation : IAppContext
{
public IIdentity User
{
get { return HttpContext.Current.Session["User"] as IIdentity; }
set { HttpContext.Current.Session["User"] = value; }
}
int IdUser
{
get { return Convert.ToInt32(Session["IdUser"]); }
set { Session["IdUser"] = value; }
}
}
For ApiControllers, build yourself a DelegatingHandler and push all of your goodies onto request.Properties. You can then retrieve them from your request whether you are testing or running live. The benefit is that you then have zero dependency on Session in your Controller.
MessageHandler
public class ContextHandler : DelegatingHandler
{
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
{
// get the goodies to add onto the request
var goodies = /* call to goodieGoodieYumYum */
// add our goodies onto the request
request.Properties.Add(Constants.RequestKey_Goodies, goodies);
// pass along to the next handler
return base.SendAsync(request, cancellationToken);
}
}
Controller Action
var goodies = (List<Goodie>)Request.Properties[Constants.RequestKey_Goodies];