Can't able to log using Zuul API gateway - java

This is my ZuulFilter.java
import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
#Component
public class ZuulLoggingFilter extends ZuulFilter {
private Logger logger = LoggerFactory.getLogger(this.getClass());
#Override
public boolean shouldFilter() {
return false;
}
#Override
public Object run() throws ZuulException {
HttpServletRequest request = RequestContext.getCurrentContext().getRequest();
logger.info("request -->{} request uri -->{}",request,request.getRequestURI());
return null;
}
#Override
public String filterType() {
return "pre";
}
#Override
public int filterOrder() {
return 1;
}
}
I have used slf4j library to log, but i can't see any log in my console after using api gateway.
I have used api gateway using following url
http://localhost:8765/{application-name}/{uri}.
I have got response properly but, It doesn't get logged in console.

Should filter must return true to get run called:
#Override
public boolean shouldFilter() {
return true;
}

Related

Java WebSocket subscribe/unsubscribe manually from inside server

I have created a simple websocket server with this configuration and I'm trying to subscribe or unsubscribe a user to a certain topic automaticaly, without the user permission (without sending SUBSCRIPTION event from the client). Example: a user connect to the server and the server automatically subscribe the user to topic "news" and "football". I'm trying to replicate what done when a client send this event "SUBSCRIBE\ndestination:/news/e88e2682-c467-4f48-b445-0af9c7983a5d\nid:/news/e88e2682-c467-4f48-b445-0af9c7983a5d\n\n\u0000" but without the client sending it actualy, is it possible?
package com.websocket.socket;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.ChannelRegistration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketTransportRegistration;
import org.springframework.web.socket.handler.WebSocketHandlerDecorator;
import org.springframework.web.socket.handler.WebSocketHandlerDecoratorFactory;
import java.util.Arrays;
#Configuration
#EnableWebSocketMessageBroker
public class WebSocketConfiguration implements WebSocketMessageBrokerConfigurer {
private static final Logger LOGGER = LoggerFactory.getLogger(WebSocketConfiguration.class);
public static final String APP = "/app";
private static final String[] topics = new String[]{
NEWS.BROKER_NAME,
FOOTBALL.BROKER_NAME
};
#Autowired
private TopicChannelInterceptor topicChannelInterceptor;
#Autowired
private UserSessions userSessions;
#Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker(topics);
config.setApplicationDestinationPrefixes(APP);
LOGGER.info("Prefix: {}", APP);
LOGGER.info("Topics: {}", Arrays.toString(topics));
}
#Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/socket")
.setAllowedOriginPatterns("*")
.withSockJS();
}
#Override
public void configureClientInboundChannel(ChannelRegistration registration) {
registration.interceptors(topicChannelInterceptor);
WebSocketMessageBrokerConfigurer.super.configureClientInboundChannel(registration);
}
#Override
public void configureWebSocketTransport(WebSocketTransportRegistration registration) {
registration.addDecoratorFactory(new WebSocketHandlerDecoratorFactory() {
#Override
public WebSocketHandler decorate(final WebSocketHandler handler) {
return new WebSocketHandlerDecorator(handler) {
#Override
public void afterConnectionEstablished(final WebSocketSession session) throws Exception {
// We will store current user's session into WebsocketSessionHolder after connection is established
userSessions.addUserSession(session.getId(), session);
LOGGER.info("Session stored");
super.afterConnectionEstablished(session);
}
};
}
});
}
}

keycloak redirect to update password url "login-actions/required-action"

