Deploying JAX-RS Servlet with constructor parameters - jax-rs

I am developing a JAX-RS servlet that adds an item to a queue using a POST method.
public class ServletResource extends Application {
private BlockingQueue<Item> queue;
public ServletResource(BlockingQueue<Item> queue) {
this.queue = queue;
}
#POST
#Consumes(MediaType.APPLICATION_JSON)
public void doPost(Item item) {
queue.put(item);
}
}
My problem is that using ResourceConfig, for deploying the Servlet in Tomcat, I can't pass the constructor parameters because ResourceConfig works at class level.
Main Method
BlockingQueue<CAPAlert> alertQueue = new LinkedBlockingQueue<>(5000);
tomcat = new Tomcat();
tomcat.setPort(servletPort);
File base = new File(System.getProperty("java.io.tmpdir"));
Context rootCtx = tomcat.addContext("", base.getAbsolutePath());
ServletContainer servlet = new ServletContainer(
new ResourceConfig(
ServletResource.class));
Tomcat.addServlet(rootCtx, "Servlet", servlet);
rootCtx.addServletMapping(servletPath, "Servlet");
tomcat.start();
SOLUTION 1: I found this solution:
ServletContainer servlet = new ServletContainer(
new ResourceConfig().register(
new ServletResource(queue)));

I finally get the next solution:
ServletContainer servlet = new ServletContainer(
new ResourceConfig().register(
new ServletResource(queue)));

Related

Apache CXF Password Type Always Sets Digest

I am working on a web service client project and using Apache CXF to send request to web service.
I need to set passwordType as PasswordText. But even if I set it in OutInterceptor property, It always sets passwordType as Digest. How can I solve this issue?
My Code is this:
JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
factory.setServiceClass(Test.class);
factory.setAddress(url);
factory.getInInterceptors().add(new SoapActionInInterceptor(action));
factory.getOutInterceptors().add(new SoapActionOutInterceptor());
Map<String, Object> outProps = new HashMap<String, Object>();
outProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN);
outProps.put(WSHandlerConstants.USER, username);
outProps.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PASSWORD_TEXT);
ClientPasswordHandler handler = new ClientPasswordHandler();
handler.setPassword(password);
outProps.put(WSHandlerConstants.PW_CALLBACK_REF, handler);
WSS4JStaxOutInterceptor wssOut = new WSS4JStaxOutInterceptor(outProps);
factory.getOutInterceptors().add(wssOut);
T serviceClient = (T) factory.create();
Client client = ClientProxy.getClient(serviceClient);
setClientPolicy(client);
And clientPolicy is this
protected synchronized void setClientPolicy(Client client) {
if (client != null) {
HTTPConduit httpConduit = (HTTPConduit) client.getConduit();
httpConduit.setAuthSupplier(null);
httpConduit.setAuthorization(null);
HTTPClientPolicy clientPolicy = new HTTPClientPolicy();
clientPolicy.setConnectionTimeout(60000L);
clientPolicy.setReceiveTimeout(60000L);
httpConduit.setClient(clientPolicy);
}
}
org.apache.cxf -> version 3.1.6
org.apache.wss4j -> version 2.1.7
I have found the solution. WSS4JStaxOutInterceptor extends AbstractWSS4JStaxInterceptor and it has a function to set incoming properties which we have send. When it try to set password property it checks incoming property with "PasswordText" string and when we use WSConstants its value is different. That's why when we set property value with "PasswordText" string it works fine. Final code for interceptor is:
private WSS4JStaxOutInterceptor createSecurityInterceptor() {
Map<String, Object> outProps = new HashMap<>();
outProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN);
outProps.put(WSHandlerConstants.USER, username);
// AbstractWSS4JStaxInterceptor class parseNonBooleanProperties require "PasswordText" check this function before changing this line
outProps.put(WSHandlerConstants.PASSWORD_TYPE, "PasswordText");
// AbstractWSS4JStaxInterceptor class parseNonBooleanProperties require "PasswordText" check this function before changing this line
ClientPasswordHandler handler = new ClientPasswordHandler();
handler.setPassword(password);
outProps.put(WSHandlerConstants.PW_CALLBACK_REF, handler);
return new WSS4JStaxOutInterceptor(outProps);
}
This solves the issue.

How can I support an HTTP Proxy using Spring 5 WebClient?

