FCM XMPP java server app - google-app-engine

I want to deploy a FCM XMPP app on Google AppEngine. I'm using this library https://github.com/thelong1EU/fcmxmppserver but I'm new on this backend side so I need some help. I managed to deploy it but it doesn't run. I don't know how to make the AppEngine call the main funtion here:
public class EntryPoint {
public static void main(String[] args) {
final String fcmProjectSenderId = senderID;
final String fcmServerKey = key;
CcsClient ccsClient = CcsClient.prepareClient(fcmProjectSenderId, fcmServerKey, false);
try {
ccsClient.connect();
} catch (XMPPException e) {
e.printStackTrace();
}
}
}
If i run just this function it all works well, but when deployed it doesn't start. What am I missing?

So I found out reading this:
https://cloud.google.com/appengine/docs/standard/java/an-overview-of-app-engine#scaling_types_and_instance_classes
When the app load it does a GET to /_ah/stop so I needed to add this to my servlet mapping. I did it like this:
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee">
<servlet>
<servlet-name>Start</servlet-name>
<servlet-class>eu.long1.jwnotes.fcmserver.StartServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Start</servlet-name>
<url-pattern>/_ah/start</url-pattern>
<url-pattern>/_ah/stop</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
</web-app>
And the in the doGet() I do this:
public class StartServlet extends HttpServlet {
private static final String GET_START = "/_ah/start";
private static final String GET_STOP = "/_ah/stop";
#Override
public void init() throws ServletException {
//init the servlet
}
#Override
public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws IOException {
switch (req.getRequestURI()) {
case GET_START:
//do something
resp.setStatus(SC_OK);
break;
case GET_STOP:
//do something else
break;
}
}
}
I don't know if this is the recommended way but it works for now. If I find something else I will post.

Related

Spring Oauth2 + User Registration

I have problem with Spring Oauth2 again. I know this topic is not easy to suggest sth or check the codes because we have too much configuration.
My project has 3 different servers, Authentication server, resource server and front-end server. I want to put register.html to user's registration in front-end project(under Angularjs files) but when I make request to the related url (http://localhost:7080/app/#register) its redirecting to the login page (http://localhost:9080/auth-service/login) only for a second i can see my register.html content but after that its going to login page.
The question is, where should i put this register.html, it should be under front-end project or authentication server ?
My authentication server and front-end server codes are;
#Configuration
public class AuthServerSecurityConfiguration extends WebSecurityConfigurerAdapter {
#Autowired
private AuthenticationManager authenticationManager;
#Override
protected void configure(AuthenticationManagerBuilder auth)
throws Exception {
auth.parentAuthenticationManager(authenticationManager);
auth.authenticationProvider(userAuthProviderService());
}
private CsrfMatcher csrfRequestMatcher = new CsrfMatcher();
#Override
protected void configure(final HttpSecurity http) throws Exception {
/*http.csrf().disable();*/
http.csrf().requireCsrfProtectionMatcher(csrfRequestMatcher);
http
.formLogin().loginPage("/login").defaultSuccessUrl("/")
/*.failureUrl("")*/.successHandler(new AuthSuccessHandler()).permitAll()
.and()
.requestMatchers().antMatchers("/login", "/oauth/authorize", "/oauth/confirm_access","/register")
.and()
.authorizeRequests().anyRequest().authenticated();
}
#Bean
public UserAuthProviderService userAuthProviderService(){
return new UserAuthProviderService();
}
private class CsrfMatcher implements RequestMatcher {
#Override
public boolean matches(HttpServletRequest request) {
return false;
}
}
}
#Configuration
#EnableAutoConfiguration
#RestController
#EnableZuulProxy
#EnableOAuth2Sso
#EnableOAuth2Client
public class UIServiceMain {
public static void main(String[] args) {
SpringApplication.run(UIServiceMain.class, args);
}
#Configuration
protected static class SecurityConfiguration extends OAuth2SsoConfigurerAdapter {
#Override
public void configure(HttpSecurity http) throws Exception {
http.logout().and()
.antMatcher("/**").authorizeRequests()
.antMatchers("/index.html", "/home.html", "/", "/login","/register.html").permitAll().anyRequest()
.authenticated().and().csrf().disable();
http.headers().frameOptions().disable(); //FOR EMBED MAP
}
//unused
private Filter csrfHeaderFilter() {
return new OncePerRequestFilter() {
#Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class
.getName());
if (csrf != null) {
Cookie cookie = WebUtils.getCookie(request, "XSRF-TOKEN");
String token = csrf.getToken();
if (cookie == null || token != null
&& !token.equals(cookie.getValue())) {
cookie = new Cookie("XSRF-TOKEN", token);
cookie.setPath("/");
response.addCookie(cookie);
}
}
filterChain.doFilter(request, response);
}
};
}
//unused
private CsrfTokenRepository csrfTokenRepository() {
HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
repository.setHeaderName("X-XSRF-TOKEN");
return repository;
}
}
}
in your UI server try to create websecurity with /register.hml enabled, something like this
#Configuration
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter{
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.requestMatchers()
.antMatchers("/register.html")
.and()
.authorizeRequests()
.anyRequest().authenticated();
}
}
edit:
or maybe in your current configuration remove .antMatcher("/**").authorizeRequests() and add and() .authorizeRequests().anyRequest().authenticated()
so finally it could be something like this:
#Override
public void configure(HttpSecurity http) throws Exception {
http.logout().and()
.antMatchers("/index.html", "/home.html", "/", "/login","/register.html").permitAll().anyRequest()
.authenticated()
.and().csrf().disable();
http.headers().frameOptions().disable() //FOR EMBED MAP
.and()
.authorizeRequests()
.anyRequest().authenticated();
}
Couple of things:
I can't think of a good reason not to put your *.html anywhere other than front end server.
Also, in general, you should permit access to your static UI components publically, like #bilak mentioned:
.antMatchers("/index.html", "/home.html", "/", "/login","/register.html").permitAll()
If you are able to see register.html page at all (assuming unauthenticated user) then it is public already
Perhaps, there is a webservice call on register.html's load event that is behind Spring security that is triggering the auth flow.

