Spring Boot Lambda Startup multiple times at the cold start - amazon-web-services

I'm writing small Data downloading service function using Spring Boot 2.7. I deployed it in the AWS lambda function. At the cold starting each time it initializes twice as shown in the image below.
Here is the lambderHandler.java
public class LambdaHandler implements RequestHandler<SQSEvent, String> {
private static final ApplicationContext applicationContext = SpringApplication.run(DataDownloaderService.class);
#Override
public String handleRequest(SQSEvent event, Context context) {
context.getLogger().log("Input: " + event);
if (!event.getRecords().isEmpty()) {
SQSEvent.SQSMessage firstRecord = event.getRecords().get(0);
String eventBody = firstRecord.getBody();
if (eventBody != null) {
ProductDownloadService productDownloadService = applicationContext.getBean(ProductDownloadServiceImpl.class);
try {
productDownloadService.downloadProductData(JsonUtil.getUserInfo(eventBody));
return "Successfully processed";
} catch (IOException e) {
return "Error in data downloading: " + e.getMessage();
}
}
}
return "Data download not success";
}
}
Here is the DataDownloaderService.java
#SpringBootApplication
#ComponentScan(basePackages = {"com.test.*"})
#EntityScan(basePackages = {"com.test.*"})
public class DataDownloaderService {
}
Why spring boot lambda function initialize multiple times at the cold start? Did I have some misconfiguration here or is it a bug?

I found a workaround to fix this issue from here.
Here is the workaround for the above code.
public class LambdaHandler implements RequestHandler<SQSEvent, String> {
private ApplicationContext applicationContext;
/**
* Entry point in the lambda function
* #param event
* #param context
* #return
*/
#Override
public String handleRequest(SQSEvent event, Context context) {
return initDataDownloaderService(event, context);
}
/**
* initialize application context and Data downloader service
*
* #param event
* #param context
* #return
*/
private String initDataDownloaderService(SQSEvent event, Context context) {
if (applicationContext == null) {
applicationContext = SpringApplication.run(DataDownloaderService.class);
}
context.getLogger().log("Input: " + event);
if (!event.getRecords().isEmpty()) {
SQSEvent.SQSMessage firstRecord = event.getRecords().get(0);
String eventBody = firstRecord.getBody();
if (eventBody != null) {
ProductDownloadService productDownloadService = applicationContext.getBean(ProductDownloadServiceImpl.class);
try {
productDownloadService.downloadProductData(JsonUtil.getUserInfo(eventBody));
return "Successfully processed";
} catch (IOException e) {
return "Error in data downloading: " + e.getMessage();
}
}
}
return "Data download not success";
}
}

Related

Camunda does not contain any history