I am building Identity management portal, using keycloak for authentication , i want to have one change password screen in this portal, when user click on that , it should redirect to keycloak theme update password screen ("http://host:port/auth/relams/<relam-name>/login-actions/required-action?execution=UPDATE_PASSWORD&client_id=test&tab_id=J4X7UdFi")
Can we achieve this in Keycloak after login?, this screen comes if we have Required Action as "UPDATE_PASSWORD" in Keyclaok UserRepresentation Object and before login if this action is there then keycloak itself redirects automatically to Update Password Screen ,
but can we give the Keycloak Update Password Screen directly to the user on UI after he logins.
We need to create RequiredActionProvider
package com.keycloak.password;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.jboss.logging.Logger;
import org.keycloak.authentication.RequiredActionContext;
import org.keycloak.authentication.RequiredActionProvider;
import org.keycloak.common.util.Time;
import org.keycloak.credential.CredentialModel;
import org.keycloak.credential.CredentialProvider;
import org.keycloak.credential.PasswordCredentialProvider;
import org.keycloak.credential.PasswordCredentialProviderFactory;
import org.keycloak.models.UserModel;
public class CustomUpdatePassword implements RequiredActionProvider {
private static final String OPENID_CONNECT_PROTOCOL = "openid-connect";
private static final String CLAIM_VALUE = "claim.value";
private static final Logger LOG = Logger.getLogger(CustomUpdatePassword.class.getName());
#Override
public void evaluateTriggers(RequiredActionContext context) {
try {
//some custom logic add required_action
if (password.getCreatedDate() == null) {
context.getUser().addRequiredAction(UserModel.RequiredAction.UPDATE_PASSWORD);
} else {
long timeElapsed = Time.toMillis(Time.currentTime()) - password.getCreatedDate();
long timeToExpire = TimeUnit.DAYS.toMillis(daysToExpirePassword);
if (timeElapsed > timeToExpire) {
context.getUser().addRequiredAction(UserModel.RequiredAction.UPDATE_PASSWORD);=
}
}
}
} catch (Exception e) {
LOG.error(e.getMessage());
}
}
#Override
public void requiredActionChallenge(RequiredActionContext context) {
}
#Override
public void processAction(RequiredActionContext context) {
}
#Override
public void close() {
}
}
And Factory class
package com.keycloak.password;
import org.keycloak.Config;
import org.keycloak.authentication.RequiredActionFactory;
import org.keycloak.authentication.RequiredActionProvider;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
public class CustomUpdatePasswordFactory implements RequiredActionFactory {
private static final CustomUpdatePassword SINGLETON = new CustomUpdatePassword();
#Override
public String getDisplayText() {
return "Password Update";
}
#Override
public RequiredActionProvider create(KeycloakSession keycloakSession) {
return SINGLETON;
}
#Override
public void init(Config.Scope scope) {
}
#Override
public void postInit(KeycloakSessionFactory keycloakSessionFactory) {
}
#Override
public void close() {
}
#Override
public String getId() {
return "Password Update";
}
}
Then these class jars needs to deploy in the jboss folder
COPY --chown=jboss:root /target/<above_project_jar>-*.jar /opt/jboss/keycloak/providers/

Spring Integration File reading