I am using Spring 5 WebClient. I want to know if it is possible to configure it to use an HTTP Proxy, or if there is a way of changing it's default configuration to do so.
This is something that the underlying client library should support.
When using Reactor Netty, you can do something like:
HttpClient httpClient = HttpClient.create()
.tcpConfiguration(tcpClient ->
tcpClient.proxy(proxy -> proxy.type(ProxyProvider.Proxy.HTTP).host("myproxyhost")));
ReactorClientHttpConnector connector = new ReactorClientHttpConnector(httpClient);
WebClient client = WebClient.builder().clientConnector(connector).build();
" tcpConfiguration" is deprecated.
So used this part of code instead.
HttpClient httpClient =
HttpClient.create()
.proxy(proxy -> proxy.type(ProxyProvider.Proxy.HTTP)
.host(sasConfig.getProxyHost())
.port(Integer.parseInt(sasConfig.getProxyPort())));
ReactorClientHttpConnector connector = new ReactorClientHttpConnector(httpClient);
WebClient webClient = WebClient.builder().clientConnector(connector).build();
Sharing recent experience here
Step 1 : Define proxy environment variables
-Dhttp.proxyHost=<proxyHost>
-Dhttp.proxyPort=8080
-Dhttps.proxyHost=<proxyHost>
-Dhttps.proxyPort=8080
-Dhttps.nonProxyHosts=localhost
Configuration of proxy on webClient
#Configuration
public class WebClientConfiguration {
#Bean
public WebClient webClient() {
return WebClient.builder() //
.defaultHeader(ACCEPT, APPLICATION_JSON_VALUE) //
.clientConnector(new ReactorClientHttpConnector(httpClient())) //
.build();
}
private HttpClient httpClient() {
return HttpClient //
.create() //
.proxyWithSystemProperties();
}
}
Set the spring cloud proxy properties (In the application start)
static {
String nonProxyHosts = System.getProperty("http.nonProxyHosts");
if (nonProxyHosts != null) {
String regexProxyList = nonProxyHosts.replaceAll("\\.", "\\\\.").replaceAll("\\/", "\\\\/").replaceAll("\\*", ".\\*");
System.setProperty("spring.cloud.gateway.httpclient.proxy.non-proxy-hosts-pattern", regexProxyList);
}
String proxyHost = System.getProperty("https.proxyHost");
String proxyPort = System.getProperty("https.proxyPort");
if (proxyHost != null && proxyPort != null) {
System.setProperty("spring.cloud.gateway.httpclient.proxy.host", proxyHost);
System.setProperty("spring.cloud.gateway.httpclient.proxy.port", proxyPort);
}
}

HttpClient default headers not working with Microsoft.Owin.Testing.TestServer

I'm using the Microsoft.Owin.Testing library to integration test my API in-memory. I've added in the OWIN JWT middleware for my authentication needs, and am now trying to pass a generated token to test requests to controllers needing authorization. I can assure you that the JWT middleware is setup correctly, as it works just fine with normal use. However, I am observing some strange behavior with the TestServer.HttpClient object. When I set a default authorization header on HttpClient to pass the token, my tests never pass because the token is not recognized. However, when I use TestServer.CreateRequest(...), the test passes correctly and the token is recognized. I would prefer to use the HttpClient methods because they make things a hell of a lot easier with all the extension methods provided such as PostAsJsonAsync, etc. I'm beginning to think there is either a bug in the TestServer.HttpClient or I that am completely missing something.
Here's my test class (using NUnit3):
public class DefinitionsControllerTests
{
private TestServer _server;
private string _accessToken;
[SetUp]
public void Setup()
{
_server = TestServer.Create<Startup>();
var credentials = new FormUrlEncodedContent(new[] {
new KeyValuePair<string, string>("grant_type", "password"),
new KeyValuePair<string, string>("username", "john.doe#mail.com"),
new KeyValuePair<string, string>("password", "testing123")
});
// get token from OWIN JWT middleware
dynamic resultBody = JObject.Parse(
_server.HttpClient.PostAsync("/oauth/token", credentials).Result.Content.ReadAsStringAsync().Result);
_accessToken = (string)resultBody.access_token;
// this does not appear to ever work
_server.HttpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", _accessToken);
}
[TearDown]
public void TearDown()
{
_server.Dispose();
}
[Test]
public void GetById_WithExistingId()
{
// 401 Unauthorized response everytime and test fails
var response = _server.HttpClient.GetAsync($"/api/definitions/{expected.Id}").Result;
var actual = response.Content.ReadAsAsync<Definition>().Result;
// 200 Ok every time and test passes
// - these variables aren't part of the test but rather to show alternate request creation method that works
var response2 = _server.CreateRequest($"/api/definitions/{expected.Id}")
.AddHeader("Authorization", "Bearer " + _accessToken)
.GetAsync()
.Result;
var actual2 = response.Content.ReadAsAsync<Definition>().Result;
response.StatusCode.ShouldBe(HttpStatusCode.OK);
actual.ShouldNotBeNull();
}
//...other test methods
}
And my controller:
[Authorize]
public class DefinitionsController : ApiController
{
private readonly IDefinitionRepository _repo;
public DefinitionsController(IDefinitionRepository repo)
{
_repo = repo;
}
public IHttpActionResult Get(Guid id)
{
var definition = _repo.Get(id);
if (definition == null)
return NotFound();
return Ok(definition);
}
}
Anyone have any idea why only CreateRequest() works? This is slightly infuriating.
The problem is that the HttpClient property returns a new instance every time. It will work if you save that instance and re-use it.
https://github.com/aspnet/AspNetKatana/blob/b850cd8b4de61e65bbd7127ce02b5df7c4cb6db5/src/Microsoft.Owin.Testing/TestServer.cs#L48

Liberty Profile and Apache HttpClient 4.2.1