I have a problem that whenever I create a process instance in Camunda Process Service, it does not write anything to ACT_HI_OP_LOG. I am not sure why it is not saving the histories into database.
#Component
#Order(Ordering.DEFAULT_ORDER + 1)
public class ProcessEngineConfiguration implements ProcessEnginePlugin {
private String tenantId;
#Override
public void preInit(ProcessEngineConfigurationImpl processEngineConfiguration) {
HistoryLevel historyLevel = new HistoryLevelFull();
processEngineConfiguration.setHistoryLevel(historyLevel);
processEngineConfiguration.setTenantCheckEnabled(true);
// processEngineConfiguration.setHistory(org.camunda.bpm.engine.ProcessEngineConfiguration.HISTORY_FULL);
processEngineConfiguration.setTenantIdProvider(new TenantIdProvider() {
#Override
public String provideTenantIdForProcessInstance(TenantIdProviderProcessInstanceContext ctx) {
return tenantId;
}
#Override
public String provideTenantIdForHistoricDecisionInstance(TenantIdProviderHistoricDecisionInstanceContext ctx) {
return tenantId;
}
#Override
public String provideTenantIdForCaseInstance(TenantIdProviderCaseInstanceContext ctx) {
return tenantId;
}
});
processEngineConfiguration.setJobExecutor(processEngineConfiguration.getJobExecutor());
}
This is how I start the process.
ProcessInstance pi = null;
try {
identityService.setAuthentication(getAuthentication());
pi = runtimeService.startProcessInstanceByKey(flowName, businessKey, variables);
} finally {
identityService.setAuthentication(null);
}
if (pi == null)
return null;
Did you check configuration?
historyLevelCheckEnabled default value is true.
Can you try to set that value false.
If you set that false, this check would not be performed.

How to create simple okhttp3 websocket connection?

Can someone please show me an example on how to establish the connection to the wss:// address with specific Authorization header, using okhttp3 okhttp-ws library?
All I have is the url of WS server and Authorization string token.
Later, I must be able to send request to that connection, listen to upcoming data from WS server and than close connection. I have a difficulties with this new to me WS world, always been working only with REST (with okhttp3 too)
So generally this sample is most of what you need
https://github.com/square/okhttp/blob/master/samples/guide/src/main/java/okhttp3/recipes/WebSocketEcho.java
But you will have two changes
Use wss instead of ws in your URL
Call request.addHeader to add your token
request.addHeader("Authorization", "Bearer " + token)
I know this is an old question, but when I try to use websocket with okhttp3 there are a lot of options that I want and it was not in the library. So I create a class that handle WS connection with extra functionalities. I hope it will help some body. Gist link
import android.os.Handler;
import android.os.Looper;
import android.support.annotation.NonNull;
import android.util.Log;
import org.json.JSONException;
import org.json.JSONObject;
import java.net.ProtocolException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.WebSocket;
import okhttp3.WebSocketListener;
import okhttp3.internal.ws.RealWebSocket;
import okhttp3.logging.HttpLoggingInterceptor;
import okio.ByteString;
/**
* Websocket class based on OkHttp3 with {event->data} message format to make your life easier.
*
* #author Ali Yusuf
* #since 3/13/17
*/
public class Socket {
private final static String TAG = Socket.class.getSimpleName();
private final static String CLOSE_REASON = "End of session";
private final static int MAX_COLLISION = 7;
public final static String EVENT_OPEN = "open";
public final static String EVENT_RECONNECT_ATTEMPT = "reconnecting";
public final static String EVENT_CLOSED = "closed";
/**
* Main socket states
*/
public enum State {
CLOSED, CLOSING, CONNECT_ERROR, RECONNECT_ATTEMPT, RECONNECTING, OPENING, OPEN
}
private static HttpLoggingInterceptor logging =
new HttpLoggingInterceptor()
.setLevel(BuildConfig.DEBUG ? HttpLoggingInterceptor.Level.HEADERS : HttpLoggingInterceptor.Level.NONE);
private static OkHttpClient.Builder httpClient =
new OkHttpClient.Builder()
.addInterceptor(logging);
public static class Builder {
private Request.Builder request;
private Builder(Request.Builder request) {
this.request = request;
}
public static Builder with(#NonNull String url) {
// Silently replace web socket URLs with HTTP URLs.
if (!url.regionMatches(true, 0, "ws:", 0, 3) && !url.regionMatches(true, 0, "wss:", 0, 4))
throw new IllegalArgumentException("web socket url must start with ws or wss, passed url is " + url);
return new Builder(new Request.Builder().url(url));
}
public Builder setPingInterval(long interval, #NonNull TimeUnit unit){
httpClient.pingInterval(interval, unit);
return this;
}
public Builder addHeader(#NonNull String name, #NonNull String value) {
request.addHeader(name, value);
return this;
}
public Socket build() {
return new Socket(request.build());
}
}
/**
* Websocket state
*/
private static State state;
/**
* Websocket main request
*/
private static Request request;
/**
* Websocket connection
*/
private static RealWebSocket realWebSocket;
/**
* Reconnection post delayed handler
*/
private static Handler delayedReconnection;
/**
* Websocket events listeners
*/
private static Map<String,OnEventListener> eventListener;
/**
* Websocket events new message listeners
*/
private static Map<String,OnEventResponseListener> eventResponseListener;
/**
* Message list tobe send onEvent open {#link State#OPEN} connection state
*/
private static Map<String,String> onOpenMessageQueue = new HashMap<>();
/**
* Websocket state change listener
*/
private static OnStateChangeListener onChangeStateListener;
/**
* Websocket new message listener
*/
private static OnMessageListener messageListener;
/**
* Number of reconnection attempts
*/
private static int reconnectionAttempts;
private static boolean skipOnFailure;
private Socket(Request request) {
Socket.request = request;
state = State.CLOSED;
eventListener = new HashMap<>();
eventResponseListener = new HashMap<>();
delayedReconnection = new Handler(Looper.getMainLooper());
skipOnFailure = false;
}
/**
* Start socket connection if i's not already started
*/
public Socket connect() {
if (httpClient == null) {
throw new IllegalStateException("Make sure to use Socket.Builder before using Socket#connect.");
}
if (realWebSocket == null) {
realWebSocket = (RealWebSocket) httpClient.build().newWebSocket(request, webSocketListener);
changeState(State.OPENING);
} else if (state == State.CLOSED) {
realWebSocket.connect(httpClient.build());
changeState(State.OPENING);
}
return this;
}
/**
* Set listener which fired every time message received with contained data.
*
* #param listener message on arrive listener
*/
public Socket onEvent(#NonNull String event, #NonNull OnEventListener listener){
eventListener.put(event,listener);
return this;
}
/**
* Set listener which fired every time message received with contained data.
*
* #param listener message on arrive listener
*/
public Socket onEventResponse(#NonNull String event, #NonNull OnEventResponseListener listener){
eventResponseListener.put(event,listener);
return this;
}
/**
* Send message in {event->data} format
*
* #param event event name that you want sent message to
* #param data message data in JSON format
* #return true if the message send/on socket send quest; false otherwise
*/
public boolean send(#NonNull String event, #NonNull String data){
try {
JSONObject text = new JSONObject();
text.put("event", event);
text.put("data", new JSONObject(data));
Log.v(TAG,"Try to send data "+text.toString());
return realWebSocket.send(text.toString());
} catch (JSONException e) {
Log.e(TAG,"Try to send data with wrong JSON format, data: "+data);
}
return false;
}
/**
* Set state listener which fired every time {#link Socket#state} changed.
*
* #param listener state change listener
*/
public Socket setOnChangeStateListener(#NonNull OnStateChangeListener listener) {
onChangeStateListener = listener;
return this;
}
/**
* Message listener will be called in any message received even if it's not
* in a {event -> data} format.
*
* #param listener message listener
*/
public Socket setMessageListener(#NonNull OnMessageListener listener) {
messageListener = listener;
return this;
}
public void removeEventListener(#NonNull String event) {
eventListener.remove(event);
onOpenMessageQueue.remove(event);
}
/**
* Clear all socket listeners in one line
*/
public void clearListeners() {
eventListener.clear();
messageListener = null;
onChangeStateListener = null;
}
/**
* Send normal close request to the host
*/
public void close() {
if (realWebSocket != null) {
realWebSocket.close(1000, CLOSE_REASON);
}
}
/**
* Send close request to the host
*/
public void close(int code, #NonNull String reason) {
if (realWebSocket != null) {
realWebSocket.close(code, reason);
}
}
/**
* Terminate the socket connection permanently
*/
public void terminate() {
skipOnFailure = true; // skip onFailure callback
if (realWebSocket != null) {
realWebSocket.cancel(); // close connection
realWebSocket = null; // clear socket object
}
}
/**
* Add message in a queue if the socket not open and send them
* if the socket opened
*
* #param event event name that you want sent message to
* #param data message data in JSON format
*/
public void sendOnOpen(#NonNull String event, #NonNull String data) {
if (state != State.OPEN)
onOpenMessageQueue.put(event,data);
else
send(event,data);
}
/**
* Retrieve current socket connection state {#link State}
*/
public State getState() {
return state;
}
/**
* Change current state and call listener method with new state
* {#link OnStateChangeListener#onChange(Socket, State)}
* #param newState new state
*/
private void changeState(State newState) {
state = newState;
if (onChangeStateListener != null) {
onChangeStateListener.onChange(Socket.this, state);
}
}
/**
* Try to reconnect to the websocket after delay time using <i>Exponential backoff</i> method.
* #see
*/
private void reconnect() {
if (state != State.CONNECT_ERROR) // connection not closed !!
return;
changeState(State.RECONNECT_ATTEMPT);
if (realWebSocket != null) {
// Cancel websocket connection
realWebSocket.cancel();
// Clear websocket object
realWebSocket = null;
}
if (eventListener.get(EVENT_RECONNECT_ATTEMPT) != null) {
eventListener.get(EVENT_RECONNECT_ATTEMPT).onMessage(Socket.this, EVENT_RECONNECT_ATTEMPT);
}
// Calculate delay time
int collision = reconnectionAttempts > MAX_COLLISION ? MAX_COLLISION : reconnectionAttempts;
long delayTime = Math.round((Math.pow(2, collision)-1)/2) * 1000;
// Remove any pending posts of callbacks
delayedReconnection.removeCallbacksAndMessages(null);
// Start new post delay
delayedReconnection.postDelayed(new Runnable() {
#Override
public void run() {
changeState(State.RECONNECTING);
reconnectionAttempts++; // Increment connections attempts
connect(); // Establish new connection
}
}, delayTime);
}
private WebSocketListener webSocketListener = new WebSocketListener() {
#Override
public void onOpen(WebSocket webSocket, Response response) {
Log.v(TAG,"Socket has been opened successfully.");
// reset connections attempts counter
reconnectionAttempts = 0;
// fire open event listener
if (eventListener.get(EVENT_OPEN) != null) {
eventListener.get(EVENT_OPEN).onMessage(Socket.this, EVENT_OPEN);
}
// Send data in queue
for (String event : onOpenMessageQueue.keySet()) {
send(event, onOpenMessageQueue.get(event));
}
// clear queue
onOpenMessageQueue.clear();
changeState(State.OPEN);
}
/**
* Accept only Json data with format:
* <b> {"event":"event name","data":{some data ...}} </b>
*/
#Override
public void onMessage(WebSocket webSocket, String text) {
// print received message in log
Log.v(TAG, "New Message received "+text);
// call message listener
if (messageListener != null)
messageListener.onMessage(Socket.this, text);
try {
// Parse message text
JSONObject response = new JSONObject(text);
String event = response.getString("event");
JSONObject data = response.getJSONObject("data");
// call event listener with received data
if (eventResponseListener.get(event) != null) {
eventResponseListener.get(event).onMessage(Socket.this, event, data);
}
// call event listener
if (eventListener.get(event) != null) {
eventListener.get(event).onMessage(Socket.this, event);
}
} catch (JSONException e) {
// Message text not in JSON format or don't have {event}|{data} object
Log.e(TAG, "Unknown message format.");
}
}
#Override
public void onMessage(WebSocket webSocket, ByteString bytes) {
// TODO: some action
}
#Override
public void onClosing(WebSocket webSocket, int code, String reason) {
Log.v(TAG,"Close request from server with reason '"+reason+"'");
changeState(State.CLOSING);
webSocket.close(1000,reason);
}
#Override
public void onClosed(WebSocket webSocket, int code, String reason) {
Log.v(TAG,"Socket connection closed with reason '"+reason+"'");
changeState(State.CLOSED);
if (eventListener.get(EVENT_CLOSED) != null) {
eventListener.get(EVENT_CLOSED).onMessage(Socket.this, EVENT_CLOSED);
}
}
/**
* This method call if:
* - Fail to verify websocket GET request => Throwable {#link ProtocolException}
* - Can't establish websocket connection after upgrade GET request => response null, Throwable {#link Exception}
* - First GET request had been failed => response null, Throwable {#link java.io.IOException}
* - Fail to send Ping => response null, Throwable {#link java.io.IOException}
* - Fail to send data frame => response null, Throwable {#link java.io.IOException}
* - Fail to read data frame => response null, Throwable {#link java.io.IOException}
*/
#Override
public void onFailure(WebSocket webSocket, Throwable t, Response response) {
if (!skipOnFailure) {
skipOnFailure = false; // reset flag
Log.v(TAG, "Socket connection fail, try to reconnect. (" + reconnectionAttempts + ")");
changeState(State.CONNECT_ERROR);
reconnect();
}
}
};
public abstract static class OnMessageListener {
public abstract void onMessage (String data);
/**
* Method called from socket to execute listener implemented in
* {#link #onMessage(String)} on main thread
*
* #param socket Socket that receive the message
* #param data Data string received
*/
private void onMessage (Socket socket, final String data) {
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
onMessage(data);
}
});
}
}
public abstract static class OnEventListener {
public abstract void onMessage (String event);
private void onMessage (Socket socket, final String event) {
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
onMessage(event);
}
});
}
}
public abstract static class OnEventResponseListener extends OnEventListener {
/**
* Method need to override in listener usage
*/
public abstract void onMessage (String event, String data);
/**
* Just override the inherited method
*/
#Override
public void onMessage(String event) {}
/**
* Method called from socket to execute listener implemented in
* {#link #onMessage(String, String)} on main thread
*
* #param socket Socket that receive the message
* #param event Message received event
* #param data Data received in the message
*/
private void onMessage (Socket socket, final String event, final JSONObject data) {
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
onMessage(event, data.toString());
onMessage(event);
}
});
}
}
public abstract static class OnStateChangeListener {
/**
* Method need to override in listener usage
*/
public abstract void onChange (State status);
/**
* Method called from socket to execute listener implemented in
* {#link #onChange(State)} on main thread
*
* #param socket Socket that receive the message
* #param status new status
*/
private void onChange (Socket socket, final State status){
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
onChange(status);
}
});
}
}
}
Usage example:
Socket socket = Socket.Builder.with(WEBSOCKET_BASE_URL).build().connect();
socket.onEvent(Socket.EVENT_OPEN, socketOpenListener);
socket.onEvent(Socket.EVENT_RECONNECT_ATTEMPT, .....);
socket.onEvent(Socket.EVENT_CLOSED, .....);
socket.onEventResponse("Some event", socketPairListener);
socket.send("Some event", "{"some data":"in JSON format"}");
socket.sendOnOpen("Some event", "{"some data":"in JSON format"}");

