I am a newbie to java servlet filters and I have a CXF web service A.
The address of A is: http://localhost:8080/AdditionWS/services/additioncls?wsdl
I want to implement a proxy web service B.
The address of B is:
http://localhost:8080/ForwardWS/services/ForwardClsPort?wsdl
To forward the requests to A through B, I added a servlet filter to B:
public class RequestFilter implements Filter {
public void doFilter(final ServletRequest request, final ServletResponse response, FilterChain chain)
throws java.io.IOException, javax.servlet.ServletException {
HttpServletResponse resp = (HttpServletResponse) response;
String redirect="http://localhost:8080/AdditionWS/services/additioncls";
Enumeration<String> enumeration=request.getParameterNames();
String parameter=null;
while(enumeration.hasMoreElements())
{
parameter=enumeration.nextElement();
if(parameter.toLowerCase()=="wsdl")
break;
}
// if the parameter 'wsdl' exists forward to http://localhost:8080/AdditionWS/services/additioncls?wsdl
if(parameter!=null)
redirect="http://localhost:8080/AdditionWS/services/additioncls?"+"wsdl";
redirect=resp.encodeRedirectURL(redirect);
resp.sendRedirect(redirect);
}
}
and I updated the web address at the client code like the following:
import java.net.MalformedURLException;
import java.net.URL;
import javax.xml.namespace.QName;
import javax.xml.ws.WebEndpoint;
import javax.xml.ws.WebServiceClient;
import javax.xml.ws.WebServiceFeature;
import javax.xml.ws.Service;
//before:
wsdlLocation=http://localhost:8080/AdditionWS/services/additioncls?wsdl
#WebServiceClient(name = "AdditionClsService",
wsdlLocation = "http://localhost:8080/ForwardWS/services/ForwardClsPort?wsdl",
targetNamespace = "http://logic/")
public class AdditionClsService extends Service {
public final static URL WSDL_LOCATION;
public final static QName SERVICE = new QName("http://logic/", "AdditionClsService");
public final static QName AdditionClsPort = new QName("http://logic/", "AdditionClsPort");
static {
URL url = null;
try {
// before url=new URL("http://localhost:8080/AdditionWS/services/additioncls?wsdl");
url = new URL("http://localhost:8080/ForwardWS/services/ForwardClsPort?wsdl");
} catch (MalformedURLException e) {
java.util.logging.Logger.getLogger(AdditionClsService.class.getName())
.log(java.util.logging.Level.INFO,
"Can not initialize the default wsdl from {0}", "http://localhost:8080/AdditionWS/services/additioncls?wsdl");
}
WSDL_LOCATION = url;
}
public AdditionClsService(URL wsdlLocation) {
super(wsdlLocation, SERVICE);
}
public AdditionClsService(URL wsdlLocation, QName serviceName) {
super(wsdlLocation, serviceName);
}
public AdditionClsService() {
super(WSDL_LOCATION, SERVICE);
}
public AdditionClsService(WebServiceFeature ... features) {
super(WSDL_LOCATION, SERVICE, features);
}
public AdditionClsService(URL wsdlLocation, WebServiceFeature ... features) {
super(wsdlLocation, SERVICE, features);
}
public AdditionClsService(URL wsdlLocation, QName serviceName, WebServiceFeature ... features) {
super(wsdlLocation, serviceName, features);
}
/**
*
* #return
* returns AdditionWSSEI
*/
#WebEndpoint(name = "AdditionClsPort")
public AdditionWSSEI getAdditionClsPort() {
return super.getPort(AdditionClsPort, AdditionWSSEI.class);
}
/**
*
* #param features
* A list of {#link javax.xml.ws.WebServiceFeature} to configure on the proxy. Supported features not in the <code>features</code> parameter will have their default values.
* #return
* returns AdditionWSSEI
*/
#WebEndpoint(name = "AdditionClsPort")
public AdditionWSSEI getAdditionClsPort(WebServiceFeature... features) {
return super.getPort(AdditionClsPort, AdditionWSSEI.class, features);
}
}
For some reason, the client requests are not forwarded to A and I got the following errors:
Exception in thread "main" javax.xml.ws.WebServiceException: org.apache.cxf.service.factory.ServiceConstructionException: Failed to create service.
at org.apache.cxf.jaxws.ServiceImpl.initialize(ServiceImpl.java:162)
at org.apache.cxf.jaxws.ServiceImpl.<init>(ServiceImpl.java:129)
at org.apache.cxf.jaxws.spi.ProviderImpl.createServiceDelegate(ProviderImpl.java:82)
at javax.xml.ws.Service.<init>(Service.java:77)
at business.AdditionClsService.<init>(AdditionClsService.java:43)
at business.AdditionWSSEI_AdditionClsPort_Client.main(AdditionWSSEI_AdditionClsPort_Client.java:49)
Caused by: org.apache.cxf.service.factory.ServiceConstructionException: Failed to create service.
at org.apache.cxf.wsdl11.WSDLServiceFactory.<init>(WSDLServiceFactory.java:87)
at org.apache.cxf.jaxws.ServiceImpl.initializePorts(ServiceImpl.java:217)
at org.apache.cxf.jaxws.ServiceImpl.initialize(ServiceImpl.java:160)
... 5 more
Caused by: javax.wsdl.WSDLException: WSDLException: faultCode=PARSER_ERROR: com.ctc.wstx.exc.WstxEOFException: Unexpected EOF in prolog
at [row,col,system-id]: [1,0,"http://localhost:8080/ForwardWS/services/ForwardClsPort?wsdl"]
at org.apache.cxf.wsdl11.WSDLManagerImpl.loadDefinition(WSDLManagerImpl.java:228)
at org.apache.cxf.wsdl11.WSDLManagerImpl.getDefinition(WSDLManagerImpl.java:163)
at org.apache.cxf.wsdl11.WSDLServiceFactory.<init>(WSDLServiceFactory.java:85)
... 7 more
Caused by: com.ctc.wstx.exc.WstxEOFException: Unexpected EOF in prolog
at [row,col,system-id]: [1,0,"http://localhost:8080/ForwardWS/services/ForwardClsPort?wsdl"]
at com.ctc.wstx.sr.StreamScanner.throwUnexpectedEOF(StreamScanner.java:685)
at com.ctc.wstx.sr.BasicStreamReader.handleEOF(BasicStreamReader.java:2141)
at com.ctc.wstx.sr.BasicStreamReader.nextFromProlog(BasicStreamReader.java:2047)
at com.ctc.wstx.sr.BasicStreamReader.next(BasicStreamReader.java:1131)
at org.apache.cxf.staxutils.StaxUtils.readDocElements(StaxUtils.java:1369)
at org.apache.cxf.staxutils.StaxUtils.readDocElements(StaxUtils.java:1263)
at org.apache.cxf.staxutils.StaxUtils.read(StaxUtils.java:1191)
at org.apache.cxf.wsdl11.WSDLManagerImpl.loadDefinition(WSDLManagerImpl.java:219)
... 9 more
Did I miss something or is there a different way to implement a proxy cxf web service that will forward client requests to A or one of its duplicates?
Thank you!
Related
How to resend same or modified message from outbound http call in case of specific client error responses like 400, 413 etc
#Bean
private IntegrationFlow myChannel() {
IntegrationFlowBuilder builder =
IntegrationFlows.from(queue)
.handle(//http post method config)
...
.expectedResponseType(String.class))
.channel(MessageChannels.publishSubscribe(channel2));
return builder.get();
}
#Bean
private IntegrationFlow defaultErrorChannel() {
}
EDIT: Added end point to handle method
#Bean
private IntegrationFlow myChannel() {
IntegrationFlowBuilder builder =
IntegrationFlows.from(queue)
.handle(//http post method config)
...
.expectedResponseType(String.class),
e -> e.advice(myRetryAdvice()))
.channel(MessageChannels.publishSubscribe(channel2));
return builder.get();
}
#Bean
public Advice myRetryAdvice(){
... // set custom retry policy
}
Custom Retry policy:
class InternalServerExceptionClassifierRetryPolicy extends
ExceptionClassifierRetryPolicy {
public InternalServerExceptionClassifierRetryPolicy() {
final SimpleRetryPolicy simpleRetryPolicy =
new SimpleRetryPolicy();
simpleRetryPolicy.setMaxAttempts(2);
this.setExceptionClassifier(new Classifier<Throwable, RetryPolicy>() {
#Override
public RetryPolicy classify(Throwable classifiable) {
if (classifiable instanceof HttpServerErrorException) {
// For specifically 500 and 504
if (((HttpServerErrorException) classifiable).getStatusCode() == HttpStatus.INTERNAL_SERVER_ERROR
|| ((HttpServerErrorException) classifiable)
.getStatusCode() == HttpStatus.GATEWAY_TIMEOUT) {
return simpleRetryPolicy;
}
return new NeverRetryPolicy();
}
return new NeverRetryPolicy();
}
});
}}
EDIT 2: Override open() to modify the original message
RequestHandlerRetryAdvice retryAdvice = new
RequestHandlerRetryAdvice(){
#Override
public<T, E extends Throwable> boolean open(RetryContext
retryContext, RetryCallback<T,E> callback){
Message<String> originalMsg =
(Message) retryContext.getAttribute(ErrorMessageUtils.FAILED_MESSAGE_CONTEXT);
Message<String> updatedMsg = //some updated message
retryContext.setAttribute(ErrorMessageUtils.FAILED_MESSAGE_CONTEXT,up datedMsg);
return super.open(retryContext, callback);
}
See a RequestHandlerRetryAdvice: https://docs.spring.io/spring-integration/reference/html/messaging-endpoints.html#message-handler-advice-chain. So, you configure some RetryPolicy to check those HttpClientErrorException for retry and the framework will re-send for you.
Java DSL allows us to configure it via second handle() argument - endpoint configurer: .handle(..., e -> e.advice(myRetryAdvice)): https://docs.spring.io/spring-integration/reference/html/dsl.html#java-dsl-endpoints
I am trying to connect my Desktop to the PHILIPS Hue light server using java.
When the code runs, it will flow into the Controller.java. When that happens, the FindBridges method in Controller.java runs. This is where the error occurs. In debugging, it displays a NullPointerException in thread "AWT-Event-Queue-0".
I presume that the server/lightbulb cannot be found at all, even though it is turned on and my android application can connect to it.
The error is stated below:
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at com.philips.lighting.gui.DesktopView$1.actionPerformed(DesktopView.java:72)
Controller.java
package com.philips.lighting;
import java.util.List;
import java.util.Random;
import javax.swing.JDialog;
import com.philips.lighting.hue.sdk.upnp.*;
import com.philips.lighting.data.HueProperties;
import com.philips.lighting.gui.AccessPointList;
import com.philips.lighting.gui.DesktopView;
import com.philips.lighting.gui.LightColoursFrame;
import com.philips.lighting.gui.PushLinkFrame;
import com.philips.lighting.hue.sdk.PHAccessPoint;
import com.philips.lighting.hue.sdk.PHBridgeSearchManager;
import com.philips.lighting.hue.sdk.PHHueSDK;
import com.philips.lighting.hue.sdk.PHMessageType;
import com.philips.lighting.hue.sdk.PHSDKListener;
import com.philips.lighting.model.PHBridge;
import com.philips.lighting.model.PHBridgeResourcesCache;
import com.philips.lighting.model.PHHueError;
import com.philips.lighting.model.PHHueParsingError;
import com.philips.lighting.model.PHLight;
import com.philips.lighting.model.PHLightState;
public class Controller {
private PHHueSDK phHueSDK;
private DesktopView desktopView;
private PushLinkFrame pushLinkDialog;
private LightColoursFrame lightColoursFrame;
private static final int MAX_HUE=65535;
private Controller instance;
public Controller(DesktopView view) {
this.desktopView = view;
this.phHueSDK = PHHueSDK.getInstance(); // or phHueSDK = PHHueSDK.getInstance();
this.instance = this;
}
public void findBridges() {
//To uniquely identify your app in the bridge whitelist we recommend you set your app name, and the device
phHueSDK.setAppName("SmartShowroomApp"); // e.g. phHueSDK.setAppName("QuickStartApp");
phHueSDK.setDeviceName("SmartDevice"); // e.g. If you are programming for Android: phHueSDK.setDeviceName(android.os.Build.MODEL);
phHueSDK = PHHueSDK.getInstance();
PHBridgeSearchManager sm = (PHBridgeSearchManager) phHueSDK.getSDKService(PHHueSDK.SEARCH_BRIDGE);
sm.search(true, true);
//This starts a UPNP/Portal Search and takes around 10 seconds.
//The PHSDKListener (onAccessPointsFound) will be notified with the bridges found.
}
private PHSDKListener listener = new PHSDKListener() {
#Override
public void onAccessPointsFound(List<PHAccessPoint> accessPointsList) {
// Handle your bridge search results here.
//Typically if multiple results are returned you will want to display them in a list
// and let the user select their bridge.
//If one is found you may opt to connect automatically to that bridge.
phHueSDK = PHHueSDK.getInstance();
desktopView.getFindingBridgeProgressBar().setVisible(false);
if (accessPointsList != null && accessPointsList.size() > 0)
{
AccessPointList accessPointList = new AccessPointList(accessPointsList, instance);
accessPointList.setVisible(true);
accessPointList.setLocationRelativeTo(null); // Centre the AccessPointList Frame
phHueSDK.getAccessPointsFound().clear(); // Clear all connected access points
phHueSDK.getAccessPointsFound().addAll(accessPointsList); // Adds multiple results to the list
}
else
{
PHBridgeSearchManager sm = (PHBridgeSearchManager) phHueSDK.getSDKService(PHHueSDK.SEARCH_BRIDGE);
sm.search(false, false, true);
}
}
#Override
public void onAuthenticationRequired(PHAccessPoint accessPoint) {
// Start the Pushlink Authentication.
phHueSDK = PHHueSDK.getInstance();
desktopView.getFindingBridgeProgressBar().setVisible(false);
phHueSDK.startPushlinkAuthentication(accessPoint);
// Arriving here indicates that Pushlinking is required (to prove the User has physical access to the bridge).
//Typically here you will display a pushlink image (with a timer) indicating to to the user they need to push the button on their bridge within 30 seconds.
pushLinkDialog = new PushLinkFrame(instance);
pushLinkDialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
pushLinkDialog.setModal(true);
pushLinkDialog.setLocationRelativeTo(null); // Center the dialog.
pushLinkDialog.setVisible(true);
}
#Override
public void onBridgeConnected(PHBridge bridge) {
phHueSDK = PHHueSDK.getInstance();
phHueSDK.setSelectedBridge(bridge);
phHueSDK.enableHeartbeat(bridge, PHHueSDK.HB_INTERVAL);
// Here it is recommended to set your connected bridge in your sdk object (as above) and start the heartbeat.
// At this point you are connected to a bridge so you should pass control to your main program/activity.
// Also it is recommended you store the connected IP Address/ Username in your app here.
//This will allow easy automatic connection on subsequent use.
// Remember to disable the heartbeat when exiting your app
//phHueSDK.disableAllHeartbeat();
//If you are only interested in a particular resource (e.g. Lights), you can enable the multi resource heartbeat as follows:
//PHHeartbeatManager heartbeatManager = PHHeartbeatManager.getInstance();
//heartbeatManager.enableLightsHeartbeat(bridge, PHHueSDK.HB_INTERVAL);
// To stop the heartbeat you can use either of the below
//heartbeatManager.disableLightsHeartbeat(bridge);
//heartbeatManager.disableAllHeartbeats(bridge);
desktopView.getFindingBridgeProgressBar().setVisible(false);
String username = HueProperties.getUsername();
String lastIpAddress = bridge.getResourceCache().getBridgeConfiguration().getIpAddress();
System.out.println("On connected: IP " + lastIpAddress);
HueProperties.storeUsername(username);
HueProperties.storeLastIPAddress(lastIpAddress);
HueProperties.saveProperties();
// Update the GUI.
desktopView.getLastConnectedIP().setText(lastIpAddress);
desktopView.getLastUserName().setText(username);
// Close the PushLink dialog (if it is showing).
if (pushLinkDialog!=null && pushLinkDialog.isShowing()) {
pushLinkDialog.setVisible(false);
}
// Enable the Buttons/Controls to change the hue bulbs.s
desktopView.getRandomLightsButton().setEnabled(true);
desktopView.getSetLightsButton().setEnabled(true);
}
#Override
public void onCacheUpdated(List cacheNotificationsList, PHBridge bridge) {
// Here you receive notifications that the BridgeResource Cache was updated. Use the PHMessageType to
// check which cache was updated, e.g.
if (cacheNotificationsList.contains(PHMessageType.LIGHTS_CACHE_UPDATED)) {
System.out.println("Lights Cache Updated ");
}
}
#Override
public void onConnectionLost(PHAccessPoint accessPoint) {
// Here you would handle the loss of connection to your bridge.
phHueSDK = PHHueSDK.getInstance();
if (accessPoint == null)
{
System.out.println("Please reconnect to your bridge.");
}
}
#Override
public void onConnectionResumed(PHBridge bridge) {
PHHueSDK phHueSDK = PHHueSDK.getInstance();
for (int i = 0; i < phHueSDK.getDisconnectedAccessPoint().size(); i++)
{
if (phHueSDK.getDisconnectedAccessPoint().get(i).getIpAddress()
.equals(bridge.getResourceCache().getBridgeConfiguration().getIpAddress())) {
phHueSDK.getDisconnectedAccessPoint().remove(i);
}
}
}
#Override
public void onError(int code, final String message) {
// Here you can handle events such as Bridge Not Responding, Authentication Failed and Bridge Not Found.
if (code == PHHueError.BRIDGE_NOT_RESPONDING) {
desktopView.getFindingBridgeProgressBar().setVisible(false);
desktopView.getFindBridgesButton().setEnabled(true);
desktopView.getConnectToLastBridgeButton().setEnabled(true);
desktopView.showDialog(message);
}
else if (code == PHMessageType.PUSHLINK_BUTTON_NOT_PRESSED) {
pushLinkDialog.incrementProgress();
}
else if (code == PHMessageType.PUSHLINK_AUTHENTICATION_FAILED) {
if (pushLinkDialog.isShowing()) {
pushLinkDialog.setVisible(false);
desktopView.showDialog(message);
}
else {
desktopView.showDialog(message);
}
desktopView.getFindBridgesButton().setEnabled(true);
}
else if (code == PHMessageType.BRIDGE_NOT_FOUND) {
desktopView.getFindingBridgeProgressBar().setVisible(false);
desktopView.getFindBridgesButton().setEnabled(true);
desktopView.showDialog(message);
}
}
#Override
public void onParsingErrors(List<PHHueParsingError> parsingErrorsList) {
// Any JSON parsing errors are returned here.
//Typically your program should never return these.
for (PHHueParsingError parsingError: parsingErrorsList) {
System.out.println("ParsingError : " + parsingError.getMessage());
}
}
};
public PHSDKListener getListener() {
return listener;
}
public void setListener(PHSDKListener listener) {
this.listener = listener;
}
public void randomLights() {
PHBridge bridge = phHueSDK.getSelectedBridge();
PHBridgeResourcesCache cache = bridge.getResourceCache();
// And now you can get any resource you want, for example:
List<PHLight> allLights = cache.getAllLights();
Random rand = new Random();
for (PHLight light : allLights) {
PHLightState lightState = new PHLightState();
lightState.setHue(rand.nextInt(MAX_HUE));
bridge.updateLightState(light, lightState); // If no bridge response is required then use this simpler form.
}
}
public void showControlLightsWindow() {
if (lightColoursFrame == null) {
lightColoursFrame = new LightColoursFrame();
}
lightColoursFrame.setLocationRelativeTo(null); // Centre window
lightColoursFrame.setVisible(true);
}
/**
* Connect to the last known access point.
* This method is triggered by the Connect to Bridge button but it can equally be used to automatically connect to a bridge.
*
*/
public boolean connectToLastKnownAccessPoint() {
String username = HueProperties.getUsername();
String lastIpAddress = HueProperties.getLastConnectedIP();
if (username==null || lastIpAddress == null) {
desktopView.showDialog("Missing Last Username or Last IP. Last known connection not found.");
return false;
}
//Obviously, every time a user opens up their Android hue app or application you don't want them to have to select their bridge, authenticate pushlink everytime.
//The recommended way to overcome this issue is to store the connected IP Address/Username (using your preferred method storage) and if set try to connect automatically.
PHAccessPoint accessPoint = new PHAccessPoint();
accessPoint.setIpAddress(lastIpAddress);
accessPoint.setUsername(username);
phHueSDK.connect(accessPoint);
return true;
//Note that the .connect method returns control to your PHSDKListener, so when connected the onBridgeConnected will be called again, and if your users Bridge IP has changed for example, onError will be called and can be handled programatically.
}
public void enableFindBridgesButton() {
desktopView.getFindBridgesButton().setEnabled(true);
}
public void showProgressBar() {
desktopView.getFindingBridgeProgressBar().setVisible(true);
}
}
DesktopView.java
package com.philips.lighting.gui;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JTextField;
import layout.TableLayout;
import com.philips.lighting.Controller;
import com.philips.lighting.data.HueProperties;
/**
* DesktopView.java
*
* The main GUI showing last connected IP/Username and buttons for Finding Bridges and Changing the Hue Lights, once connected to a bridge.
*
*/
public class DesktopView extends JFrame {
private static final long serialVersionUID = -7469471678945429320L;
private Controller controller;
private JButton setLightsButton;
private JButton randomLightsButton;
private JButton findBridgesButton;
private JButton connectToLastBridgeButton;
private JProgressBar findingBridgeProgressBar;
private JTextField lastConnectedIP;
private JTextField lastUserName;
public DesktopView(){
setTitle("Hue Desktop");
JPanel mainPanel = new JPanel();
// TODO - Move to another class
JPanel controls = new JPanel();
controls.setLayout(new GridLayout(2,3));
findingBridgeProgressBar = new JProgressBar();
findingBridgeProgressBar.setBorderPainted(false);
findingBridgeProgressBar.setIndeterminate(true);
findingBridgeProgressBar.setVisible(false);
//Set up components preferred size
String lastUsername = HueProperties.getUsername();
String lastConnectedIPStr = HueProperties.getLastConnectedIP();
JLabel labelLastConIP = new JLabel("Last Connected IP:");
lastConnectedIP = new JTextField(lastConnectedIPStr);
lastConnectedIP.setEditable(false);
JLabel labelLastUsername = new JLabel("Last UserName:");
lastUserName = new JTextField(lastUsername);
lastUserName.setEditable(false);
findBridgesButton = new JButton("Find New Bridges");
findBridgesButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
findBridgesButton.setEnabled(false);
connectToLastBridgeButton.setEnabled(false);
controller.findBridges();
findingBridgeProgressBar.setBorderPainted(true);
findingBridgeProgressBar.setVisible(true);
}
});
connectToLastBridgeButton = new JButton("Auto Connect");
connectToLastBridgeButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent ae) {
if (controller.connectToLastKnownAccessPoint()) {
connectToLastBridgeButton.setEnabled(false);
findBridgesButton.setEnabled(false);
findingBridgeProgressBar.setBorderPainted(true);
findingBridgeProgressBar.setVisible(true);
}
}
});
setLightsButton = new JButton("Change Light Colours");
setLightsButton.setEnabled(false);
setLightsButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
controller.showControlLightsWindow();
}
});
randomLightsButton = new JButton("Randomize Lights");
randomLightsButton.setEnabled(false);
randomLightsButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
controller.randomLights();
}
});
double border = 10;
double size[][] =
{{border, 160, 20, 300, 20, 160}, // Columns
{border, 26, 10, 26, 26, 26,6,26}}; // Rows
mainPanel.setLayout (new TableLayout(size));
mainPanel.add(labelLastConIP, " 1, 1");
mainPanel.add(lastConnectedIP, " 3, 1");
mainPanel.add(labelLastUsername, " 1, 3");
mainPanel.add(lastUserName, " 3, 3");
mainPanel.add(findingBridgeProgressBar, " 3, 5");
mainPanel.add(connectToLastBridgeButton, " 5, 1");
mainPanel.add(findBridgesButton, " 5, 3");
mainPanel.add(randomLightsButton, " 5, 5");
mainPanel.add(setLightsButton, " 5, 7");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setPreferredSize(new Dimension(700,270));
getContentPane().add(new JLabel(" An example Java/Swing Desktop Application to control your Hue Lights."), BorderLayout.NORTH);
getContentPane().add(mainPanel, BorderLayout.CENTER);
//4. Size the frame.
pack();
setLocationRelativeTo(null); // Centre the window.
setVisible(true);
}
public void setController(Controller controller) {
this.controller = controller;
}
public JButton getSetLightsButton() {
return setLightsButton;
}
public JButton getRandomLightsButton() {
return randomLightsButton;
}
public JButton getFindBridgesButton() {
return findBridgesButton;
}
public JButton getConnectToLastBridgeButton() {
return connectToLastBridgeButton;
}
public void showDialog(String message) {
JOptionPane.showMessageDialog(this, message);
}
public JProgressBar getFindingBridgeProgressBar() {
return findingBridgeProgressBar;
}
public JTextField getLastConnectedIP() {
return lastConnectedIP;
}
public JTextField getLastUserName() {
return lastUserName;
}
}
HueDesktop.java
package com.philips.lighting;
import com.philips.lighting.data.HueProperties;
import com.philips.lighting.gui.DesktopView;
import com.philips.lighting.hue.sdk.PHHueSDK;
/**
* HueDesktop.java
* An example Java/Swing Desktop application illustrating how to connect to a bridge and change your Hue lights
* using a Java Desktop Application.
*
* For more information on programming for Hue see:
* http://developers.meethue.com
*
*/
class HueDesktop {
public static void main(String args[]) {
new HueDesktop();
}
public HueDesktop() {
PHHueSDK phHueSDK = PHHueSDK.create();
// Load in HueProperties, if first time use a properties file is created.
HueProperties.loadProperties();
// Set Up the View (A JFrame, MenuBar and Console).
DesktopView desktopView = new DesktopView();
// Bind the Model and View
Controller controller = new Controller(desktopView);
desktopView.setController(controller);
// Register the PHSDKListener to receive callbacks from the bridge.
phHueSDK.getNotificationManager().registerSDKListener(controller.getListener());
}
}
Did you ever solve this? In future it is probably best to post hue Java SDK issues on the GitHub site. https://github.com/PhilipsHue/PhilipsHueSDK-Java-MultiPlatform-Android/issues
I would have seen this sooner on here (I wrote this code btw so am possibly the culprit).
I do remember seeing a similar issue before, am pretty sure it was related to Macs and the JDK Compiler level used (I possibly used an incompatible Swing component on Mac and JDK 1.6). Can you let me know your OS and JDK Compiler level and I will check this further?
I am receiving an error when using NServiceBus 4.0.3 with NHibernate 3.3.1 when it's trying to process a message
INFO NServiceBus.Unicast.Transport.TransportReceiver [(null)] <(null)> - Failed to process message
Autofac.Core.Registration.ComponentNotRegisteredException: The requested service 'NServiceBus.Impersonation.ExtractIncomingPrincipal' has not been registered. To avoid this exception, either register a component to provide the service, check for service registration using IsRegistered(), or use the ResolveOptional() method to resolve an optional dependency.
at NServiceBus.Unicast.Transport.TransportReceiver.ProcessMessage(TransportMessage message) in c:\BuildAgent\work\d4de8921a0aabf04\src\NServiceBus.Core\Unicast\Transport\TransportReceiver.cs:line 353
at NServiceBus.Unicast.Transport.TransportReceiver.TryProcess(TransportMessage message) in c:\BuildAgent\work\d4de8921a0aabf04\src\NServiceBus.Core\Unicast\Transport\TransportReceiver.cs:line 233
at NServiceBus.Transports.Msmq.MsmqDequeueStrategy.ProcessMessage(TransportMessage message) in c:\BuildAgent\work\d4de8921a0aabf04\src\NServiceBus.Core\Transports\Msmq\MsmqDequeueStrategy.cs:line 262
at NServiceBus.Transports.Msmq.MsmqDequeueStrategy.Action() in c:\BuildAgent\work\d4de8921a0aabf04\src\NServiceBus.Core\Transports\Msmq\MsmqDequeueStrategy.cs:line 197
2013-08-30 09:35:02,508 [9] WARN NServiceBus.Faults.Forwarder.FaultManager [(null)] <(null)> - Message has failed FLR and will be handed over to SLR for retry attempt: 1, MessageID=8aaed043-b744-49c2-965d-a22a009deb32.
I think it's fairly obvious what that I need to implement or register an "ExtractIncomingPrincipal", but I can't seem to find any documentation on how or whether there is a default one that I can use. I wouldn't have figured that I would have had to register any of the NServiceBus-related services as many of them are already being registered in my IoC implementation.
As requested, here is the EndpointConfig and supporting code I have currently:
[EndpointSLA("00:00:30")]
public class EndpointConfig : IConfigureThisEndpoint, AsA_Server, IWantCustomInitialization {
public void Init() {
Configure.With().ObjectBuilderAdapter().UseInMemoryTimeoutPersister().UseInMemoryGatewayPersister().InMemorySagaPersister().InMemorySubscriptionStorage();
}
}
//public class PrincipalExtractor : ExtractIncomingPrincipal {
// public IPrincipal GetPrincipal(TransportMessage message) {
// return Thread.CurrentPrincipal;
// }
//}
public class ObjectBuilderAdapter : IContainer {
readonly IDependencyInjector injector;
public ObjectBuilderAdapter(IDependencyInjectionBuilder dependencyInjectionBuilder) {
injector = dependencyInjectionBuilder.Create(); //This method does all the common service registrations that I am trying to re-use
//injector.RegisterType<ExtractIncomingPrincipal, PrincipalExtractor>();
}
public void Dispose() {
injector.Dispose();
}
public object Build(Type typeToBuild) {
return injector.Resolve(typeToBuild);
}
public IContainer BuildChildContainer() {
return new ObjectBuilderAdapter(new DependencyInjectorBuilder());
}
public IEnumerable<object> BuildAll(Type typeToBuild) {
return injector.ResolveAll(typeToBuild);
}
public void Configure(Type component, DependencyLifecycle dependencyLifecycle) {
injector.RegisterType(component);
}
public void Configure<T>(Func<T> component, DependencyLifecycle dependencyLifecycle) {
injector.RegisterType(component);
}
public void ConfigureProperty(Type component, string property, object value) {
if (injector is AutofacDependencyInjector) {
((AutofacDependencyInjector)injector).ConfigureProperty(component, property, value);
} else {
Debug.WriteLine("Configuring {0} for property {1} but we don't handle this scenario.", component.Name, property);
}
}
public void RegisterSingleton(Type lookupType, object instance) {
injector.RegisterInstance(lookupType, instance);
}
public bool HasComponent(Type componentType) {
return injector.IsRegistered(componentType);
}
public void Release(object instance) { }
}
public static class Extensions {
public static Configure ObjectBuilderAdapter(this Configure config) {
ConfigureCommon.With(config, new ObjectBuilderAdapter(new DependencyInjectorBuilder()));
return config;
}
}
I removed the IWantCustomInitialization (left over from something else I had tried earlier) interface implementation on the class and my service now processes the message. There are errors still (relating to trying to connect to Raven [even though I thought I am using everything in-memory), but it's processing the message.
i have written a small grails webapp. I am using milton.io to access some content via webdav.
So webdav is still working and i am able to put, get, delete files - and so on.
But now i want to add authentication and authorization. And here is the problem:
The Resource Interface gives me 2 methods:
Object authenticate(String user, String password);
boolean authorise(Request request, Request.Method method, Auth auth);
So my Resource classes implements the Resource Interface, but the method authenticate is never called by the framework. Do i have to implement Auth Basic by my self?
My knowledge about milton is very poor. May be i forgot something, cause my webdav client (e.g. cadaver) never asks for a username / password.
Thanks for any help
Peter Waver
Signature of my Resource Classes:
class SResource implements GetableResource, PropFindableResource, Resource, DeletableResource, MoveableResource, ReportableResource, CopyableResource
class SFileResource extends SResource implements ReplaceableResource
class SFolderResource extends SResource implements PutableResource, MakeCollectionableResource, CollectionResource
And here is the builder to get the HttpManager
class SMiltonConfig implements MiltonConfigurator {
protected HttpManagerBuilder builder;
protected List<Initable> initables;
protected HttpManager httpManager;
public SMiltonConfig(){
try {
// Attempt to use Enterprise edition build if available
Class builderClass = Class.forName("io.milton.ent.config.HttpManagerBuilderEnt");
builder = (HttpManagerBuilder) builderClass.newInstance();
println ("load Ent. HTTP Manager")
} catch (InstantiationException ex) {
builder = new HttpManagerBuilder();
println ("load Std. HTTP Manager")
} catch (IllegalAccessException ex) {
println ("load Std. HTTP Manager")
builder = new HttpManagerBuilder();
} catch (ClassNotFoundException ex) {
println ("load Std. HTTP Manager")
builder = new HttpManagerBuilder();
}
}
#Override
public HttpManager configure(Config arg0) throws ServletException {
ResourceFactory rf = new SResourceFactory();
builder.setMainResourceFactory(rf);
checkAddInitable(initables, builder.getMainResourceFactory());
httpManager = builder.buildHttpManager();
for( Initable i : initables ) {
i.init(config, httpManager);
}
return httpManager;
}
#Override
public void shutdown() {
httpManager.shutdown()
for( Initable i : initables ) {
i.destroy(httpManager);
}
}
private void checkAddInitable(List<Initable> initables, Object o) {
if( o instanceof Initable) {
initables.add((Initable)o);
} else if( o instanceof List ) {
for( Object o2 : (List)o) {
checkAddInitable(initables, o2);
}
}
}
}
And here the ResourceFactory
class SResourceFactory implements ResourceFactory {
def fileSystemService
public SResourceFactory(){
println "loading resource Factory"
def ctx = ServletContextHolder.servletContext.getAttribute(GrailsApplicationAttributes.APPLICATION_CONTEXT)
fileSystemService = ctx.fileSystemService
}
#Override
public Resource getResource(String host, String strPath)
throws NotAuthorizedException, BadRequestException {
SResource sfr
sfr = fileSystemService.getFolderByPath(strPath)
return sfr
}
}
If you need Basic Auth - you have to enable it. So add the following line to the config method of the SMiltonConfig Class.
builder.setEnableOptionsAuth(true); // enables auth
builder.setEnableBasicAuth(true); // optional
Here'S an example of the Resource authorise Method
#Override
public boolean authorise(Request r, Method m, Auth a) {
return a != null;
}
Hope it helps
Florian Pfann
I have been using Tomcat 6.0.26-6.0.35 for several years with JSF 2 Mojarra, various versions up to 2.1.2 which I have been using for some months. I have several request-scoped and session-scoped beans with code like this:
private #Resource(name="jdbc/cLabs", mappedName="jdbc/cLabs") DataSource cLabs;
which has been correctly injected in every version of Tomcat 6 I've used. I also have other types of #Resource that doesn't work either, so it isn't just DataSource resources. I've tried switching to Tomcat 7.0.27 and suddenly none of these constructs works any more. The resource is not injected. I also have other types of #Resource that doesn't work either, so it isn't just DataSource resources. However in each case the resource named does exist, and can be looked up via e.g.
new InitialContext().lookup("java:comp/env/jdbc/cLabs");
[They are defined by elements in context.xml]
This of course is a royal PITA as I spent some time a year or two ago replacing the latter with the former. Is there some other magic spell I have to weave with Tomcat 7 to make it work again?
Note that resources are injected correctly into Servlets, so it isn't completely broken. Some interaction between Tomcat and JSF.
My guess is something is causing org.apache.catalina.core.DefaultInstanceManager to ignore annotations because faces requires the #PostConstruct method to be processed apart from #Resource fields. I have created a workaround that works for fields annotated with #Resource.
Add the following to web.xml:
<context-param>
<param-name>com.sun.faces.injectionProvider</param-name>
<param-value>com.example.faces.Tomcat7InjectionProvider</param-value>
</context-param>
And add the class to your source:
package com.example.faces;
import java.lang.reflect.Field;
import javax.annotation.Resource;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.servlet.ServletContext;
import org.apache.catalina.util.Introspection;
import com.sun.faces.spi.InjectionProviderException;
import com.sun.faces.vendor.WebContainerInjectionProvider;
public class Tomcat7InjectionProvider extends WebContainerInjectionProvider {
public Tomcat7InjectionProvider(ServletContext servletContext) {
}
#Override
public void inject(Object managedBean) throws InjectionProviderException {
if (managedBean != null) {
// see org.apache.catalina.core.DefaultInstanceManager
Field[] fields = Introspection.getDeclaredFields(managedBean.getClass());
for (Field field : fields) {
// field may be private
field.setAccessible(true);
if (field.isAnnotationPresent(Resource.class)) {
Resource annotation = null;
try {
annotation = field.getAnnotation(Resource.class);
Context ctx = new InitialContext();
Object resource = ctx.lookup("java:comp/env/" + annotation.name());
field.set(managedBean, resource);
} catch (Exception e) {
throw new InjectionProviderException("cannot find resource " + annotation.name(), e);
}
}
}
}
}
}
Answering my own question, an improved version of #JeffE's answer. The basic problem is:
A Tomcat6InjectionProvider was provided with JSF 2.0 but was removed at some point.
The default WebContainerInjectionProvider doesn't process #Resource annotations, as JeffE points out.
You can overcome this without web.xml context-entries as follows:
Create a file called META-INF/services/com.sun.faces.spi.injectionprovider and add the following line to it:
com.sun.faces.vendor.Tomcat7InjectionProvider:org.apache.catalina.core.DefaultInstanceManager
The meaning of this line is that if the second class is present in the deployment, the first class is used as the injection provider. The second class above is part of Tomcat 7.
Compile the following class.
This version contains numerous improvements over JeffE's version. Specifically:
it processes superclasses, as required by the #Resource and #Resources Javadoc
it processes #Resource and #Resources annotations at the class level
it processes methods annotated with #Resource, as required by the #Resource Javadoc
it handles empty or missing name attributes of #Resources correctly, as required by the #Resource Javadoc
it restores the Field's original access
it has no dependencies on Tomcat classes.
Adjust the package name above if you change its package name.
package com.sun.faces.vendor;
import com.sun.faces.spi.DiscoverableInjectionProvider;
import com.sun.faces.spi.InjectionProviderException;
import java.lang.reflect.Field;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.Resource;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.ServletContext;
/**
* #author Jeff E
* #author Esmond Pitt Improvements named above.
*
* #see javax.annotation.Resource
*
* #see <a href="http://stackoverflow.com/a/21978577/207421">This StackOverflow
* answer, although what org.apache.catalina.util.Introspection may be and where
* it lives remains a mystery.</a>
*/
public class Tomcat7InjectionProvider
extends DiscoverableInjectionProvider
{
private Logger logger = Logger.getLogger(this.getClass().getName());
private ServletContext servletContext;
private WebContainerInjectionProvider delegate = new WebContainerInjectionProvider();
public Tomcat7InjectionProvider(ServletContext servletContext)
{
logger.config("constructed");
this.servletContext = servletContext;
}
#Override
public void inject(Object managedBean) throws InjectionProviderException
{
logger.log(Level.CONFIG, "managedBean={0}", new Object[]{managedBean.getClass().getName()});
Class<?> clazz = managedBean.getClass();
do
{
List<Resource> classResources = new LinkedList<>();
// Process class-level #Resources and #Resource
if (clazz.isAnnotationPresent(Resources.class))
{
Resources annotation = clazz.getAnnotation(Resources.class);
for (Resource resource : annotation.value())
{
classResources.add(resource);
}
}
if (clazz.isAnnotationPresent(Resource.class))
{
Resource annotation = clazz.getAnnotation(Resource.class);
classResources.add(annotation);
}
for (Resource annotation : classResources)
{
String name = annotation.name();
// Make sure the resource exists.
try
{
Context ctx = new InitialContext();
Object resource = ctx.lookup("java:comp/env/" + name);
}
catch (NamingException exc)
{
throw new InjectionProviderException("checking class resource " + annotation.name()+" of "+clazz.getName(), exc);
}
}
// Process fields with #Resource
// see org.apache.catalina.core.DefaultInstanceManager
// Field[] fields = Introspection.getDeclaredFields(managedBean.getClass());
Field[] fields = managedBean.getClass().getDeclaredFields();
for (Field field : fields)
{
if (field.isAnnotationPresent(Resource.class))
{
Resource annotation = field.getAnnotation(Resource.class);
String name = annotation.name();
logger.log(Level.CONFIG, "injecting #Resource(name=\"{2}\") into {0}.{1}", new Object[]
{
managedBean.getClass().getName(), field.getName(), name
});
try
{
Context ctx = new InitialContext();
Object resource;
if (name != null && name.length() > 0)
{
resource = ctx.lookup("java:comp/env/" + name);
}
else
{
resource = ctx.lookup(clazz.getName() + "/" + field.getName());
}
// field may be private
boolean accessibility = field.isAccessible();
try
{
field.setAccessible(true);
field.set(managedBean, resource);
}
finally
{
field.setAccessible(accessibility);
}
}
catch (NamingException | IllegalAccessException exc)
{
throw new InjectionProviderException("injecting resource " + annotation.name()+" into "+clazz.getName()+"."+field.getName(), exc);
}
}
}
// Process methods with #Resource
for (Method method : clazz.getDeclaredMethods())
{
if (method.isAnnotationPresent(Resource.class)
&& method.getName().startsWith("set")
&& method.getName().length() > 3
&& method.getReturnType() == void.class
&& method.getParameterTypes().length == 1)
{
// It's a setter with #Resource
Resource annotation = method.getAnnotation(Resource.class);
String name = annotation.name();
logger.log(Level.CONFIG, "injecting #Resource(name=\"{2}\") via {0}.{1}", new Object[]
{
managedBean.getClass().getName(), method.getName(), name
});
try
{
Context ctx = new InitialContext();
Object resource;
if (name != null && name.length() > 0)
{
resource = ctx.lookup("java:comp/env/" + name);
}
else
{
name = method.getName().substring(3);
name = name.substring(0,1).toLowerCase()+name.substring(1);
resource = ctx.lookup(clazz.getName() + "/" + name);
}
// method may be private
boolean accessibility = method.isAccessible();
try
{
method.setAccessible(true);
method.invoke(managedBean, resource);
}
finally
{
method.setAccessible(accessibility);
}
}
catch (NamingException | IllegalAccessException | InvocationTargetException exc)
{
throw new InjectionProviderException("injecting resource " + annotation.name()+" via "+clazz.getName()+"."+method.getName(), exc);
}
}
}
} while ((clazz = clazz.getSuperclass()) != Object.class);
}
#Override
public void invokePostConstruct(Object managedBean) throws InjectionProviderException
{
logger.log(Level.CONFIG, "managedBean={0}", new Object[]{managedBean});
delegate.invokePostConstruct(managedBean);
}
#Override
public void invokePreDestroy(Object managedBean) throws InjectionProviderException
{
logger.log(Level.CONFIG, "managedBean={0}", new Object[]{managedBean});
delegate.invokePreDestroy(managedBean);
}
}
E&OE
Another possibility, yet I would think unlikely; is you are using metadata-complete="true" in your web.xml or web-fragment.xml file(s).
Defined metadata-complete:
The metadata-complete attribute defines whether this deployment descriptor and other related deployment
descriptors for this module (e.g., web service descriptors) are complete, or whether the class files available
to this module and packaged with this application should be examined for annotations that specify
deployment information. If metadata-complete is set to "true", the deployment tool must ignore any
annotations that specify deployment information, which might be present in the class files of the
application. If metadata-complete is not specified or is set to "false", the deployment tool must examine the
class files of the application for annotations, as specified by the specifications.
Example web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app metadata-complete="true" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>ResourceTest</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
</web-app>
Sorry I'm unable to comment due to rep or I would of asked for more clarification on what errors/etc you are seeing. That being said I have tested with both Tomcat 7.0.27 and Tomcat 7.0.41 with java full version "1.6.0_51-b11-457" and was able to use #Resource.
Context.xml
<?xml version="1.0" encoding="UTF-8"?>
<Context>
<Resource name="jdbc/Sample" auth="Container"
type="javax.sql.DataSource" username="nbuser" password="nbuser"
driverClassName="org.apache.derby.jdbc.ClientDriver"
url="jdbc:derby://localhost/Sample"
maxActive="8" maxIdle="4"/>
</Context>
ResourceTest.java
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import javax.annotation.Resource;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;
#WebServlet("/ResourceTest")
public class ResourceTest extends HttpServlet {
private static final long serialVersionUID = 1L;
#Resource(name="jdbc/Sample")
private DataSource ds;
public ResourceTest() {
// TODO Auto-generated constructor stub
}
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
PrintWriter out = response.getWriter();
out.println("<body>");
try {
//Context initCtx = new InitialContext();
//Context envCtx = (Context) initCtx.lookup("java:comp/env");
//DataSource ds = (DataSource) envCtx.lookup("jdbc/Sample");
Connection conn = ds.getConnection();
Statement s = conn.createStatement();
s.execute("Select * From \"NBUSER\".\"Friends\"");
ResultSet rs = s.getResultSet();
while (rs.next()) {
out.println(rs.getString("NAME") + " is my friend.");
}
conn.close();
} catch (Exception ex) {
ex.printStackTrace();
}
out.println("</body>");
}
/**
* #see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
}
}