Eureka+Cloud-Config with Wildfly and deployment order - java

I need to integrate some SpringBoot services in a Wildfly environment.
There is a Eureka-Server+Cloud Config-Service runing as a WAR in a wildfly. I cannot see the dashboard, but I can see the self-registered service in the XML data in ..eureka/apps
If I start a SpringBoot client for Eureka/Cloud Config in a standalone mode - it connects perfectly to this Wildfly/Eureka/CloudConfig service. The same, when I add this client as a WAR into the already running Wildfly/Eureka/CloudConfig system.
But when I kill the server and restart it, the parallel deployment of the two WARs produce of course a lot of exception during startup. Thats ok, because the Eureka Server isn't up yet. But after it's - the client registeres itself correctly to the Eureka server (I see it in eureka/apps again). But the client sends exceptions all the time.
2018-06-22 12:40:10,345 WARN [org.springframework.cloud.config.client.DiscoveryClientConfigServiceBootstrapConfiguration] (DiscoveryClient-CacheRefreshExecutor-0) Could not locate configserver via discovery: java.lang.IllegalStateException: No instances found of configserver (EUREKA-DISCOVERY-SERVICE)
at org.springframework.cloud.config.client.ConfigServerInstanceProvider.getConfigServerInstance(ConfigServerInstanceProvider.java:25)
at org.springframework.cloud.config.client.DiscoveryClientConfigServiceBootstrapConfiguration.refresh(DiscoveryClientConfigServiceBootstrapConfiguration.java:80)
at org.springframework.cloud.config.client.DiscoveryClientConfigServiceBootstrapConfiguration.heartbeat(DiscoveryClientConfigServiceBootstrapConfiguration.java:72)
at sun.reflect.GeneratedMethodAccessor122.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.context.event.ApplicationListenerMethodAdapter.doInvoke(ApplicationListenerMethodAdapter.java:261)
at org.springframework.context.event.ApplicationListenerMethodAdapter.processEvent(ApplicationListenerMethodAdapter.java:180)
at org.springframework.context.event.ApplicationListenerMethodAdapter.onApplicationEvent(ApplicationListenerMethodAdapter.java:142)
at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172)
at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139)
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:400)
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:406)
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:354)
at org.springframework.cloud.netflix.eureka.CloudEurekaClient.onCacheRefreshed(CloudEurekaClient.java:112)
at com.netflix.discovery.DiscoveryClient.fetchRegistry(DiscoveryClient.java:981)
at com.netflix.discovery.DiscoveryClient.refreshRegistry(DiscoveryClient.java:1471)
at com.netflix.discovery.DiscoveryClient$CacheRefreshThread.run(DiscoveryClient.java:1438)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
The exception comes every 30sec (refresh time).
I don't understand, why this happens. The ...eureka/apps result shows the service
<applications>
<versions__delta>1</versions__delta>
<apps__hashcode>UP_2_</apps__hashcode>
<application>
<name>EUREKA-DISCOVERY-SERVICE</name>
<instance>
<instanceId>192.168.207.94:eureka-discovery-service:8443</instanceId>
<hostName>localhost</hostName>
<app>EUREKA-DISCOVERY-SERVICE</app>
<ipAddr>192.168.207.94</ipAddr>
<status>UP</status>
<overriddenstatus>UNKNOWN</overriddenstatus>
<port enabled="false">80</port>
<securePort enabled="true">8443</securePort>
<countryId>1</countryId>
<dataCenterInfo class="com.netflix.appinfo.InstanceInfo$DefaultDataCenterInfo">
<name>MyOwn</name>
</dataCenterInfo>
<leaseInfo>
<renewalIntervalInSecs>30</renewalIntervalInSecs>
<durationInSecs>90</durationInSecs>
<registrationTimestamp>1529662231729</registrationTimestamp>
<lastRenewalTimestamp>1529663993904</lastRenewalTimestamp>
<evictionTimestamp>0</evictionTimestamp>
<serviceUpTimestamp>1529662210687</serviceUpTimestamp>
</leaseInfo>
<metadata>
<management.port>8443</management.port>
<configPath>/eureka-ds/config</configPath>
</metadata>
<homePageUrl>http://localhost:80/</homePageUrl>
<statusPageUrl>http://localhost:8443/actuator/info</statusPageUrl>
<healthCheckUrl>http://localhost:8443/actuator/health</healthCheckUrl>
<secureHealthCheckUrl>https://localhost:8443/actuator/health</secureHealthCheckUrl>
<vipAddress>eureka-discovery-service</vipAddress>
<secureVipAddress>eureka-discovery-service</secureVipAddress>
<isCoordinatingDiscoveryServer>true</isCoordinatingDiscoveryServer>
<lastUpdatedTimestamp>1529662231729</lastUpdatedTimestamp>
<lastDirtyTimestamp>1529662193289</lastDirtyTimestamp>
<actionType>ADDED</actionType>
</instance>
</application>
<application>
<name>MARK2</name>
<instance>
<instanceId>192.168.207.94:mark2:9998</instanceId>
<hostName>192.168.207.94</hostName>
<app>MARK2</app>
<ipAddr>192.168.207.94</ipAddr>
<status>UP</status>
<overriddenstatus>UNKNOWN</overriddenstatus>
<port enabled="true">9998</port>
<securePort enabled="false">443</securePort>
<countryId>1</countryId>
<dataCenterInfo class="com.netflix.appinfo.InstanceInfo$DefaultDataCenterInfo">
<name>MyOwn</name>
</dataCenterInfo>
<leaseInfo>
<renewalIntervalInSecs>30</renewalIntervalInSecs>
<durationInSecs>90</durationInSecs>
<registrationTimestamp>1529662210686</registrationTimestamp>
<lastRenewalTimestamp>1529663979339</lastRenewalTimestamp>
<evictionTimestamp>0</evictionTimestamp>
<serviceUpTimestamp>1529662210687</serviceUpTimestamp>
</leaseInfo>
<metadata>
<management.port>9998</management.port>
<configPath>/eureka-ds/config</configPath>
<user>user</user>
<password>software1</password>
</metadata>
<homePageUrl>http://192.168.207.94:9998/</homePageUrl>
<statusPageUrl>http://192.168.207.94:9998/actuator/info</statusPageUrl>
<healthCheckUrl>http://192.168.207.94:9998/actuator/health</healthCheckUrl>
<vipAddress>mark2</vipAddress>
<secureVipAddress>mark2</secureVipAddress>
<isCoordinatingDiscoveryServer>false</isCoordinatingDiscoveryServer>
<lastUpdatedTimestamp>1529662210687</lastUpdatedTimestamp>
<lastDirtyTimestamp>1529662208806</lastDirtyTimestamp>
<actionType>ADDED</actionType>
</instance>
</application>
</applications>