Interceptors doesn't work in Unit tests

I am get Interceptors working on the application server. I have annotated EJB:
#Stateless
#Named("accountsEJB")
public class AccountsEJB {
#PersistenceContext(unitName = "weducationPU")
private EntityManager em;
// . . . other methods
#WithLog
#Restricted(allowedRoles = {}) // Allowed only for admin
public Account save(Account item) {
if (item.getId() == 0) {
em.persist(item);
return item;
} else {
return em.merge(item);
}
}
#WithLog
#Restricted(allowedRoles = {}) // Allowed only for admin
public void delete(final Account item) {
Account a = em.find(Account.class, item.getId());
if (null != a) {
em.remove(a);
}
}
}
Empty list of roles means, that It's allowed only for role admin.
Here the unit test file for this EJB
public class AccountsEJBTest {
private static EJBContainer container;
private static AccountsEJB ejb;
#BeforeClass
public static void setUpClass() {
try {
Map<String, Object> properties = new HashMap<>();
properties.put(EJBContainer.MODULES, new File("target/classes"));
properties.put("org.glassfish.ejb.embedded.glassfish.installation.root", "glassfish");
properties.put(EJBContainer.APP_NAME, "weducation");
container = EJBContainer.createEJBContainer(properties);
ejb = (AccountsEJB) container.getContext().lookup("java:global/weducation/classes/AccountsEJB");
System.out.println("AccountsEJBTest running...");
} catch (NamingException e) {
fail("Container init error: " + e.getMessage());
}
}
#AfterClass
public static void tearDownClass() {
if (null != container) {
container.close();
}
System.out.println("AccountsEJBTest finished");
}
private boolean equals(Account source, Account result) {
if (!source.getFullName().contentEquals(result.getFullName())) return false;
if (!source.getLogin().contentEquals(result.getLogin())) return false;
return source.getRole() == result.getRole();
}
#Test
public void testOperations() {
try {
System.out.println("-->testOperations()");
Account testAccount = new Account();
testAccount.setFullName("Test Account");
testAccount.setLogin("test");
testAccount.setPassword("test");
testAccount.setConfirm("test");
testAccount.updatePassword();
testAccount.setRole(AccountRole.DEPOT);
Account savedAccount = ejb.save(testAccount);
assertTrue(equals(testAccount, savedAccount));
savedAccount.setFullName("Still Test Account");
savedAccount.setLogin("test1");
testAccount = ejb.save(savedAccount);
assertTrue(equals(testAccount, savedAccount));
testAccount.setPassword("testpwd");
testAccount.setConfirm("testpwd");
testAccount.updatePassword();
savedAccount = ejb.save(testAccount);
assertTrue(equals(testAccount, savedAccount));
ejb.delete(savedAccount);
} catch (Exception e) {
fail("Exception class " + e.getClass().getName() + " with message " + e.getMessage());
}
}
}
And this test working. I think, that is not correct, because there is no user with admin role logged in. But why this behavior happing?
UPDATED.
#Restricted interface:
#Inherited
#InterceptorBinding
#Target({METHOD, TYPE})
#Retention(RUNTIME)
public #interface Restricted {
#Nonbinding
AccountRole[] allowedRoles();
}
SecurityInterceptor class
#Interceptor
#Restricted(allowedRoles = {})
public class SecurityInterceptor implements Serializable {
#Inject
private transient SessionMB session;
#AroundInvoke
public Object checkSecurity(InvocationContext context) throws Exception {
//System.out.println("Security checker started.");
if ((session == null) || (session.getUser() == null)) {
throw new SecurityException("Can't get user info");
}
// Allow all to admin
if (session.isAdmin()) {
//System.out.println("It's admin.");
return context.proceed();
}
// walk non administrator roles
for (AccountRole r : getAllowedRoles(context.getMethod())) {
// if match - accept method invocation
if (session.getUser().getRole() == r) {
//System.out.println("It's " + r.getDescription());
return context.proceed();
}
}
throw new SecurityException(session.getUser().getFullName()
+ " has no souch privilegies ");
}
private AccountRole[] getAllowedRoles(Method m) {
if (null == m) {
throw new IllegalArgumentException("Method is null!");
}
// Walk all method annotations
for (Annotation a : m.getAnnotations()) {
if (a instanceof Restricted) {
return ((Restricted) a).allowedRoles();
}
}
// Now - walk all class annotations
if (null != m.getDeclaringClass()) {
for (Annotation a : m.getDeclaringClass().getAnnotations()) {
if (a instanceof Restricted) {
return ((Restricted) a).allowedRoles();
}
}
}
// if no annotaion found
throw new RuntimeException("Annotation #Restricted not found at method "
+ m.getName() + " or it's class.");
}
}
The beans.xml is placed in WEB-INF folder and looks like
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
bean-discovery-mode="annotated">
<interceptors>
<class>ru.edu.pgtk.weducation.interceptors.LogInterceptor</class>
<class>ru.edu.pgtk.weducation.interceptors.SecurityInterceptor</class>
</interceptors>
</beans>
Can someone help me to know:
How to get Interceptors working in Unit tests?
How to start authorized session in Unit tests (log in as admin, for example)?
How to test such operations as creation and deleting account with the different tests (one test for creating, one for deleting)? Is it correct - to test all operations in one test?
Thank you for your time and your questions.

