Does websockets work with tomcat7 on cloudbees? - websocket

Cloudbees now support websockets : http://wiki.cloudbees.com/bin/view/RUN/WebSockets
I tried to implement a very simple test on cloudbees using the tomcat7 clickStack
You can see the webpage trying to open this websocket here : http://wstest.ws.cloudbe.es/
This is working on my machine but doesn't at RUN#cloud
Am I missing something? The tomcat7 clickStack doesn't support websockets?
Thanks in advance.
My Servlet :
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import org.apache.catalina.websocket.MessageInbound;
import org.apache.catalina.websocket.StreamInbound;
import org.apache.catalina.websocket.WebSocketServlet;
import org.apache.catalina.websocket.WsOutbound;
#WebServlet(urlPatterns = "/testWebsocket")
public class TestWebsocket extends WebSocketServlet {
private static final long serialVersionUID = 1L;
#Override
protected StreamInbound createWebSocketInbound(String string, HttpServletRequest hsr) {
return new MessageInbound() {
#Override
protected void onOpen(WsOutbound outbound) {
super.onOpen(outbound);
}
#Override
protected void onClose(int status) {
super.onClose(status);
}
#Override
protected void onBinaryMessage(ByteBuffer bb) throws IOException {
}
#Override
protected void onTextMessage(CharBuffer cb) throws IOException {
System.out.println(cb.toString());
WsOutbound outbound = getWsOutbound();
outbound.writeTextMessage(CharBuffer.wrap((cb.toString()).toCharArray()));
}
};
}
}

I never tried this combination, but afaik this should work. Di you well configured your router in http 1.1 mode ?

Related

Open tracer Jaeger Trace not getting reflect for apache camel

I am new to apache camel and open tracing with Jaeger, I trying to get the traces for apache camel in Jaeger UI but its not getting captured through Open Tracing.
import org.apache.camel.CamelContext;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.impl.DefaultCamelContext;
import org.springframework.stereotype.Component;
#Component
public class RouteBuilderClient {
public void test() throws Exception {
DefaultCamelContext camelContext = new DefaultCamelContext();
camelContext.addRoutes(new RouteBuilder() {
#Override
public void configure() throws Exception {
from("timer:first-timer")
.to("log:first-timer");
}
});
camelContext.start();
camelContext.stop();
}
}
However if if I extend the RouteBuilder class(Below is the sample code) and then I override the configure method then traces are getting generated for Apache camel. Is there any way without extending the routeBuilder I can get the traces?
import org.apache.camel.builder.RouteBuilder;
import org.springframework.stereotype.Component;
#Component
public class RouteBuilderClient extends RouteBuilder {
#Override
public void configure() throws Exception {
from("timer:first-timer")
.to("log:first-timer");
}
}
My controller class:
import org.apache.camel.opentracing.starter.CamelOpenTracing;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
#CamelOpenTracing
public class JaegarClientApplication {
public static void main(String[] args) {
SpringApplication.run(JaegarClientApplication.class, args);
}
}
Try adding this in your setup() method, before starting the Camel context:
OpenTracingTracer ottracer = new OpenTracingTracer();
ottracer.init(camelContext);
camelContext.start();
Below is my code that Worked successfully.
import org.apache.camel.CamelContext;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.impl.DefaultCamelContext;
import org.apache.camel.opentracing.OpenTracingTracer;
public class RouteBuilderClient3 {
public void test() throws Exception {
RouteBuilder builder = new RouteBuilder() {
public void configure() {
from("timer:first-timer3").transform().constant("Rajesh client 3")
.to("log:first-timer3");
}
};
CamelContext myCamelContext = new DefaultCamelContext();
myCamelContext.addRoutes(builder);
OpenTracingTracer ottracer = new OpenTracingTracer();
ottracer.init(myCamelContext);
myCamelContext.start();
// myCamelContext.stop();
}
}

Using multiple configuration files in OSGi with equinox launcher