I am newbie to Spring Integration. I am working on solution, but I am stuck on a specific issue while using inbound file adapter ( FileReadingMessageSource ).
I have to read files from different directories and process them and save the files in different directories. As I understand, the directory name is fixed at the start of the flow.
Can some one help me on changing the directory name for different requests.
I attempted the following. First of all, I am not sure whether it is correct way to about and although it worked for only one directory. I think Poller was waiting for more files and never came back to read another directory.
#SpringBootApplication
#EnableIntegration
#IntegrationComponentScan
public class SiSampleFileProcessor {
#Autowired
MyFileProcessor myFileProcessor;
#Value("${si.outdir}")
String outDir;
#Autowired
Environment env;
public static void main(String[] args) throws IOException {
ConfigurableApplicationContext ctx = new SpringApplication(SiSampleFileProcessor.class).run(args);
FileProcessingService gateway = ctx.getBean(FileProcessingService.class);
boolean process = true;
while (process) {
System.out.println("Please enter the input Directory: ");
String inDir = new Scanner(System.in).nextLine();
if ( inDir.isEmpty() || inDir.equals("exit") ) {
process=false;
} else {
System.out.println("Processing... " + inDir);
gateway.processFilesin(inDir);
}
}
ctx.close();
}
#MessagingGateway(defaultRequestChannel="requestChannel")
public interface FileProcessingService {
String processFilesin( String inputDir );
}
#Bean(name = PollerMetadata.DEFAULT_POLLER)
public PollerMetadata poller() {
return Pollers.fixedDelay(1000).get();
}
#Bean
public MessageChannel requestChannel() {
return new DirectChannel();
}
#ServiceActivator(inputChannel = "requestChannel")
#Bean
GenericHandler<String> fileReader() {
return new GenericHandler<String>() {
#Override
public Object handle(String p, Map<String, Object> map) {
FileReadingMessageSource fileSource = new FileReadingMessageSource();
fileSource.setDirectory(new File(p));
Message<File> msg;
while( (msg = fileSource.receive()) != null ) {
fileInChannel().send(msg);
}
return null; // Not sure what to return!
}
};
}
#Bean
public MessageChannel fileInChannel() {
return MessageChannels.queue("fileIn").get();
}
#Bean
public IntegrationFlow fileProcessingFlow() {
return IntegrationFlows.from(fileInChannel())
.handle(myFileProcessor)
.handle(Files.outboundAdapter(new File(outDir)).autoCreateDirectory(true).get())
.get();
}
}
EDIT: Based on Gary's response replaced some methods as
#MessagingGateway(defaultRequestChannel="requestChannel")
public interface FileProcessingService {
boolean processFilesin( String inputDir );
}
#ServiceActivator(inputChannel = "requestChannel")
public boolean fileReader(String inDir) {
FileReadingMessageSource fileSource = new FileReadingMessageSource();
fileSource.setDirectory(new File(inDir));
fileSource.afterPropertiesSet();
fileSource.start();
Message<File> msg;
while ((msg = fileSource.receive()) != null) {
fileInChannel().send(msg);
}
fileSource.stop();
System.out.println("Sent all files in directory: " + inDir);
return true;
}
Now it is working as expected.
You can use this code
FileProcessor.java
import org.springframework.messaging.Message;
import org.springframework.stereotype.Component;
#Component
public class FileProcessor {
private static final String HEADER_FILE_NAME = "file_name";
private static final String MSG = "%s received. Content: %s";
public void process(Message<String> msg) {
String fileName = (String) msg.getHeaders().get(HEADER_FILE_NAME);
String content = msg.getPayload();
//System.out.println(String.format(MSG, fileName, content));
System.out.println(content);
}
}
LastModifiedFileFilter.java
package com.example.demo;
import org.springframework.integration.file.filters.AbstractFileListFilter;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
public class LastModifiedFileFilter extends AbstractFileListFilter<File> {
private final Map<String, Long> files = new HashMap<>();
private final Object monitor = new Object();
#Override
protected boolean accept(File file) {
synchronized (this.monitor) {
Long previousModifiedTime = files.put(file.getName(), file.lastModified());
return previousModifiedTime == null || previousModifiedTime != file.lastModified();
}
}
}
Main Class= DemoApplication.java
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import org.apache.commons.io.FileUtils;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.annotation.Aggregator;
import org.springframework.integration.annotation.InboundChannelAdapter;
import org.springframework.integration.annotation.Poller;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.channel.QueueChannel;
import org.springframework.integration.core.MessageSource;
import org.springframework.integration.dsl.IntegrationFlow;
import org.springframework.integration.dsl.IntegrationFlows;
import org.springframework.integration.dsl.channel.MessageChannels;
import org.springframework.integration.dsl.core.Pollers;
import org.springframework.integration.file.FileReadingMessageSource;
import org.springframework.integration.file.filters.CompositeFileListFilter;
import org.springframework.integration.file.filters.SimplePatternFileListFilter;
import org.springframework.integration.file.transformer.FileToStringTransformer;
import org.springframework.integration.scheduling.PollerMetadata;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.PollableChannel;
import org.springframework.stereotype.Component;
#SpringBootApplication
#Configuration
public class DemoApplication {
private static final String DIRECTORY = "E:/usmandata/logs/input/";
public static void main(String[] args) throws IOException, InterruptedException {
SpringApplication.run(DemoApplication.class, args);
}
#Bean
public IntegrationFlow processFileFlow() {
return IntegrationFlows
.from("fileInputChannel")
.transform(fileToStringTransformer())
.handle("fileProcessor", "process").get();
}
#Bean
public MessageChannel fileInputChannel() {
return new DirectChannel();
}
#Bean
#InboundChannelAdapter(value = "fileInputChannel", poller = #Poller(fixedDelay = "1000"))
public MessageSource<File> fileReadingMessageSource() {
CompositeFileListFilter<File> filters =new CompositeFileListFilter<>();
filters.addFilter(new SimplePatternFileListFilter("*.log"));
filters.addFilter(new LastModifiedFileFilter());
FileReadingMessageSource source = new FileReadingMessageSource();
source.setAutoCreateDirectory(true);
source.setDirectory(new File(DIRECTORY));
source.setFilter(filters);
return source;
}
#Bean
public FileToStringTransformer fileToStringTransformer() {
return new FileToStringTransformer();
}
#Bean
public FileProcessor fileProcessor() {
return new FileProcessor();
}
}
The FileReadingMessageSource uses a DirectoryScanner internally; it is normally set up by Spring after the properties are injected. Since you are managing the object outside of Spring, you need to call Spring bean initialization and lifecycle methods afterPropertiesSet() , start() and stop().
Call stop() when the receive returns null.
> return null; // Not sure what to return!
If you return nothing, your calling thread will hang in the gateway waiting for a response. You could change the gateway to return void or, since your gateway is expecting a String, just return some value.
However, your calling code is not looking at the result anyway.
> gateway.processFilesin(inDir);
Also, remove the #Bean from the #ServiceActivator; with that style, the bean type must be MessageHandler.