Setting global properties for RTC Jazz Build definition

I have several Build Definitions in RTC/Jazz and i use a variable to set out DB-Release in various Build Definitions
Build-Lib
Build-Server-App
Build-Run-Test-Server
Build-Client-App
Build-Run-Test-Client
and in all Definitions i use the Property DB_SCHEMA,
DB_SCHEMA = 8.1
once we update our DB and use a new Schema i have to set the Build Property up to
DB_SCHEMA = 8.2
now i must update all Build-Definitions... and if i forget one or i misspell something, then my boss gets mad at me - joking, but honestly, i don't want to make mistakes
--> how can i define a global Property that can be used in all Build-Definitions?
I don't see any global property in the help page, so you might consider developing a program:
using the RTC Java API
for each build definition, setting the property to the expected value (as in this thread)
IBuildDefinition definition = (IBuildDefinition) buildDefinition.getWorkingCopy();
definition.setProperty("propertyName","");
definition = buildClient.save(definition, monitor);
Ok VonC here is my solution:
one Part is an RTC-Adapter which handles Connections from and to the RTC base:
(it provides further getter/setters wich are not relevant for this solution - i purged them)
RTC-Adapter
public class RtcAdapter {
//yes i know - having hardcoded user/pass is bad, ignore this - image it's in a property file or set by a popup dialog
private static final String repositoryURI = "https://xxxxxxxxxxxx/ccm";
private static final String userId = "xxxxxxxxxxx";
private static final String password = "xxxxxxxxxx";
private static final String projectAreaName = "xxxxxxxxxx";
private ITeamRepository teamRepository = null;
private IProgressMonitor monitor = new NullProgressMonitor();
private IProjectArea projectArea = null;
private ITeamBuildClient buildClient = null;
//i'm implementing a singleton class - you can argue with mie if it's a good approach
private static final RtcAdapter inst = new RtcAdapter();
private RtcAdapter(){
super();
}
public ITeamRepository getTeamRepository() {
return teamRepository;
}
public IProgressMonitor getMonitor() {
return monitor;
}
public IProjectArea getProjctArea(){
return projectArea;
}
public ITeamBuildClient getBuildClient(){
return buildClient;
}
private void setTeamRepository(ITeamRepository teamRepositoryIn) {
teamRepository = teamRepositoryIn;
}
/**
*
* #param repositoryURI
* #param userId
* #param password
* #param monitor
* #return
* #throws TeamRepositoryException
*/
private ITeamRepository login(String repositoryURI, String userId,String password, IProgressMonitor monitor) throws TeamRepositoryException {
ITeamRepository teamRepository = TeamPlatform.getTeamRepositoryService().getTeamRepository(repositoryURI);
teamRepository.registerLoginHandler(new LoginHandler(userId, password));
teamRepository.login(monitor);
return teamRepository;
}
/**
* LoginHandler required by login function
*
*/
private static class LoginHandler implements ILoginHandler, ILoginInfo {
private String fUserId;
private String fPassword;
private LoginHandler(String userId, String password) {
fUserId = userId;
fPassword = password;
}
public String getUserId() {
return fUserId;
}
public String getPassword() {
return fPassword;
}
public ILoginInfo challenge(ITeamRepository repository) {
return this;
}
}
public static RtcAdapter inst() {
return inst;
}
public boolean connect() {
TeamPlatform.startup();
System.out.println("Team Platform Startup");
try {
IProgressMonitor monitor = new NullProgressMonitor();
setTeamRepository(login(repositoryURI, userId, password, monitor));
System.out.println("Logged in");
IProcessClientService processClient= (IProcessClientService) getTeamRepository().getClientLibrary(IProcessClientService.class);
URI uri= URI.create(projectAreaName.replaceAll(" ", "%20"));
projectArea = (IProjectArea) processClient.findProcessArea(uri, null, RtcAdapter.inst().getMonitor() );
buildClient = (ITeamBuildClient) getTeamRepository().getClientLibrary(ITeamBuildClient.class);
System.out.println("projet area = "+projectArea.getName() );
} catch (TeamRepositoryException e) {
System.out.println("TeamRepositoryException : " + e.getMessage());
e.printStackTrace();
return false;
} catch (Exception e) {
System.out.println(e.getMessage());
e.printStackTrace();
return false;
}
return true;
}
public void disconnect(){
System.out.println("Logged out");
TeamPlatform.shutdown();
}
}
the other part is the working Class, i called it BuildDefinitionHelper (what a great name, haha)
BuildDefinitionHelper
public class BuildDefinitionHelper {
/**
* #param args
*/
public static void main(String[] args) {
new BuildDefinitionHelper().startUp(); //not-so-nice startup, but i don't mind
}
private final String[] adaPublishDefinitionList = new String[]{
"publish ada develop-40",
"publish ada develop-40 nightly",
"publish ada develop-54",
"publish ada develop-54 nightly",
"publish ada develop-56",
"publish ada develop-56 nightly",
"publish ada develop-58",
"publish ada develop-58 nightly",
};
private final String BUILD_NR = "BUILD_NR";
private final String MAJOR = "MAJOR";
private final String MINOR = "MINOR";
private void startUp() {
final int major = 57;
final int minor = 11;
final int build = 1;
//connect
if (RtcAdapter.inst().connect() ){
//getting required resources - a singleton is helpful here (look above)
IProgressMonitor pMon = RtcAdapter.inst().getMonitor();
ITeamBuildClient buildClient = RtcAdapter.inst().getBuildClient();
try {
for (String adaPublish: adaPublishDefinitionList ){
//get build definition
IBuildDefinition workingCopy = getBuildDefinition(adaPublish, buildClient, pMon);
//seting properties
String propMajor = getFormattededInteger(major);
String propMinor = getFormattededInteger(minor);
String propBuild = getFormattededInteger(build);
setBuildProperty(MAJOR, propMajor, workingCopy);
setBuildProperty(MINOR, propMinor, workingCopy);
setBuildProperty(BUILD_NR, propBuild, workingCopy);
//store changes
saveBuildDefinition(workingCopy, buildClient, pMon);
}
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (TeamRepositoryException e) {
e.printStackTrace();
}
//at the end: disconnect
RtcAdapter.inst().disconnect();
}
}
private void saveBuildDefinition(IBuildDefinition definition, ITeamBuildClient buildClient, IProgressMonitor progressMonitor) throws TeamBuildDuplicateItemException, IllegalArgumentException, TeamRepositoryException {
buildClient.save(definition, progressMonitor);
}
private String getFormattededInteger(int value) {
if (value >= 0 && value <= 9){
return "00"+value;
}
if (value >= 10 && value <= 99){
return "0"+value;
}
return ""+value;
}
private IBuildDefinition getBuildDefinition(String buildDefinitionName, ITeamBuildClient buildClient, IProgressMonitor progressMonitor) throws IllegalArgumentException, TeamRepositoryException {
IBuildDefinition buildDefinition = buildClient.getBuildDefinition(buildDefinitionName, progressMonitor );
IBuildDefinition definition = (IBuildDefinition) buildDefinition.getWorkingCopy();
return definition;
}
private void setBuildProperty(String propertyName, String propertyValue, IBuildDefinition definition ) throws TeamBuildDuplicateItemException, IllegalArgumentException, TeamRepositoryException {
definition.setProperty(propertyName,propertyValue);
System.out.println("set "+propertyName+" to "+ propertyValue+" in Build Definition "+definition.getId() );
}
private void printBuildDefinition(String[] buildDefinitionList, ITeamBuildClient buildClient, IProgressMonitor progressMonitor) throws IllegalArgumentException, TeamRepositoryException {
for (String buildDefinitionName: buildDefinitionList ){
IBuildDefinition buildDefinition = buildClient.getBuildDefinition(buildDefinitionName, progressMonitor );
IBuildDefinition definition = (IBuildDefinition) buildDefinition.getWorkingCopy();
System.out.println("name = "+buildDefinitionName+" definition = "+definition);
}
}
}

uploading file from backberry to web service = JVM error 104 Uncaught NullPointerException?

I am developing a small blackberry project.
Here are the step that it is supposed to be:
User clicks Speak! button. The application record speech voice. [No Problem]
When user finishes speaking, click Stop! button. Once the stop button is clicked, the speech voice will be saved on BB as an AMR file. Then, the file will be sent to web service via ksoap2. Web service will return response as a string of file name. The problem is web service return nothing and there is an error occur: JVM error 104: Uncaught NullPointerException I wonder if I placed the code on the right place, or I did something wrong with ksoap2??
here is the code for web service
namespace VoiceServer
{
/// <summary>
/// Converting AMR to WAV
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
public class Service1 : System.Web.Services.WebService
{
public string UploadFile(String receivedByte, String location, String fileName)
{
String filepath = fileName;
/*don't worry about receivedByte and location, I will work on them after the problem is solved :) */
return "Success"+filepath;
}
private void InitializeComponent()
{
}
}
}
Below is the code running on Eclipse, I'm not sure if I placed the code for sending file to web service on the right place.
public class MyAudio extends MainScreen {
private ButtonField _startRecordingButton;
private ButtonField _stopRecordingButton;
private HorizontalFieldManager _fieldManagerButtons;
private VoiceNotesRecorderThread _voiceRecorder;
private LabelField _myAudioTextField;
private DateField hourMin;
private long _initTime;
public MyAudio() {
_startRecordingButton = new ButtonField("Speak!", ButtonField.CONSUME_CLICK);
_stopRecordingButton = new ButtonField("Stop!", ButtonField.CONSUME_CLICK);
_fieldManagerButtons = new HorizontalFieldManager();
_voiceRecorder = new VoiceNotesRecorderThread(500000,"file:///store/home/user/voicefile.amr",this);
_voiceRecorder.start();
myButtonFieldChangeListener buttonFieldChangeListener = new myButtonFieldChangeListener();
_startRecordingButton.setChangeListener(buttonFieldChangeListener);
_stopRecordingButton.setChangeListener(buttonFieldChangeListener);
_fieldManagerButtons.add(_startRecordingButton);
_fieldManagerButtons.add(_stopRecordingButton);
_myAudioTextField = new LabelField(" Welcome to VoiceSMS!!!" );
add(_fieldManagerButtons);
add(_myAudioTextField);
SimpleDateFormat sdF = new SimpleDateFormat("ss");
hourMin = new DateField("", 0, sdF);
hourMin.setEditable(false);
hourMin.select(false);
_initTime = System.currentTimeMillis();
add(hourMin);
}
public void setAudioTextField(String text) {
_myAudioTextField.setText(text);
}
public void startTime() {
_initTime = System.currentTimeMillis();
hourMin.setDate(0);
}
public void updateTime() {
hourMin.setDate((System.currentTimeMillis()-_initTime));
}
class myButtonFieldChangeListener implements FieldChangeListener{
public void fieldChanged(Field field, int context) {
if(field == _startRecordingButton) {
try {
_voiceRecorder.startRecording();
} catch (IOException e) {
e.printStackTrace();
}
}else if(field == _stopRecordingButton) {
_voiceRecorder.stopRecording();
//----------Send AMR to Web Service-------------//
Object response = null;
String URL = "http://http://localhost:portnumber/Service1.asmx";
String method = "UploadFile";
String NameSpace = "http://tempuri.org/";
FileConnection fc = null;
byte [] ary = null;
try
{
fc = (FileConnection)Connector.open("file:///store/home/user/voicefile.amr",Connector.READ_WRITE);
int size = (int) fc.fileSize();
//String a = Integer.toString(size);
//Dialog.alert(a);
ary = new byte[size];
fc.openDataInputStream().read(ary);
fc.close();
}
catch (IOException e1)
{
e1.printStackTrace();
}
SoapObject client = new SoapObject(NameSpace,method);
client.addProperty("receivedByte",new SoapPrimitive(SoapEnvelope.ENC,"base64",Base64.encode(ary)));
client.addProperty("location","Test/");
client.addProperty("fileName","file:///store/home/user/voicefile.amr");
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.bodyOut = client;
HttpTransport http = new HttpTransport(URL);
try
{
http.call(method,envelope);
}
catch(InterruptedIOException io)
{
io.printStackTrace();
}
catch (IOException e)
{
System.err.println(e);
}
catch (XmlPullParserException e)
{
System.err.println(e);
}
catch(OutOfMemoryError e)
{
System.out.println(e.getMessage());
}
catch(Exception e)
{
e.printStackTrace();
}
try
{
response = envelope.getResponse();
Dialog.alert(response.toString());
}
catch (SoapFault e)
{
System.err.println(e);
System.out.println("Soap Fault");
}
catch(NullPointerException ne)
{
System.err.println(ne);
}
Dialog.alert(response.toString());
//Dialog.alert("Send Success");
//----------End of Upload-to-Web-Service--------//
}
}
}
}
I don't know if the file is not sent to web service, or web service has got the file and produce no response??? I am a real newbie for BB programming. Please let me know if I did anything wrong.
Thanks in advance!!!
There is a typo in your URL variable value.
"http://" typed twice
String URL = "http://http://localhost:portnumber/Service1.asmx";
Hooray!!! Problem Solved!
just changed URL as Rafael suggested and added [WebMethod] above "public string UploadFile" in the web service code