I want to use separate configuration files for different bundles instead of using a single configuration/config.ini file. I am following this doc https://www.eclipse.org/equinox/documents/quickstart-framework.php .
I am not able to figure out how to achieve this. Any suggestion would be very helpful.
Thanks in advance.
Following links solve the problem I was facing-
https://www.eclipse.org/forums/index.php/t/1072082/
https://git.eclipse.org/c/om2m/org.eclipse.om2m.git/tree/org.eclipse.om2m.site.mn-cse/configurations/services/lifx.basedriver.properties
https://git.eclipse.org/c/om2m/org.eclipse.om2m.git/tree/org.eclipse.om2m.sdt/org.eclipse.om2m.sdt.home.lifx/src/main/java/org/eclipse/om2m/sdt/home/lifx/impl/Activator.java
Steps I followed to achieve this -
Create configurations/services/<config_file_name>.properties having configurations in key-value pair. For example - property1 property1_value
Import package org.osgi.service.cm for your bundle
Use the following code
package <package_name>;
import java.util.Dictionary;
import java.util.Hashtable;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.cm.ConfigurationException;
import org.osgi.service.cm.ManagedService;
public class Activator implements BundleActivator, ManagedService {
private static BundleContext context;
private ServiceRegistration managedServiceServiceRegistration;
static BundleContext getContext() {
return context;
}
public void start(BundleContext bundleContext) throws Exception {
Activator.context = bundleContext;
Dictionary properties = new Hashtable<>();
properties.put(Constants.SERVICE_PID, "config_file_name");
managedServiceServiceRegistration =
bundleContext.registerService(ManagedService.class.getName(), this, properties);
}
public void stop(BundleContext bundleContext) throws Exception {
Activator.context = null;
}
#Override
public void updated(Dictionary properties) throws ConfigurationException {
try {
System.out.println(properties.get("property1"));
} catch (Exception e) {
e.printStackTrace();
}
}
}

How to make post request in apache camel rest

I am new apache rest dsl with spring boot, have made following changes
Main Class
package com.javaoutofbounds.pojo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication(scanBasePackages = {"com.ccs.batchfile"})
public class BatchFileApplication {
public static void main(String[] args) {
SpringApplication.run(BatchFileApplication.class, args);
}
}
Service class
package com.ccs.batchfile.service;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.model.rest.RestBindingMode;
import org.springframework.stereotype.Component;
#Component
public class BatchFileService extends RouteBuilder {
#Override
public void configure() throws Exception {
restConfiguration().component("servlet").bindingMode(RestBindingMode.json);
rest("/batchFile").consumes("application/json").produces("application/json").get("/routeStart").to("direct:startRoute");
}
}
Route class
package com.ccs.batchfile.routes;
import org.apache.camel.builder.RouteBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.ccs.batchfile.processor.StartRouteProcessor;
#Component
public class StartRoute extends RouteBuilder{
#Autowired
private StartRouteProcessor startRouteProcessor;
#Override
public void configure() throws Exception {
from("direct:startRoute").log("Inside StartRoute")
.process(startRouteProcessor);
}
}
Processor class
package com.ccs.batchfile.processor;
import org.apache.camel.Exchange;
import org.apache.camel.Processor;
import org.springframework.stereotype.Component;
#Component("startRouteProcessor")
public class StartRouteProcessor implements Processor{
public void process(Exchange exchange) throws Exception {
String message = exchange.getIn().getBody(String.class);
System.out.println(message);
}
}
I am not getting control to StartRouteProcessor, when i make below post request in postman
http://localhost:8080/batchFile/routeStart/
I have used below test payload to check if works.
{
"title" : "test title",
"singer" : "some singer"
}
When i post the above request i am getting 404 error. Kindly help on this please
I tried your example and you need to add two changes.
In your "main" class, the 'component scan' annotation is right, but you have to add a 'ServletRegistrationBean' with name 'CamelServlet':
package org.funcode.app.main;
import org.apache.camel.component.servlet.CamelHttpTransportServlet;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
#SpringBootApplication(scanBasePackages = {"org.funcode.app"})
public class BatchFileApplication {
private static final String CAMEL_URL_MAPPING = "/api/*";
private static final String CAMEL_SERVLET_NAME = "CamelServlet";
public static void main(String[] args) {
SpringApplication.run(BatchFileApplication.class, args);
}
#Bean
public ServletRegistrationBean servletRegistrationBean() {
ServletRegistrationBean registration =
new ServletRegistrationBean(new CamelHttpTransportServlet(), CAMEL_URL_MAPPING);
registration.setName(CAMEL_SERVLET_NAME);
return registration;
}
}
And if you want view on the log the content you posted on the request, you need to change the method of the request to "post":
package org.funcode.app.main;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.model.rest.RestBindingMode;
import org.springframework.stereotype.Component;
#Component
public class BatchFileService extends RouteBuilder {
#Override
public void configure() throws Exception {
restConfiguration().component("servlet").bindingMode(RestBindingMode.json);
rest("/batchFile")
.consumes("application/json")
.produces("application/json")
.post("/routeStart")
.to("direct:startRoute");
}
}
I hope it helps.