This answer may be helpful for the error No instances found of configserver(configserver),
Spring Cloud Config Server has the default name as "configserver" If you override this name using the spring.application.name=my-config-server in application.properties then in the Config Client application's bootstrap.properties you need to use spring.cloud.config.discovery.service-id=my-config-server
Sample Config Server
spring.application.name=my-config-server
eureka.instance.hostname=localhost
server.port=8888
spring.cloud.config.server.git.uri=file:////Users/asadhat/work/lab/spring-cloud
eureka.client.service-url.defaultZone=http://localhost:8761/eureka/
Sample Config Client
spring.application.name=my-config-client
server.port=7000
eureka.instance.hostname=localhost
spring.cloud.config.discovery.enabled=true
eureka.client.service-url.defaultZone=http://localhost:8761/eureka/
spring.cloud.config.discovery.service-id=my-config-server

I found a way, to get it work.
If I set spring.cloud.config.fail-fast=false (which is the default) then the service makes multiple retries. Then during bootstrap the service sends errors, but after the config server is up, the client service registeres and everything is ok. That takes some seconds...
then - I learned, do not put Eureka server and Cloud config server in one service. Even it is a good idea to reduce the minimize the infrastructure, the cloud config service is a little bit triggy and needs full access to the URL path. Even defining prefixe doesn't really work because of a minor bug (there is a pull request).
third - in a Wildfly environment define the StatusPageURLPath and HealthCheckURLPath correctly (see above, it's wrong)

Related

IIS rewrite rule with Tomcat 9.0

I have deployed a Spring Boot application in Tomcat in Windows Server and it's accessible on browser via http://server-name:8080/app. Now, for end users I don't want them to hit the app at port 8080, so I have configured an IIS rewrite rule
<rule name="app" enabled="true" stopProcessing="false">
<match url="^app.*" />
<action type="Rewrite" url="http://server-name:8080/{R:0}" logRewriteUrl="true" />
</rule>
Now, when I hit http://server-name/app, it works, but the subsequent calls are going to http://server-name:8080/app.
I am not sure if there is a problem with the IIS rule since I ran the app.war using same application.properties as
java -jar app.war --server.port=8080 --spring.config.import=application.properties
The only caveat here is I am passing context path in properties as
server.servlet.context-path=/app
and in this scenario all the URL calls go without port 8080. If anyone have any insight or solution, please share.
Please NOTE: I can't host Tomcat on port 80 as there are other apps running on port 80 which uses the API from app deployed in Tomcat.

Java application calling WCF returns "Connection Reset" while SoapUI works fine

I have a C# MVC application (.NET framework 4.6.2) with a WCF (soap based) web service located at /webservice inside the application. The WCF web service is for a 3rd party vendor to call and push their data to. We have the application in a test environment on a Windows Server 2016 server with ports 80 and 443 open and our certs aren't selfsigned and valid. When we test the service using SoapUI, we are able to correctly get to the WCF web service and post the test data to the server but when our vendor posts the data from their Java application they get "Connection Reset". We've removed all authentication and are just trying to get them to reach the WCF but our IIS logs and application logs don't even show them hitting our server. SoapUI (both inside and outside our network/firewall) is able to hit the service correctly. Our web.config looks like this:
<system.serviceModel>
<diagnostics>
<messageLogging logEntireMessage="true" logMalformedMessages="true" logMessagesAtServiceLevel="true" logMessagesAtTransportLevel="true" maxMessagesToLog="3000"/>
</diagnostics>
<bindings>
<basicHttpBinding>
<binding name="basicBinding" textEncoding="utf-8" openTimeout="00:03:00" closeTimeout="00:03:00"/>
</basicHttpBinding>
</bindings>
<services>
<service behaviorConfiguration="serviceBehavior" name="WebServiceUniqueName">
<endpoint address="/endpoint/soap" binding="basicHttpBinding" bindingConfiguration="basicBinding" name="soapEndpoint" bindingNamespace="https://test.site.com/webservice" contract="Our.Namespace.ISoapContract"/>
<endpoint address="mex" binding="mexHttpBinding" name="mexEndpoint" contract="IMetadataExchange"/>
<host>
<baseAddresses>
<add baseAddress="/webservice/servicename"/>
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="serviceBehavior">
<serviceMetadata externalMetadataLocation="https://test.site.com/webservice/content.xml"
httpGetEnabled="true" />
<serviceDebug httpHelpPageEnabled="false" includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"/>
and the code for our WCF looks like this:
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
[ServiceBehavior(Namespace = "https://test.site.com/webservice")]
public class MyService : ISoapContract
{
public DataResponse SubmitData(DataRequest input)
{
// Code here
}
}
namespace Our.Namespace
{
[ServiceContract(Namespace = "https://test.site.com/webservice")]
[XmlSerializerFormat]
public interface ISoapContract
{
[OperationContract(Name = "SubmitData")]
[XmlSerializerFormat]
DataResponse SubmitData(DataRequest input);
}
}
Our server works with TLS 1.2 and falls back to 1.1 (exactly what the vendor is expecting). Our firewall isn't showing anything being blocked and the "Connection Reset" message is within the first few seconds of their request. The 3rd party is able to access the WSDL from their browsers, so all of this leads me to believe there is something failing during the handshake. SoapUI is coming through and that runs on Java, so we are really stumped at this point. Does Java calling a C# WCF application require something extra? Is there a way to capture a handshake attempt?
Update after more testing:
We took Sambit's advice and used the Microsoft web service client and that worked without any problems. We created another test WCF and also created an app that called our server and put both in Azure without any problems. We could reach our web service but the vendor still can't reach the server. We added more logging and looked at the firewall and the traffic from the vendor was getting through the firewall and to the server but was reporting "TCP reset from server".
The 3rd party vendor's application was hosted in a shared environment and they are able to run commands on their server but they can't change any code to log extra information. They were able to ping our server and run the following command:
nc -zv (server_url) 443
And that connected successfully but when they attempted to get the cert from the server, that failed:
openssl s_client -tls1_2 -showcerts -connect (server_url):443
CONNECTED(00000003) write:errno=104
--- no peer certificate available
--- No client certificate CA names sent
After help from a lot of really smart people on both sides, the problem ended up being Server Name Indication (SNI):
https://en.wikipedia.org/wiki/Server_Name_Indication
The vendor's application is running an old version of Java that doesn't understand/support SNI and they aren't able to upgrade at this time.
Our server admins dedicated an IP on our Windows Server for the domain being called by the vendor and disabled SNI for that particular domain. We are now able to receive the vendor's web server calls without any problems.

Is it possible to configure a failover for JMS-Bridge to a JMS-Cluster with Wildfly 10?

I have two JMS-Servers which are linked together as a JMS-Cluster in a standalone-full-ha environment. These servers are hosting my JMS-Destinations (let’s call them JMS-Master).
Additionally there is a server which is configured as standalone-full server (let’s name it JMS-Slave). This server has a JMS-Bridge to a JMS-Topic.
For this configuration I created at the JMS-Slave two socket bindings to the remote servers:
<outbound-socket-binding name="remote-server-1">
<remote-destination host="a.b.c.d" port="8080"/>
</outbound-socket-binding>
<outbound-socket-binding name="remote-server-2">
<remote-destination host="a.b.c.d" port="18080"/>
</outbound-socket-binding>
I use them at two http-connectors at the messaging subsystem configuration:
<http-connector name="remote-1-http-connector" socket-binding="remote-server-1" endpoint="http-acceptor"/>
<http-connector name="remote-2-http-connector" socket-binding="remote-server-2" endpoint="http-acceptor"/>
And I created a pooled-connection-factory:
<pooled-connection-factory name="remote-connection" entries="java:/jms/remoteCF" connectors="remote-1-http-connector remote-2-http-connector" user="testuser" password="testpassword" failover-on-initial-connection="true"/>
Finally I configure the JMS-Bridge:
<jms-bridge name="HelloWorldQueue-jms-bridge" quality-of-service="DUPLICATES_OK" failure-retry-interval="5000" max-retries="-1" max-batch-size="10" max-batch-time="100">
<source connection-factory="ConnectionFactory" destination="queue/HelloWorldQueue"/>
<target connection-factory="jms/RemoteConnectionFactory" destination="queue/HelloWorldQueue" user="heinz" password="becker" >
<target-context>
<property name="java.naming.factory.initial" value="org.jboss.naming.remote.client.InitialContextFactory"/>
<property name="java.naming.provider.url" value="http-remoting://a.b.c.d:8080, http-remoting://a.b.c.d:18080"/>
</target-context>
</target>
</jms-bridge>
The result:
If both JMS-Master servers are up and I start the JMS-Slave,
everything works.
If one of JMS-Master servers is down and I start the JMS-Slave, it
works as well. The jms-bridge connects to the available node.
But if I shutdown the node to which the JMS Bridge of the JMS-Slave
is connected there is no failover.
I am looking for a configuration where the JMS-Bridge is “reconnecting” after a crash to the available node without having it into the same cluster than the JMS-Master.
How can I achieve this? Are there other possibilities to get a similar behavior? Or is there a proposal for a complete different setup?
I think I found two possible solutions for the problem myself. But they have both some disadvantages.
The first one is to use a JMS-Core-Bridge. See Configuring Core Bridges at the Red Hat JBoss docs:
Do not confuse a core bridge with a JMS bridge. A core bridge is used
to bridge any two JBoss EAP messaging instances and uses the core API.
A JMS bridge can be used to bridge any two JMS 1.1 compliant JMS
providers and uses the JMS API. It is preferable to use a core bridge
instead of a JMS bridge whenever possible.
The Core-Bridge does a fail-over more or less out of the box. Already with one connector it would do a failover automatically. It retrieves the cluster topology during the first connect and uses it during its lifetime. And to be able to start the bridge if a JMS-Master is down, we can add additional connectors:
<subsystem xmlns="urn:jboss:domain:messaging-activemq:1.0">
<server name="default">
....
<bridge name="my-core-bridge" static-connectors="remote-1-http-connector remote-2-http-connector" queue-name="jms.queue.HelloWorldQueue" user="username" password="pwd"/>
</server>
...
</subsystem>
The disadvantage of a core-bridge seems to be that it does not support JMS-Topics out of the box. Only JMS-Queues seem to work without overhead.
But it is possible as well to configure a JMS-Bridge that it reconnects to another server. To establish a connection, the JMS-Bridge proceeds a JNDI-lookup at one of the servers configured by the property "java.naming.provider.url". This lookup is just executed during startup and once it is done, it uses the retrieved remote connection-factory (here named RemoteConnectionFactory) to connect and reconnect. But it is using the RemoteConnectionFactory of the JMS-Master! Therfore it is necessary to
configure the this connection factory there:
<connection-factory name="RemoteConnectionFactory" entries="java:jboss/exported/jms/RemoteConnectionFactory" connectors="master-1-http-connector master-2-http-connector" ha="true" block-on-acknowledge="true" reconnect-attempts="-1"/>
If this RemoteConnectionFactory has a connector to each JMS-Master, the JMS-Bridge retrieves all necessary information to do a reconnect to another server, if necessary. The bridge configuration of my question is working now without modification:
<jms-bridge name="HelloWorldQueue-jms-bridge" quality-of-service="DUPLICATES_OK" failure-retry-interval="5000" max-retries="-1" max-batch-size="10" max-batch-time="100">
<source connection-factory="ConnectionFactory" destination="queue/HelloWorldQueue"/>
<target connection-factory="jms/RemoteConnectionFactory" destination="queue/HelloWorldQueue" user="username" password="pwd" >
<target-context>
<property name="java.naming.factory.initial" value="org.jboss.naming.remote.client.InitialContextFactory"/>
<property name="java.naming.provider.url" value="http-remoting://a.b.c.d:8080, http-remoting://a.b.c.d:18080"/>
</target-context>
</target>
</jms-bridge>
The disadvantage of my "jms-bridge configuration" is its complexity.

windows single sign on tomcat through IIS Url rewrite

I'm facing a difficult setup where I have to configure single sign on, based on the logged in used on my tomcat application.
I already took some steps which allow me to login via single sign on directly on my tomcat application by using waffle.
I have 1 server where I have a tomcat running and a IIS running (but this IIS will move to another server in the same domain in the future).
I have the Tomcat running on port 8205 and the IIS configure to accept url's from authpoc.company.com. IIS does a redirect to localhost:8025 via URL Rewrite.
My web.xml from IIS
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="ReverseProxyInboundRule1">
<match url="(.*)" />
<action type="Rewrite" url="http://localhost:8205/{R:1}" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
What works
When opening the application directly on localhost:8205 on the server. I get a nice single sign on based on my domain user.
When opening the application directly on the ip of the server. 192.168.1.1:8205. I can log in but single sign on does not work anymore. This I don't understand. (edit: solved, this is a setting in Internet explorer, see SSO waffle asking username and password for more information)
What doesn't work
When redirecting from IIS, I don't get to login into my tomcat application. I have windows authentication enabled, with Negotiate and NTML enabled (in this sequence).
I read a lot on the internet but I can't find anyone with this particular setup. I don't really have the impression I'm doing something exotic.
One possiblity is that I should connect IIS via AJP instead of a much simpeler URL rewrite.
any help is welcome! Thanks
I got an answer on the google groups saying this is not possible because of the reverse proxy counting as a hop.
https://groups.google.com/forum/#!topic/waffle-users/VCaawJMD0Mw
I'm going to try another approach

Tomcat 8 Manager, HTML and Text running, access from ANT Connection Refused

first time poster here. I'm setting up a new Tomcat 8 instance and I'm trying to utilize tomcat 8 manager from my build.xml script (via IntelliJ). I'm using the list command to test the connection, but want I really want is stop/start/redeploy/etc. I've tested both manager/text/ and manager/html succesfully.
[Windows 7 box]
Code snippets incoming
tomcat-users.xml:
<role rolename="admin-gui"/>
<role rolename="manager-script" />
<role rolename="manager-gui" />
<user username="script" password="test" roles="admin-gui,manager-script"/>
<user username="manager" password="test" roles="admin-gui,manager-gui"/>
build.xml:
<target name="list"
description="List installed applications on servlet container">
<echo>List Using:(${manager.url}) [${manager.username}|${manager.password}]</echo>
<list url="${manager.url}"
username="${manager.username}"
password="${manager.password}"/>
</target>
Output from 'list' task from IntelliJ:
List Using:(http://localhost:8080/manager/text) [script|test]
Task: list
C:\apps\myapp\build.xml:478: java.net.ConnectException: Connection refused: connect
at org.apache.catalina.ant.AbstractCatalinaTask.execute(AbstractCatalinaTask.java:269)
...etc
Every tutorial I go to talks about setting up Tomcat-Users.xml or opening port 8443 for the manager, but I haven't seen an answer for what to do if you have confirmed manager is running (it is) but build.xml/ANT seem have trouble getting authorized.
Things to check:
Have you actually confirmed that manager app is deployed to the /manager context? It's only deployed by default on the default host. For other virtual hosts, this is something you must do manually. Try visiting http://localhost:8080/manager with your web browser. Try logging in with the manager-gui user.
Does your tomcat instance run more than one virtual host? If so, it's possible that your ant task is hitting a different virtual host than one you want. Check your $CATALINA_HOME/conf/server.xml file's <Engine> and <Host> elements. Does <Engine> contain just one <Host>? If it contains multiple hosts, whate are the name attributes set to? What is the defaultHost attribute of <Engine> set to?

Categories

Resources