JBoss 6 EAP - override HTTP response status code in a SOAP service that sends empty response back from 202 to 200 - cxf

We have a SOAP web service that we are migrating from JBoss EAP 5.1 to 6.4.7 and one of the webservices returns absolutely nothing but 200 (in JBoss 5). When we migrated to 6 it still works and returns nothing but returns a 202 instead and that is going to break clients. We have no control over clients. I tried a SOAPHandler at the close method but it does nothing as it is not even called as my guess is that since there is no SOAP message going back there is nothing that triggers the handler.
I also tried to access the context directly in the web method and modif but it did nothing.
MessageContext ctx = wsContext.getMessageContext();
HttpServletResponse response = (HttpServletResponse) ctx.get(MessageContext.SERVLET_RESPONSE);
response.setStatus(HttpServletResponse.SC_OK);
I couldn't find anything in the manual.
Any direction is very much appreciated.
Here is how the port and its implementation look like:
Here is how the port and its implementation head look like:
#WebService(name = "ForecastServicePortType", targetNamespace = "http://www.company.com/forecastservice/wsdl")
#SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
#XmlSeeAlso({
ObjectFactory.class
})
public interface ForecastServicePortType {
/**
*
* #param parameters
* #throws RemoteException
*/
#WebMethod(action = "http://www.company.com/forecast/sendForecast")
public void sendForecast(
#WebParam(name = "SendForecast", targetNamespace = "http://www.company.com/forecastservice", partName = "parameters")
SendForecastType parameters) throws RemoteException;
}
#WebService(name = "ForecastServicePortTypeImpl", serviceName = "ForecastServicePortType", endpointInterface = "com.company.forecastservice.wsdl.ForecastServicePortType", wsdlLocation = "/WEB-INF/wsdl/ForecastServicePortType.wsdl")
#HandlerChain(file = "/META-INF/handlers.xml")
public class ForecastServicePortTypeImpl implements ForecastServicePortType {
...
}