How to prevent Redis writes for anonymous user sessions

I have this sample application:
package com.example.session;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
#SpringBootApplication
public class DemoRedisDataSessionApplication {
#Configuration
#EnableWebSecurity
#EnableRedisHttpSession(redisNamespace = "demo-redis-data-session")
public static class AppConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("user").password("0000").roles("USER");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin().and()
.authorizeRequests().antMatchers("/ping").permitAll().and()
.authorizeRequests().anyRequest().fullyAuthenticated();
}
}
#RestController
public static class AppController {
#GetMapping("/ping")
public String ping() {
return "pong";
}
#GetMapping("/secured")
public String secured() {
return "secured";
}
}
public static void main(String[] args) {
SpringApplication.run(DemoRedisDataSessionApplication.class, args);
}
}
When I hit /secured I get 302 redirected to the /login form, which is what I expect if I am not logged in, but I get some unwanted entries in Redis:
127.0.0.1:6379> keys *
1) "spring:session:demo-redis-data-session:sessions:expires:dbb124b9-c37d-454c-8d67-409f28cb88a6"
2) "spring:session:demo-redis-data-session:expirations:1515426060000"
3) "spring:session:demo-redis-data-session:sessions:dbb124b9-c37d-454c-8d67-409f28cb88a6"
I don't want to create this data for every anonymous user (read crawler), so is there a way to prevent these Redis entries when hitting a secured endpoint/page with an anonymous user?
Additional data used for this sample project
 docker-compose.yml
version: "2"
services:
redis:
image: redis
ports:
- "6379:6379"
Spring Boot version
1.5.9.RELEASE
This is not the optimal solution since it creates only one session for all crawlers, but at least I don't get Redis full of unwanted session.
import lombok.extern.log4j.Log4j;
import org.springframework.session.Session;
import org.springframework.session.SessionRepository;
import org.springframework.session.web.http.CookieHttpSessionStrategy;
import org.springframework.session.web.http.MultiHttpSessionStrategy;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
#Log4j
#Component
public class CrawlerManagerSessionStrategyWrapper implements MultiHttpSessionStrategy {
private CookieHttpSessionStrategy delegate;
private volatile String crawlerSessionId;
public CrawlerManagerSessionStrategyWrapper() {
this.delegate = new CookieHttpSessionStrategy();
}
public String getRequestedSessionId(HttpServletRequest request) {
String sessionId = getSessionIdForCrawler(request);
if (sessionId != null)
return sessionId;
else {
return delegate.getRequestedSessionId(request);
}
}
public void onNewSession(Session session, HttpServletRequest request, HttpServletResponse response) {
delegate.onNewSession(session, request, response);
if (isCrawler(request)) {
crawlerSessionId = session.getId();
}
}
public void onInvalidateSession(HttpServletRequest request, HttpServletResponse response) {
delegate.onInvalidateSession(request, response);
}
public HttpServletRequest wrapRequest(HttpServletRequest request, HttpServletResponse response) {
return request;
}
public HttpServletResponse wrapResponse(HttpServletRequest request, HttpServletResponse response) {
return response;
}
private String getSessionIdForCrawler(HttpServletRequest request) {
if (isCrawler(request)) {
SessionRepository<Session> repo = (SessionRepository<Session>) request.getAttribute(SessionRepository.class.getName());
if (crawlerSessionId != null && repo != null) {
Session session = repo.getSession(crawlerSessionId);
if (session != null) {
return crawlerSessionId;
}
}
}
return null;
}
private boolean isCrawler(HttpServletRequest request) {
// Here goes the logic to understand if the request comes from a crawler, for example by checking the user agent.
return true;
}
}
The only thing to implement is the isCrawler method to state if the request comes from a crawler.