Example of registering classes for Objectify using ServletContextListener

I have read a couple of articles, including Objectify's documentation in Github, that the best practice on registering classes for Objectify purpose is to use ServletContextListener in web.xml. Unfortunately, I couldn't find any example for the Google App Engine (endpoint) scenario.
Does anyone have an example that I can follow?
Thanks!
First, enable ObjectifyFilter in web.xml if you haven't done so already
<filter>
<filter-name>ObjectifyFilter</filter-name>
<filter-class>com.googlecode.objectify.ObjectifyFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>ObjectifyFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Then what I do is to create a class like this:
public class OfyService {
private static final Logger logger = Logger.getLogger(OfyService.class.getName());
static {
try {
ObjectifyService.register(EntityA.class);
/* ... more entities ... */
} catch (Exception e) {
logger.log(Level.SEVERE, e.toString());
}
}
public static Objectify ofy() {
return ObjectifyService.ofy();
}
public static ObjectifyFactory factory() {
return ObjectifyService.factory();
}
}
In my endpoint methods I then use Objectify with OfyService.ofy().load().type(EntityA.class)....
The answer I am looking for is here: ...I already have the setup you suggested, however, it will occasionally give me the "class not registered error"
Adding a Listener to your web.xml
<listener>
<listener-class>[Fully qualified name of your class]</listener-class>
</listener>
And implements the ServletContextListener, and start to register your entities as below:
public class BootstrapListener implements ServletContextListener {
#Override
public void contextInitialized(ServletContextEvent sce) {
ObjectifyFactory factory= ObjectifyService.factory();
factory.register(**[YOUR_ENTITY]**.class);
}

Camel blueprint testing and cucumber

Is it possible to combine cucumber with CamelBlueprintTestSupport? I have my runner class:
#RunWith(Cucumber.class)
#CucumberOptions(monochrome=true,
format={ "pretty", "html:target/cucumber"},
features = "C:/Users/Developer/workspace_camel/SRV002_PatronInformation/src/test/resources/cucumber/asynchronousErrorHandling.feature")
public class RunFeature_SRV002_PatronInformationTest {
}
and my blueprint test class with the scenarios:
public class SRV002_PatronInformationScenarioTest extends CamelBlueprintTestSupport {
#Override
protected String getBlueprintDescriptor() {
return "/OSGI-INF/blueprint/blueprint.xml";
}
#Given("^client communicates asynchronous via socket$")
public void client_communicates_asynchronous_via_socket() throws Throwable {
System.out.println("test");
}
#When("^client posts message$")
public void an_error_occurs_inside_the_integration() throws Throwable {
String endpoint = "netty4:tcp://localhost:5000?sync=false&textline=true";
template.sendBody(endpoint, "test");
}
#Then("^the integration should not return response to the client$")
public void the_integration_should_not_return_the_error_to_the_client() throws Throwable {
System.out.println("test");
}
}
The problem now is that, when I run this I run into nullpointerexception at template.sendbody because the context, bundle and routes haven't started. For some reason it seems adding #RunWith(Cucumber) prevents the camel routes from starting.
Anyone knows how this can be solved? Thanks
Souciance
Ok so I managed to solve this.
For reference look here:
http://camel.465427.n5.nabble.com/How-to-test-routes-when-using-another-TestRunner-td5772687.html
Thanks to Gregor Lenz for the help.
Essentially the key here is that in your Camel BlueprintTestSupport class, inside the test method, that starts the given scenario you need to add this.setUp(). See the code below:
In Cucumber
SRVXXX_FileTransferCamelRunner filetransfer = new SRVXXX_FileTransferCamelRunner();
#Given("^an input file$")
public void an_input_file() throws Throwable {
endpoint.append("file:C:/Camel/input?fileName=input.txt");
}
#When("^client puts the file in the input directory$")
public void client_puts_the_file_in_the_input_directory() throws Throwable {
filetransfer.testPutFile(fileData.toString(), endpoint.toString());
}
#Then("^the integration should move the file to the output directory$")
public void the_integration_should_move_the_file_to_the_output_directory() throws Throwable {
String outputPath = "C:/Camel/output/input.txt";
filetransfer.testFileHasMoved(outputPath);
}
In Camel
#Test
public void testPutFile(String body, String endpoint) throws Exception {
this.setUp();
template.sendBody(endpoint,body);
Thread.sleep(2000);
assertFileNotExists(endpoint);
}

