I am writing a Java ODL application. I am following the general pattern of L2-Switch. I have a PacketIn dispatcher where I would like to know the port of connected switch where a packet was received. How can I do this? Thanks.
You can get the in_port like this :
#Override
public void onPacketReceived(PacketReceived packetReceived) {
Match match = packetReceived.getMatch();
String inPort = match.getInPort().getValue();
}
Supposing that this method belongs to a class you have created implementing the PacketProcessingListener:
public class PacketProcessing implements PacketProcessingListener{
...
}
Related
I know this question was asked a lot of time but i'm trying multiple solutions and can't make it work.
I am really new to Apache Camel, and I'm using it with Spring Boot.
What I want to do is have a global route to one of my folders, and when a file arrive in this folder trigger a process depending on a part of the file name.
Currently I just setup a route and try to trigger the process only for one of my file:
#Override
public void configure() throws Exception {
from("file://{{data.input.dir}}?moveFailed=errors&delete=true").choice()
.when(header("CamelFileName").endsWith(".zip"))
.process(myprocessor)
.end();
}
And my test:
#EndpointInject("mock:result") protected MockEndpoint resultEndpoint;
#Test
public void test() throws Exception {
ModelCamelContext mcc = camelContext.adapt(ModelCamelContext.class);
// Build a test route by adding an mock endpoint to the route
RouteDefinition route = mcc.getRouteDefinition(ROUTE_NAME);
RouteDefinition testRoute = route.to(resultEndpoint);
But here I have a null pointer exeception in the last line.
EDIT: Here is my Route definition
#Component public class MyRoute extends RouteBuilder {
public static final String ROUTE_NAME = "myRoute";
private final Processor myProcessor;
#Autowired public MyRoute(#Qualifier("my.processor") Processor myProcessor) {
this.myProcessor= myProcessor;
}
#Override public void configure() throws Exception {
from("file://{{data.input.dir}}?moveFailed=errors&delete=true").routeId(ROUTE_NAME).choice()
.when(header("CamelFileName").startsWith("ACK")).process(myProcessor).end();
}
}
First of all: What is the ROUTE_NAME you pass to get the route definition in your test? Because you have not defined a route ID in your route, Camel automatically generates a route ID. Have you really defined the generated route name in a constant? This name can change when you add other routes.
You should set a static self-defined route ID
from("whatever").routeId("import-file-route").choice()...
So that you can get the Route definition with a robust reference
mcc.getRouteDefinition("import-file-route")
Second: as far as I know, you cannot just call .to on the route definition. If you want to add a mock endpoint to your route, you have to advice the route.
This can be done for example by adding this method to your test-class...
public void addMockToEndOfRoute() throws Exception {
context.getRouteDefinition(""import-file-route"").adviceWith(context, new AdviceWithRouteBuilder() {
#Override
public void configure() {
weaveAddLast().to("mock:result");
}
});
}
... and then call addMockToEndOfRoute() in the test method.
Added to answer
Currently you import all files and try to limit routing to files with a specific name. Problem is that all imported files are deleted. So when you later try to read the corresponding DATA file, it could already be deleted.
You can limit the file-consumer to files with a specific name pattern with the include option that takes a regex
from("file://{{data.input.dir}}?include=ACK.*&...")
Like this only files with name "ACK[whatever]" are imported, so you can remove your content based router.
Quarkus using Rest Client, explains how to use the MicroProfile REST Client. For Base URL application.properties can be used.
org.acme.restclient.CountriesService/mp-rest/url=https://restcountries.eu/rest #
With above approach, cant have dynamic base URL.
Able to achieve it by using RestClientBuilder as explained in MicroProfile Rest Client. Downside of this approach is not having auto-negotiation capability.
SimpleGetApi simpleGetApi = RestClientBuilder.newBuilder().baseUri(getApplicationUri()).build(SimpleGetApi.class);
Is there other or better way to achieve this? Thanks.
While it is true, that the MP Rest CLient does not allow you to set the BaseUri dynamically when you use declarative/Injected clients, there are some (albeit hacky) ways how to achieve that.
One is to use standard ClientRequestFilter which can modify the URL:
#Provider
#Slf4j
public class Filter implements ClientRequestFilter {
#Inject RequestScopeHelper helper;
#Override
public void filter(ClientRequestContext requestContext) throws IOException {
if (helper.getUrl() != null) {
URI newUri = URI.create(requestContext.getUri().toString().replace("https://originalhost.com", helper.getUrl()));
requestContext.setUri(newUri);
}
}
}
Where RequestScopeHelper is some help class (e.g. request scoped bean) through which you can pass the dynamic url, for example:
#Inject
RequestScopeHelper helper;
#Inject
#RestClient
TestIface myApiClient;
public void callSomeAPIWithDynamicBaseUri(String dynamic) {
helper.setUrl(dynamic);
myApiClient.someMethod();
}
Second is to use MP rest client SPI, namely the RestClientListener which allows you to modify the rest clients after they are built.
For this to work, you have to set the scope of your rest client to RequestScoped so that new instance is created for each request(if you use singleton for example, then the client is only created once and your listener will only be called once). This you can do via quarkus properties:
quarkus.rest-client."com.example.MyRestIface".scope=javax.enterprise.context.RequestScoped
public class MyListener implements RestClientListener {
#Override
public void onNewClient(Class<?> serviceInterface, RestClientBuilder builder) {
String newUri = //obtain dynamic URI from somewhere e.g. again request scope bean lookup, or maybe dynamic config source (create new in-memory ConfigSource, before you invoke your rest client set the corresponding rest client url property to your dynamic value, then inside this listener use ConfigProvider.getConfig().getProperty...)
builder.baseUri(URI.create(newUri));
}
}
Don't forget to register this listener as service provider(META-INF/services/org.eclipse.microprofile.rest.client.spi.RestClientListener)
Another option is to use custom CDI producer that would produce the Rest client instances for you; then you could control all client config yourself. You can use the RestClientBase from Quarkus rest client which is exactly what Quarkus uses under the hood during deployment phase to construct client instances. You will however have to duplicate all the logic related to registration of handlers, interceptors etc.
Do keep in mind, that any of these solutions will make the debugging and problem analysis more challenging - because you will now have multiple places, where the URI is controlled(MP config/quarkus properties, env vars, your custom impl...), so you need to be careful with your approach and maybe add some explicit log messages when you override the URI manually.
MicroProfile REST Client in Quarkus does allow you to use dynamic base URL with that simple "hack" :
Just put an empty String in #Path annotations for you API interface like that :
import javax.ws.rs.GET;
import javax.ws.rs.Path;
#Path("")
public interface SimpleGetApi {
#Path("")
#GET
String callWithDynmamicUrl(); //it can be String or any return type you want
}
After that you are ready to call your dynamic base URL :
import org.eclipse.microprofile.rest.client.RestClientBuilder;
import java.net.URI;
public class Example {
public static void main(String[] args) {
URI anyDynamicUrl = URI.create("http://restcountries.eu/rest/some/dynamic/path");
SimpleGetApi simpleGetApi = RestClientBuilder.newBuilder().baseUri(anyDynamicUrl)
.build(SimpleGetApi.class);
simpleGetApi.callWithDynmamicUrl();
}
}
I can't find examples of use of stompSubProtocolHandler and SubProtocolWebSocketHandler?
I need extend this SubProtocolWebSocketHandler class?
private static class ProducerStompSessionHandler2 extends SubProtocolWebSocketHandler {
public ProducerStompSessionHandler2(MessageChannel clientInboundChannel,
SubscribableChannel clientOutboundChannel) {
super(clientInboundChannel, clientOutboundChannel);
// TODO Auto-generated constructor stub
}
}
I'm using a handler for a Sockjs java client that extend of StompSessionHandlerAdapter and is working. I can connect, subscribe and send messages:
private static class ProducerStompSessionHandler extends StompSessionHandlerAdapter {
...
}
But I see another user telling that there are two implementacions: SubProtocolWebSocketHandler and stompSubProtocolHandler.
https://stackoverflow.com/a/28306539/6243317
These are implementation of Java Websocket over STOMP clients? how use? advantages? why use this implementation?
To answer your main question in the title, I think this sample by Spring would be useful to you. The stompSubProtocolHandler is more server side in the sample, but I assume the logic will be the same for client.
I'm in the process of converting all my Spring Services to Jersey, when I came across an issue about how to convert the RequestParam's params feature of Spring to Jersey?
#RequestMapping(value = "/earnings", params = "type=csv")
Spring:
#RequestMapping(value = "/earnings", params = "type=csv")
public void earningsCSV() {}
#RequestMapping(value = "/earnings", params = "type=excel")
public void earningsExcel() {}
#RequestMapping("/earnings")
public void earningsSimple() {}
Jersey:
#Path("/earnings")
public void earningsCSV() {}
#Path("/earnings")
public void earningsExcel() {}
#RequestMapping("/earnings")
public void earningsSimple() {}
How to specify the type "csv/excel" in Jersey?
Does Jersey even support Filtering Requests based on Param's?
If not, is there any way I can achieve this?
I was thinking of a filter which process them and re-directs requests, but I've nearly 70+ services which needs to be addressed this way.
So I'll have to end up writing a filter for all of them. Also, It doesn't sound like a clean approach.
Any suggestions would be appreciated.
Thanks in advance.
There was no configuration in Jersey to define this, the way its done in spring.
I solved this by creating a Parent Service which accepts the call and re-directs the call to respective services based on param.
#Path("/earnings")
public void earningsParent(#QueryParam("type") final String type) {
if("csv".equals(type))
return earningsCSV();
else if("excel".equals(type))
return earningsExcel();
else
return earningsSimple();
}
public void earningsCSV() {}
public void earningsExcel() {}
public void earningsSimple() {}
I felt this approach was better than Filter as it doesn't need the developer to go change the Filter in future if it needs to be extended.
I've the following bundles:
- GreetingAPI (bundle which defines the greeting() method) (Service)
- GreetingImpl1 (bundle which implements greeting() method for English mode)
- GreetingImpl2 (bundle which implements greeting() method for Italian mode)
- GreetingConsumer (bundle which uses the greeting service)
How Can I create a component (I suppose it's a factory) that based on a given language parameter lets the consumer bundle to use a different implementation of the service.
You're thinking about this the wrong way around. The provider should not register a different service depending on something that the consumer does, because the provider shouldn't know anything about the consumer.
Instead, you can have multiple providers of the same service but annotate them with appropriate metadata. Then the consumer of the service can choose whether or not to filter on specific properties.
For example, when we register a service we can add properties as follows (note that I am using the OSGi Declarative Services annotations, see OSGi Compendium Release 5, section 112.8):
#Component(property = "locale=en_GB")
public class MyGreetingImpl1 implements Greeting {
public String greet() { return "How do you do"; }
}
#Component(property = "locale=en_US")
public class MyGreetingImpl2 implements Greeting {
public String greet() { return "Howdy"; }
}
#Component(property = "locale=fr_FR")
public class MyGreetingImpl3 implements Greeting {
public String greet() { return "Bonjour"; }
}
Now the consumer can choose whichever language it wants using a target filter. Note the use of a wildcard, as the consumer in this case only cares about the language but not the country code:
#Component
public class GreetingConsumer {
#Reference(target = "(language=en*)")
public void setGreeting(Greeting greeting) { ... }
}
One of the possible solutions is to have some kind of a language manager. So your consumer has a language manager and not directly the greetings service
The manager is notified with the registration / deregistration of every language implementation of your GreetingAPI.
Your language manager keeps trace of the diffrent implementations. Your manager provides the right implementation of the target language (using an enum for example)
Example
public class LanguageManagerImpl implements LanguageManager {
//LanguageEnum can be used to distinguish the different languages
private Map<LanguageEnum, GreetingAPI> greetings = new HashMap<LanguageEnum, GreetingAPI>();
public void registerLanguage(GreetingAPI greeting) {
LanguageEnum language = greeting.getLanguageEnum();
//add the greetings to the map
}
public void deregisterLanguage(GreetingAPI greeting){
//remove your greeting from the map
}
public GreetingAPI getGreetingForLanguage(LanguageEnum language) {
return greetings.get(language);
}
}
If you are using blueprint, then you need to add to the language manager blueprint a reference-list with a refence listener on GreetingAPI
Otherwise you use traditional listeners
Example
<bean id="languageManager"
class="your.language.managerimpl.LanguageManagerImpl">
</bean>
<service ref="languageManager" interface="your.language.manager.interface.LanguageManager" />
<reference-list interface="your.greeting.interface.GreetingAPI"
availability="optional">
<reference-listener ref="languageManager"
bind-method="registerLanguage" unbind-method="deregisterLanguage" />
</reference-list>