Use pivotal cloud foundry redis and rabbitmq service using as vcap service in spring boot application

I am able to use REDIS and RABBITMQ services which is on pivotal.While binding services I am able to get the Credentials and using that credentials in my application.properties for spring boot project.
But this configuration that I am using is hard-coded in application.Properties
To Make this configuration dynamically I came to know that we can use vcap services provided by pivotal.
So want to use run-time credentials for redis and rabbimq.
My Code is below for reference.
application.propeties
rabbitmq.host=hostname
rabbitmq.virtual-host=vhostanme
rabbitmq.username=username
rabbitmq.password=password
rabbit.mainqueue=abhi
rabbit.errorqueue=abc
redis.host=redishostname
redis.port=port
redis.password=password
My Config class:
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
#Component
public class Config {
static String rabbitMqHost;
static String rabbitMqVHost;
static String rabbitMqUsername;
static String rabbitMqPassword;
static String rabbitMqMainQueue;
static String rabbitMqErrorQueue;
static String redisHost;
static int redisPort;
static String redisPassword;
Config() {
}
public static String getRedisHost() {
return redisHost;
}
public static void setRedisHost(String redisHost) {
Config.redisHost = redisHost;
}
public static int getRedisPort() {
return redisPort;
}
public static void setRedisPort(int redisPort) {
Config.redisPort = redisPort;
}
public static String getRedisPassword() {
return redisPassword;
}
public static void setRedisPassword(String redisPassword) {
Config.redisPassword = redisPassword;
}
public static String getRabbitMqMainQueue() {
return rabbitMqMainQueue;
}
public static void setRabbitMqMainQueue(String rabbitMqMainQueue) {
Config.rabbitMqMainQueue = rabbitMqMainQueue;
}
public static String getRabbitMqErrorQueue() {
return rabbitMqErrorQueue;
}
public static void setRabbitMqErrorQueue(String rabbitMqErrorQueue) {
Config.rabbitMqErrorQueue = rabbitMqErrorQueue;
}
public static String getRabbitMqHost() {
return rabbitMqHost;
}
public static void setRabbitMqHost(String rabbitMqHost) {
Config.rabbitMqHost = rabbitMqHost;
}
public static String getRabbitMqVHost() {
return rabbitMqVHost;
}
public static void setRabbitMqVHost(String rabbitMqVHost) {
Config.rabbitMqVHost = rabbitMqVHost;
}
public static String getRabbitMqUsername() {
return rabbitMqUsername;
}
public static void setRabbitMqUsername(String rabbitMqUsername) {
Config.rabbitMqUsername = rabbitMqUsername;
}
public static String getRabbitMqPassword() {
return rabbitMqPassword;
}
public static void setRabbitMqPassword(String rabbitMqPassword) {
Config.rabbitMqPassword = rabbitMqPassword;
}
#Value("${rabbitmq.host}")
public void setRabbitMqHosts(String url) {
setRabbitMqHost(url);
}
#Value("${rabbitmq.virtual-host}")
public void setRabbitMqVHosts(String url) {
setRabbitMqVHost(url);
}
#Value("${rabbitmq.username}")
public void setRabbitUsernames(String url) {
setRabbitMqUsername(url);
}
#Value("${rabbitmq.password}")
public void setRabbitPasswords(String url) {
setRabbitMqPassword(url);
}
#Value("${rabbit.mainqueue}")
public void setRabbitMainQueues(String url) {
setRabbitMqMainQueue(url);
}
#Value("${rabbit.errorqueue}")
public void setRabbitErrorQueues(String url) {
setRabbitMqErrorQueue(url);
}
#Value("${redis.host}")
public void setRedisHosts(String url) {
setRedisHost(url);
}
#Value("${redis.port}")
public void setRedisPorts(int url) {
setRedisPort(url);
}
#Value("${redis.password}")
public void setRedisPasswords(String url) {
setRedisPassword(url);
}
}
My MessagesConsumer class in which I am using that Conguration to take message from rabbitmq jms queue and save to redis:
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import javax.annotation.PostConstruct;
import javax.jms.ConnectionFactory;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.Session;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import com.es.consumer.config.Config;
import com.rabbitmq.jms.admin.RMQConnectionFactory;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisShardInfo;
#Component
public class MessagesConsumer {
#Autowired
JmsTemplate jmsTemplate;
final Logger logger = LoggerFactory.getLogger(MessagesConsumer.class);
Jedis jedis;
JedisShardInfo shardInfo;
#PostConstruct
public void init() {
shardInfo = new JedisShardInfo(Config.getRedisHost(), Config.getRedisPort());
shardInfo.setPassword(Config.getRedisPassword());
jedis = new Jedis(shardInfo);
jedis.connect();
jedis.select(2);
}
#Bean
ConnectionFactory connectionFactory() {
RMQConnectionFactory connectionFactory = new RMQConnectionFactory();
connectionFactory.setUsername(Config.getRabbitMqUsername());
connectionFactory.setPassword(Config.getRabbitMqPassword());
connectionFactory.setVirtualHost(Config.getRabbitMqVHost());
connectionFactory.setHost(Config.getRabbitMqHost());
return connectionFactory;
}
#SuppressWarnings("rawtypes")
#Scheduled(fixedRate = 1)
public void readQueueAndSaveData() {
// take message process it and save to redis as hmset
}}
Any Help would be appreciable.
There are two ways of doing this.
1) Remove all the properties from application.properties, and write a configuration bean that will create RedisTemplate and RabbitTemplate beans for you. The factory properties required for these are to be obtained from the VCAP_SERVICES. On CF, the VCAP_SERVICES env variable, will have the services information that are binded to the app. When u push the app, with redis, rabbit service binded into your space, then their properties are available in VCAP_SERVICES. So just do System.getEnv("VCAP_SERVICES") in your code and then parse the json to get the service details to create the templates.
2) Remove the properties from application.properties, and use spring cloud connector. Spring cloud has a subproject called Spring cloud connectors that provide utilities to connect to various cloud services.
http://cloud.spring.io/spring-cloud-connectors/spring-cloud-spring-service-connector.html#_rabbitmq
Just you need to define a class that extends AbstractCloudConfig as below
class CloudConfig extends AbstractCloudConfig {
#Bean
public RabbitConnectionFactory rabbitFactory() {
return connectionFactory().rabbitConnectionFactory("rabbit-servicename");
}
#Bean
public RedisConnectionFactory redisFactory() {
return connectionFactory().redisConnectionFactory("redis-servicename");
}
}
The second approach is prefered if you are using Spring, as this needs very less coding and can be switched, to different cloud providers with no much effort.

Resources