Bootstrap camel in spring web application

I'm creating a application with Spring-jersey-camel. I wanted to expose my jersey layer and internally invoke camel routes to invoke resources.
web.xml
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
applicationContext.xml
<camelContext id="camelContext" xmlns="http://camel.apache.org/schema/spring">
<packageScan>
<package>com.company.myapp.camel</package>
<excludes>**.*</excludes>
<includes>*Routes.java</includes>
</packageScan>
</camelContext>
MyRoutes.java
#Component
public final class MyRoutes extends RouteBuilder {
#Override
public void configure() throws Exception {
from("direct:getOrdersData").validate(body().isNotNull())
.log("Camel to get orders")
.to("restlet:http://localhost:8081/ordersapp/rest/order/123");
}
}
OrderResourceImpl.java
#Component
#Path("/orderLookup")
public class ReservationResources {
#org.apache.camel.produce
ProducerTemplate producer;
public void setProducer(ProducerTemplate producer) throws Exception {
this.producer = producer;
}
#GET
#Produces(MediaType.APPLICATION_JSON)
#Path("{orderId}")
public Response orderLookup(#PathParam("orderId") final long orderrId){
Response r = Response.noContent().build();
//Producer is null. throws nullPointerException
String order= producer.requestBody("direct:getOrdersData", orderId, String.class);
r = Response.ok().entity(reservation).build();
return r;
}
}
Any idea what I'm doing wrong? or how to inject myRoute/ProducerTemplate im my orderResourceImpl.java. Thanks in advance
Two Options,
If ReservationResources is a spring bean then, Inject the Camel Context into it and create a ProducerTemplate from that
ProducerTemplate template = camelContext.createProducerTemplate();
If ReservationResources is not a spring bean then get the Camel Context via a static method https://stackoverflow.com/a/13633109/3696510 and then create the ProducerTemplate.
ProducerTemplate template = StaticSpringApplicationContext.getBean("camelContext").createProducerTemplate()
Also if you do use that StaticSpringApplicationContext mentioned in the link, I would add this method to it.
public static <T> T getBean(String beanName, Class<T> clazz) {
return (T) CONTEXT.getBean(beanName,clazz);
}

Error 500 when contacting webservice with cxf and guice

I'm using cfx 2.5.1 and guice 2.0.
I have this interface for the ws
#WebService(targetNamespace="http://com.example.firstapp/")
public interface IWSEchoService {
#WebMethod(operationName="echoService")
String echoService(#WebParam(name="id") String id,#WebParam(name="payload") String payload) throws SOAPFault;
#WebMethod(operationName="testAttachment")
DataHandler testAttachment(DataHandler attachment) throws SOAPFault;
}
And the implementation
#WebService(targetNamespace = "http://com.example.firstapp/")
public class WSEchoServiceImpl implements IWSEchoService {
protected Log logger = LogFactory.getLog(this.getClass());
#WebMethod(operationName = "echoService")
public String echoService(String id, String payload) throws SOAPFault {
return id + "|" + payload;
}
#WebMethod(operationName = "testAttachment")
public DataHandler testAttachment(DataHandler attachment) throws SOAPFault {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
FileUtil.copyInputStream(attachment.getInputStream(), baos);
logger.debug(baos.toString());
} catch (IOException ex) {
logger.error(ex);
}
logger.info("Attachment ok! Size: " + baos.size());
return attachment;
}
}
Also I have
public class ContextStartup implements ServletContextListener {
private Log logger = LogFactory.getLog(ContextStartup.class);
private CamelContext camelContext;
public void contextInitialized(ServletContextEvent sce) {
try {
camelContext = new GuiceCamelContext(Guice.createInjector(Stage.DEVELOPMENT, new MyModule()));
camelContext.start();
startWS();
} catch (Exception ex) {
logger.error(ex);
}
}
.....
private void startWS() {
String address = "http://localhost:8191/ws/echoService";
Endpoint.publish(address, new WSEchoServiceImpl());
}
private class MyModule extends CamelModuleWithMatchingRoutes {
#Override
protected void configure() {
super.configure();
// bind camel component
}
}
}
Finally the web.xml for tomcat
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<listener>
<description>Start and destroy CamelContext</description>
<listener-class>com.example.firstapp.ContextStartup</listener-class>
</listener>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
Now when in my browser i call
http://localhost:8191/ws/echoService?wsdl
or
http://localhost:8191/ws/echoService
i have a http 500 error, but in the console or in the tomcat log i haven't any exception or error
I also used this guide http://jax-ws-commons.java.net/guice/ but i had the same result
Did you try replacing localhost by IP ?
We faced same problem and this solved the problem.

Resources