In case anybody will find this useful. Here is the solution;
Apache CXF by default uses async requests and even if the annotation #OneWay is missing it still behaves as it if was there.
So in order to disable that an interceptor needs to be created like below:
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.binding.soap.interceptor.AbstractSoapInterceptor;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.phase.Phase;
import java.util.Arrays;
public class DisableOneWayInterceptor extends AbstractSoapInterceptor {
private static final Log LOG = LogFactory.getLog(DisableOneWayInterceptor.class);
public DisableOneWayInterceptor(){
super(Phase.PRE_LOGICAL);
addBefore(Arrays.asList(org.apache.cxf.interceptor.OneWayProcessorInterceptor.class.getName()));
}
#Override
public void handleMessage(SoapMessage soapMessage) throws Fault {
if(LOG.isDebugEnabled())
LOG.debug("OneWay behavior disabled");
soapMessage.getExchange().setOneWay(false);
}
}
And called in WebService class (annotated with #WebService) as below:
#org.apache.cxf.interceptor.InInterceptors (interceptors = {"com.mycompany.interceptors.DisableOneWayInterceptor" })

Related

Apache Camel FTP integration

I have just started working around the Apache Camel. I have a requirement to implement an FTP/FTPS/SFTP client, which would be used to fetch the files from the respective servers. I was looking into the possibility of using Apache Camel to do this but I am still confused after going through the examples and the tutorials.
The requirement is to fetch the files from the FTP/SFTP servers when the request is received from the scheduler.
Following is the route created using EndPoint-DSL
#Component
public class FtpReceiveRoute extends EndpointRouteBuilder {
#Override
public void configure() throws Exception {
from(
ftp("localhost:2001/home/admin")
.account("admin")
.password("admin12345")
.recursive(true)
)
.routeId("ftpReceive")
.log("From done!")
.to("log:ftp-log")
.log("To done!!");
}
}
I am trying to use the above route by invoking it when the request is made to fetch the file like below.
#Override
protected FtpResponse doMessage(String param, FtpRequest req) {
FtpResponse response = new FtpResponse ();
CamelContext ctx = new DefaultCamelContext();
ctx.addRoutes(##route); //FtpReceiveRoute, add the Routebuilder instance as EndpointRouteBuilder is acceptable.
ctx.start();
//Might need to induce sleep so that all the files are downloaded
ctx.stop();
return response;
}
The confusion is around how to invoke the Camel process with the route. I have used EndpointRouteBuilder to create the route because of the type-safe creation of the endpoint URI. I am not getting an option to add this route to the CamelContext as it expects the RouteBuilder instance which is not type-safe.
Further, the CamelContext is the engine and to invoke the route I would need to start and stop this engine. This I am not able to digest if I need to start and stop the engine to execute a route then I would need to induce some sleep in between so that all files are downloaded. Just to add there are more routes that I need to add with the implementation. Once the engine is started it would load and execute all the added routes which is not the requirement.
Maybe I am not getting how to use this properly. Any resources aiding my situation are welcome. Thanks.
You should not create and start new camel context every time you want to fetch file from server. What you should do instead is start one when your application starts and use that for all your exchanges.
You can use Spring-boot to initialize CamelContext and add annotated RouteBuilders to it automatically. Check the maven archetype camel-archetype-spring-boot for example.
If you want to call camel routes from Java you can Inject CamelContext to your bean and use it to create ProducerTemplate. This can be used to invoke Routes defined in the RouteBuilder.
Using ProducerTemplate.send you can get the resulting exchange.
Using producer template
Using File-component which works very similary to ftp-component.
package com.example;
import org.apache.camel.builder.endpoint.EndpointRouteBuilder;
import org.springframework.stereotype.Component;
#Component
public class MySpringBootRouter extends EndpointRouteBuilder {
#Override
public void configure() {
from(direct("fileFromFTP"))
.routeId("fileFromFTP")
// reads files from <project>/input using file consumer endpoint
.pollEnrich(file("input"), 1000)
// If file is found, convert body to string.
// Which in this case will read contents of the file to string.
.filter(body().isNotNull())
.convertBodyTo(String.class)
.end()
;
}
}
package com.example;
import org.apache.camel.CamelContext;
import org.apache.camel.Exchange;
import org.apache.camel.ProducerTemplate;
import org.apache.camel.support.DefaultExchange;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import static org.apache.camel.builder.endpoint.StaticEndpointBuilders.direct;
#Configuration
#EnableScheduling
public class MySpringBean {
#Autowired
CamelContext camelContext;
#Scheduled(fixedRate = 1000)
public void scheduledTask() {
System.out.println("Scheduled Task!");
if(camelContext.isStopped()) {
System.out.println("Camel context not ready yet!");
return;
}
useProducerTemplate();
}
public void useProducerTemplate(){
ProducerTemplate producerTemplate = camelContext.createProducerTemplate();
Exchange inExchange = new DefaultExchange(camelContext);
//synchronous call!
Exchange result = producerTemplate.send(direct("fileFromFTP").toString(), inExchange);
String resultBody = result.getMessage().getBody(String.class);
String fileName = result.getMessage().getHeader(Exchange.FILE_NAME, String.class);
if(resultBody != null){
System.out.println("Consumed file: "+ fileName + " contents: " + resultBody.toString());
}
else{
System.out.println("No file to consume!");
}
}
}
Depending on what you need to do with the files you could probably do that inside camel route. Then you would only need to call the producerTemplate.sendBody.
public void useProducerTemplate(){
ProducerTemplate producerTemplate = camelContext.createProducerTemplate();
Exchange inExchange = new DefaultExchange(camelContext);
producerTemplate.sendBody(direct("fileFromFTP").toString(), inExchange);
}
Starting stopping camel route
If you want to start polling file consumer only for a short while you can do start the route and use for example aggregation timeout to shutdown the route when no new files have been received in any given duration.
#Component
public class MySpringBootRouter extends EndpointRouteBuilder {
#Override
public void configure() {
AggregationStrategy aggregateFileNamesStrategy = AggregationStrategies
.flexible(String.class)
.accumulateInCollection(ArrayList.class)
.pick(header(Exchange.FILE_NAME))
;
from(file("input"))
.routeId("moveFilesRoute")
.autoStartup(false)
.to(file("output"))
.to(seda("moveFilesRouteTimeout"));
;
from(seda("moveFilesRouteTimeout"))
.routeId("moveFilesRouteTimeout")
.aggregate(constant(true), aggregateFileNamesStrategy)
.completionTimeout(3000)
.log("Consumed files: ${body.toString()}")
.process(exchange -> {
exchange.getContext().getRouteController().stopRoute("moveFilesRoute");
})
.end()
;
}
}
public void startMoveFilesRoute() {
try {
System.out.println("Starting moveFilesRoute!");
camelContext.getRouteController().startRoute("moveFilesRoute");
//Sending null body moveFilesRouteTimeout to trigger timeout if there are no files to transfer
camelContext.createProducerTemplate().sendBody(seda("moveFilesRouteTimeout").toString(), null);
} catch(Exception e) {
System.out.println("failed to stop route. " + e);
}
}

Hystrix Javanica : Call always returning result from fallback method.(java web app without spring)

I am trying to integrate Hystrix javanica into my existing java EJB web application and facing 2 issues with running it.
When I try to invoke following service it always returns response from fallback method and I see that the Throwable object in fallback method has "com.netflix.hystrix.exception.HystrixTimeoutException" exception.
Each time this service is triggered, HystrixCommad and fallback methods are called multiple times around 50 times.
Can anyone suggest me with any inputs? Am I missing any configuration?
I am including following libraries in my project.
project libraries
I have setup my aspect file as follows:
<aspectj>
<weaver options="-verbose -showWeaveInfo"></weaver>
<aspects>
<aspect name="com.netflix.hystrix.contrib.javanica.aop.aspectj.HystrixCommandAspect"/>
</aspects>
</aspectj>
Here is my config.properties file in META-INF/config.properties
hystrix.command.default.execution.timeout.enabled=false
Here is my rest service file
#Path("/hystrix")
public class HystrixService {
#GET
#Path("clusterName")
#Produces({ MediaType.APPLICATION_JSON })
public Response getClusterName(#QueryParam("id") int id) {
ClusterCmdBean clusterCmdBean = new ClusterCmdBean();
String result = clusterCmdBean.getClusterNameForId(id);
return Response.ok(result).build();
}
}
Here is my bean class
public class ClusterCmdBean {
#HystrixCommand(groupKey = "ClusterCmdBeanGroup", commandKey = "getClusterNameForId", fallbackMethod = "defaultClusterName")
public String getClusterNameForId(int id) {
if (id > 0) {
return "cluster"+id;
} else {
throw new RuntimeException("command failed");
}
}
public String defaultClusterName(int id, Throwable e) {
return "No cluster - returned from fallback:" + e.getMessage();
}
}
Thanks for the help.
If you want to ensure you are setting the property, you can do that explicitly in the circuit annotation itself:
#HystrixCommand(commandProperties = {
#HystrixProperty(name = "execution.timeout.enabled", value = "false")
})
I would only recommend this for debugging purposes though.
Something that jumps out to me is that Javanica uses AspectJ AOP, which I have never seen work with new MyBean() before. I've always have to use #Autowired with Spring or similar to allow proxying. This could well just be something that is new to me though.
If you set a breakpoint inside the getClusterNameForId can you see in the stack trace that its being called via reflection (which it should be AFAIK)?
Note you can remove commandKey as this will default to the method name. Personally I would also remove groupKey and let it default to the class name.