Websockets Tomcat 7 does not work in existing project

I try to run a websocket server in a Java project that was running on Tomcat6. I have set up a Tomcat 7 server where the project now is running on.
First I tried to run the socket example of Tomcat7. This run perfectly. I copied this class to my old project. When I run the old project again all the functionalities are working like before but only the websocket server doe not work.
This is the ChatAnnotation class that I have copied from the examples from Tomcat to my old project.
import java.io.IOException;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.atomic.AtomicInteger;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import org.apache.log4j.Logger;
#ServerEndpoint(value = "/websocket/chat")
public class ChatAnnotation {
private static Logger logger = Logger.getLogger(ChatAnnotation.class);
private static final String GUEST_PREFIX = "Guest";
private static final AtomicInteger connectionIds = new AtomicInteger(0);
private static final Set<ChatAnnotation> connections = new CopyOnWriteArraySet<ChatAnnotation>();
private final String nickname;
private Session session;
public ChatAnnotation() {
nickname = GUEST_PREFIX + connectionIds.getAndIncrement();
logger.info("ws instance");
}
#OnOpen
public void start(Session session) {
this.session = session;
connections.add(this);
String message = String.format("* %s %s", nickname, "has joined.");
broadcast(message);
}
#OnClose
public void end() {
connections.remove(this);
String message = String.format("* %s %s", nickname, "has disconnected.");
broadcast(message);
}
#OnMessage
public void incoming(String message) {
// Never trust the client
String filteredMessage = String.format("%s: %s", nickname, message.toString());
broadcast(filteredMessage);
}
#OnError
public void onError(Throwable t) throws Throwable {
logger.error("Chat Error: " + t.toString(), t);
}
private static void broadcast(String msg) {
for (ChatAnnotation client : connections) {
try {
synchronized (client) {
client.session.getBasicRemote().sendText(msg);
}
} catch (IOException e) {
logger.debug("Chat Error: Failed to send message to client", e);
connections.remove(client);
try {
client.session.close();
} catch (IOException e1) {
// Ignore
}
String message = String.format("* %s %s", client.nickname, "has been disconnected.");
broadcast(message);
}
}
}
}
I have noting added in my web.xml. In my old project are also tcpsockets used can this be the problem?
Can anyone help me with this problem?
EDIT
Class added:
import java.util.HashSet;
import java.util.Set;
import javax.websocket.Endpoint;
import javax.websocket.server.ServerApplicationConfig;
import javax.websocket.server.ServerEndpointConfig;
import org.apache.log4j.Logger;
public class ExamplesConfig implements ServerApplicationConfig {
private static Logger log = Logger.getLogger(ChatAnnotation.class);
public Set<ServerEndpointConfig> getEndpointConfigs(Set<Class<? extends Endpoint>> endpointClasses) {
Set<ServerEndpointConfig> result = new HashSet<ServerEndpointConfig>();
log.info("getEndpointConfigs");
return result;
}
public Set<Class<?>> getAnnotatedEndpointClasses(Set<Class<?>> scanned) {
log.info("getAnnotatedEndpointClasses");
return scanned;
}
}
Java websocket server use return value of ServerApplicationConfig interface to deploy programmatic endpoints and for annotated endpoints.
For Tomcat example, if you change the package name of ChatAnnotation. You have to modify websocket.ExamplesConfig too.
public Set<Class<?>> getAnnotatedEndpointClasses(Set<Class<?>> scanned) {
// Deploy all WebSocket endpoints defined by annotations in the examples
// web application. Filter out all others to avoid issues when running
// tests on Gump
Set<Class<?>> results = new HashSet<>();
for (Class<?> clazz : scanned) {
String name = clazz.getPackage().getName();
boolean ok = name.startsWith("websocket.");
if (ok) {
results.add(clazz);
}
}
return scanned;
}
The getAnnotatedEndpointClasses(scanned) only return classes which package name start with websocket. Unmatched classes will not deployed even they have #ServerEndpoint declarations.

SpringWebSockets does not send message from server