Not sure if others have seen this, but I can't figure out what the deal is...
I am using Liberty Profile 8.5.5.1 with IBM JDK 7 pxi3270sr5-20130619_01(SR5)
I have a class that needs to make URL requests to another server (PHP based). So I wrote a HttpHelper class to call the apache HttpClient classes. If I invoke my helper from a plain java application I have no problem. When I run the exact same code within Liberty I get a ClassNotFound Error for javax.net.ssl.SSLSocket
Here is my code that calls the apache classes...
public class HttpClientHelper
{
static Logger LOGGER = Logger.getLogger(HttpClientHelper.class.getName());
static String cname = HttpClientHelper.class.getName();
static HttpClientHelper _instance = null;
static PoolingClientConnectionManager _cm = null;
private HttpClientHelper()
{
SchemeRegistry schemeRegistry = new SchemeRegistry();
schemeRegistry.register(
new Scheme("http", 80, PlainSocketFactory.getSocketFactory()));
_cm = new PoolingClientConnectionManager(schemeRegistry);
_cm.setMaxTotal(200);
_cm.setDefaultMaxPerRoute(20);
HttpHost shost = new HttpHost("joomla32.cal2.net", 80);
_cm.setMaxPerRoute(new HttpRoute(shost), 50);
}
protected static HttpClientHelper getInstance() {
if (_instance == null) {
_instance = new HttpClientHelper();
}
return _instance;
}
public static String getUrlBody(String url) {
String method = "getUrlBody(String url)";
LOGGER.entering(cname, method, url);
getInstance();
String val = null;
DefaultHttpClient httpclient = null;
try {
HttpContext context = new BasicHttpContext();
httpclient = new DefaultHttpClient(_cm);
HttpGet httpget = new HttpGet(url);
HttpResponse response = httpclient.execute(httpget, context);
HttpEntity entity = response.getEntity();
System.out.println(response.getStatusLine());
val = EntityUtils.toString(entity);
EntityUtils.consume(entity);
} catch (Exception e) {
LOGGER.logp(Level.WARNING, cname, method, e.getMessage(), url);
}catch(Error e){
LOGGER.logp(Level.INFO,cname,method,e.getMessage());
e.printStackTrace();
}
finally{
LOGGER.exiting(cname, method, val);
}
return val;
}
}
\
The Error gets thrown at the httpclient.execute(httpget,context);
I have tried adding the ssl updates to the IBM JDK but that didn't work.
ssl.SocketFactory.provider=com.ibm.jsse2.SSLSocketFactoryImpl
ssl.ServerSocketFactory.provider=com.ibm.jsse2.SSLServerSocketFactoryImpl
Any help would be appreciated
Figured it out...
My HttpClient Helper class was packaged in a bundle as part of a feature. The bundle didn't import javax.net.ssl so the class couldn't find it. Doh.

Access Current NHibernate Session in Castle Windsor IOC Container

I am trying to access my current nhibernate session using IOC from within a running Quartz.net Job and every time it comes back as null stating the following:
'NHibernateSession.Current' threw an exception of type 'SharpArch.Domain.PreconditionException' NHibernate.ISession SharpArch.Domain.PreconditionException}. An ISessionStorage has not been configured
Here is my current code setup. I cannot figure out for the life of me how to setup my IOC so that the NHibernate ISession within my IScheduledMessageQueries query is set correctly. The Quartz triggers are working correctly, I just cannot access the ISession to call my queries from within the Job. Any help and/or advice?
Global.cs Code:
protected virtual void InitializeServiceLocator()
{
_container = new WindsorContainer(new XmlInterpreter()).Install(new WebWindsorInstaller());
StartQuartzScheduler();
ComponentRegistrar.AddComponentsTo(_container);
ServiceLocator.SetLocatorProvider(() => new WindsorServiceLocator(_container));
DependencyResolver.SetResolver(new WindsorDependencyResolver(_container));
var activator = new WebApiControllerFactory(_container);
GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpControllerActivator), activator);
}
private static void StartQuartzScheduler()
{
ISchedulerFactory schedulerFactory = new StdSchedulerFactory();
IJobFactory jobFactory = new WindsorJobFactory(_container);
var scheduler = schedulerFactory.GetScheduler();
scheduler.JobFactory = jobFactory;
scheduler.Start();
var sendScheduledMessageJob = new JobDetailImpl("sendScheduledMessageJob", typeof(SendScheduledMessageJob));
var trigger = new CalendarIntervalTriggerImpl
{
StartTimeUtc = DateTime.UtcNow.Subtract(new TimeSpan(1)),
Name = "Daily Trigger",
RepeatIntervalUnit = IntervalUnit.Second,
RepeatInterval = 1
};
scheduler.ScheduleJob(sendScheduledMessageJob, trigger);
}
public class SendScheduledMessageJob : IJob
{
private readonly IScheduledMessageQueries _scheduledMessageQueries;
public SendScheduledMessageJob(IScheduledMessageQueries scheduledMessageQueries)
{
_scheduledMessageQueries = scheduledMessageQueries;
}
public void Execute(IJobExecutionContext context)
{
var unsentScheduledMessages =
_scheduledMessageQueries.GetAllUnsentScheduledMessages(DateTime.Now);
}
}