Spring data JPA waiting find

I have some method which import prices for airports and save it to database through Spring data JPA repositories.
Import method is this:
#Transactional
public Future<Boolean> importFuel(File serverFile, Long providerIdLong) {
final FuelProvider fuelProvider = fuelProviderRepository
.findOne(providerIdLong);
LOG.debug("fuelProvider:" + fuelProvider.getName());
List<AirportFuel> airportFuels = processors
.get(providerIdLong).process(serverFile, fuelProvider);
if(airportFuels==null){
return new AsyncResult<>(false);
}
airportFuelRepository.deleteByFpId(providerIdLong);
airportFuelRepository.save(airportFuels);
fuelProvider.setUpdated(new Date());
fuelProviderRepository.save(fuelProvider);
return new AsyncResult<>(true);
}
For example this is read method:
List<AirportFuel> airportFuels = airportFuelRepository.findByIata(airport.getIata());
and AirportFuelRepository:
#Repository
#Transactional(readOnly = true)
public interface AirportFuelRepository extends CrudRepository<AirportFuel,
Long> {
#Transactional
#Modifying
#Query("delete from AirportFuel af where af.fpId = :#{#fpId}")
void deleteByFpId(#Param("fpId") Long fpId);
#Transactional(readOnly = true)
List<AirportFuel> findByIata(String iata);
List<AirportFuel> findByIataAndFpId(String iata, Long fpId);
}
Application is based on Spring boot, Hibernate, Spring data JPA and MS SQL.
If import method running then other method which also use airportFuelRepository waiting for end of this method and i do not know why. I suppose the reading method will work with the data before the import and will not waiting to end import method.
Thank you for advice.
If I understand correctly you want to have both methods be able to access the same repository asynchronously.
In order to do this annotate your method with the #Async annotation.
A few links to get you started:
baeldung.com
Spring Quickstart
Spring Javadoc
Dzone

(Android Studio) Connecting an app to Google Endpoints Module

I'm having trouble following the second step here.
I really don't understand how this sample does anything other than return a simple toast message. How does it utilize the API to display that message?
class EndpointsAsyncTask extends AsyncTask<Pair<Context, String>, Void, String> {
private static MyApi myApiService = null;
private Context context;
#Override
protected String doInBackground(Pair<Context, String>... params) {
if(myApiService == null) { // Only do this once
MyApi.Builder builder = new MyApi.Builder(AndroidHttp.newCompatibleTransport(),
new AndroidJsonFactory(), null)
// options for running against local devappserver
// - 10.0.2.2 is localhost's IP address in Android emulator
// - turn off compression when running against local devappserver
.setRootUrl("http://10.0.2.2:8080/_ah/api/")
.setGoogleClientRequestInitializer(new GoogleClientRequestInitializer() {
#Override
public void initialize(AbstractGoogleClientRequest<?> abstractGoogleClientRequest) throws IOException {
abstractGoogleClientRequest.setDisableGZipContent(true);
}
});
// end options for devappserver
myApiService = builder.build();
}
context = params[0].first;
String name = params[0].second;
try {
return myApiService.sayHi(name).execute().getData();
} catch (IOException e) {
return e.getMessage();
}
}
#Override
protected void onPostExecute(String result) {
Toast.makeText(context, result, Toast.LENGTH_LONG).show();
}
I'm afraid my this sample is too complex for my limited knowledge. How exactly do I "talk" to the Google Endpoints Module when running an app? Specifically, What is EndpointsAsyncTask();?
Are there any resources listing all the methods available to me? Is there a simpler example of an app communicating with a Google Cloud Endpoint?
The service methods available to you are defined by the backend source in section 1.
In the example you posted, this line: myApiService.sayHi(name).execute()
is an actual invocation call to the backend that you defined by annotating #ApiMethod("sayHi") on the method in the MyEndpoint.java class of your backend module.
The reason your Android app defines an EndpointsAsyncTask is because slow operations such as calls that hit the network need to happen off of the UI thread to avoid locking the UI. The demo simply puts the returned value into a Toast but you could modify onPostExecute() to do whatever you'd like with the result.
For more info on Google Endpoints check out:
https://cloud.google.com/appengine/docs/java/endpoints/
And for info about using an Android AsyncTask look here:
http://developer.android.com/reference/android/os/AsyncTask.html

Akka/Camel UntypedConsumerActor not consuming from file-based queue

I'm trying to put together my first Akka/Camel application from "scratch" (read, "noob") using the following lib versions:
akka-camel: 2.2.0-RC1
According to all of the documentation I can find (Akka docs, user groups, etc.) all I have to do to consume from a file-based queue is set up my system this way:
Main class:
actorSystem = ActorSystem.create("my-system");
Props props = new Props(Supervisor.class);
ActorRef supervisor = actorSystem.actorOf(props, "supervisor");
Camel camel = CamelExtension.get(actorSystem);
CamelContext camelContext = camel.context();
camelContext.start();
Supervisor class:
import akka.actor.ActorRef;
import akka.actor.Props;
import akka.camel.javaapi.UntypedConsumerActor;
import org.apache.camel.Message;
/**
* Manages creation and supervision of UploadBatchWorkers.
*/
public class Supervisor extends UntypedConsumerActor {
#Override
public String getEndpointUri() {
return "file:///Users/myhome/queue";
}
#Override
public void preStart() {
String test = "test";
}
#Override
public void onReceive(Object message) {
if (message instanceof CamelMessage) {
// do something
}
}
My problem is that even though I know the supervisor object is being created and breaks during debugging on the preStart() method's "test" line (not to mention that if I explicitly "tell" it something it processes fine), it does not consume from the defined endpoint, even though I have another application producing messages to the same endpoint.
Any idea what I'm doing wrong?
Ok, the problem was my own fault and is clearly visible in the example code if you look at the Consumer trait from which the UntypedConsumerActor inherits.
This method:
#Override
public void preStart() {
String test = "test";
}
overrides its parent's preStart() method, right? Well, that parent method is actually the one that registers the consumer with the on-the-fly created endpoint, so while you can override it, you must call super() or it will not work.
Hope this is useful to someone down the road!
Try changing your instanceof inside of onReceive to this:
if (message instanceof CamelMessage){
//do processing here
}
Where CamelMessage is from package akka.camel. That's what the examples in the akka camel docs are doing.

Resources