Hi i have an issue with spring websockets, this is the scenario:
a standalone application is sending (remote) some data like date Date, procedence String, and weight BigDecimal this data is sending via TCP to socket,
after that this data is saving into database at this point all is fine, but in the next step (websocket) i cannot show this information in a webpage, the weight data must be showed (live) in the screen
this is my websocket configuration:
import java.util.List;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.converter.MessageConverter;
import org.springframework.messaging.handler.invocation.HandlerMethodArgumentResolver;
import org.springframework.messaging.handler.invocation.HandlerMethodReturnValueHandler;
import org.springframework.messaging.simp.config.ChannelRegistration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketTransportRegistration;
#Configuration
#EnableWebSocketMessageBroker
public class WebSocketConfiguration implements WebSocketMessageBrokerConfigurer {
#Override
public void registerStompEndpoints(final StompEndpointRegistry registry) {
registry.addEndpoint("/indicator").withSockJS();
}
#Override
public void configureClientInboundChannel(final ChannelRegistration registration) {
}
#Override
public void configureClientOutboundChannel(final ChannelRegistration registration) {
}
#Override
public void configureMessageBroker(final MessageBrokerRegistry registry) {
}
#Override
public void configureWebSocketTransport(WebSocketTransportRegistration wstr) {
}
#Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> list) {
}
#Override
public void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> list) {
}
#Override
public boolean configureMessageConverters(List<MessageConverter> list) {
return Boolean.TRUE;
}
}
this is my another class that receive data form socket and process information and send to websocket:
import com.mcss.mcontrols.helper.ByteHelper;
import com.spc.basweb.Constants;
import com.spc.basweb.transmissor.dto.Transmission;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.messaging.core.MessageSendingOperations;
import org.springframework.messaging.simp.broker.BrokerAvailabilityEvent;
import com.spc.basweb.service.BroadcastingService;
import com.spc.basweb.service.DataProcessorService;
import java.io.IOException;
import org.springframework.integration.annotation.MessageEndpoint;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.integration.annotation.Transformer;
#MessageEndpoint
public class BroadcastingServiceImpl implements BroadcastingService, ApplicationListener<BrokerAvailabilityEvent> {
private static final Logger LOGGER = Logger.getLogger(BroadcastingServiceImpl.class);
private final MessageSendingOperations<String> messagingTemplate;
private String processedData;
#Autowired
DataProcessorService dataProcessorService;
#Autowired
public BroadcastingServiceImpl(final MessageSendingOperations<String> messagingTemplate) {
this.messagingTemplate = messagingTemplate;
}
#Override
public String getProcessedData() {
return processedData;
}
#Override
#ServiceActivator(inputChannel = "broadcaster")
public String broadcast(byte[] bytes) {
try {
Transmission t = (Transmission) ByteHelper.toObject(bytes);
LOGGER.debug(t.getProcedence() + " " + t.getDate() + " " + t.getWeight());
String rm = this.dataProcessorService.processData(t);
this.messagingTemplate.convertAndSend(Constants.END_POINT_READ, this.dataProcessorService.getWeighing().getWeight().toString());
return rm;
} catch (IOException | ClassNotFoundException ex) {
LOGGER.error("Error de transmision de objetos", ex);
}
return DataProcessorService.NOT_OK_RESPONSE;
}
#Override
public void onApplicationEvent(BrokerAvailabilityEvent e) {
LOGGER.debug("Application event");
}
#Transformer(outputChannel = "broadcaster")
public String convert(String response) {
return response;
}
}
in the debbuger i'm getting this information:
30-03-2016 15:07:20 DEBUG SimpleBrokerMessageHandler:277 - Processing MESSAGE destination=/read session=null payload=3003
in another class (Controller) i'm using the same method:
this.messagingTemplate.convertAndSend(Constants.END_POINT_READ, "3500");
and sending "manually" the information an is showing correctly. and i'm getting in debbuger this message:
30-03-2016 15:05:18 DEBUG SimpleBrokerMessageHandler:277 - Processing MESSAGE destination=/read session=dfR45V77 payload=3500
the difference is in session value but i don't know what this session is having null in the process, what am i doing wrong some clarification o help is welcome
First of all I don't see the configureMessageBroker implementation, so it isn't clear how that may work at all...
From other hand if you see such a difference, try to debug the code in the SimpMessagingTemplate.
I only see headerAccessor.setSessionId(sessionId); in the SimpleBrokerMessageHandler when it does
logger.debug("Broadcasting to " + subscriptions.size() + " sessions.");

Categories